| /* | 
 |  * | 
 |  *    Copyright (c) 2020 Project CHIP Authors | 
 |  *    Copyright (c) 2016-2017 Nest Labs, Inc. | 
 |  * | 
 |  *    Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  *    you may not use this file except in compliance with the License. | 
 |  *    You may obtain a copy of the License at | 
 |  * | 
 |  *        http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  *    Unless required by applicable law or agreed to in writing, software | 
 |  *    distributed under the License is distributed on an "AS IS" BASIS, | 
 |  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  *    See the License for the specific language governing permissions and | 
 |  *    limitations under the License. | 
 |  */ | 
 |  | 
 | #include <system/SystemConfig.h> | 
 |  | 
 | /** | 
 |  *    @file | 
 |  *      Implementation of the fault-injection utilities for CHIP System Layer. | 
 |  */ | 
 | /* module header, also carries config, comes first */ | 
 | #include <system/SystemFaultInjection.h> | 
 |  | 
 | #include <string.h> | 
 |  | 
 | namespace chip { | 
 | namespace System { | 
 | namespace FaultInjection { | 
 |  | 
 | using nl::FaultInjection::Manager; | 
 | using nl::FaultInjection::Name; | 
 | using nl::FaultInjection::Record; | 
 |  | 
 | static Record sFaultRecordArray[kFault_NumberOfFaultIdentifiers]; | 
 | static Manager sManager; | 
 | static int32_t sFault_AsyncEvent_Arguments[1]; | 
 | static const Name sManagerName  = "CHIPSys"; | 
 | static const Name sFaultNames[] = { | 
 |     "PacketBufferNew", | 
 |     "TimeoutImmediate", | 
 |     "AsyncEvent", | 
 | }; | 
 |  | 
 | static int32_t (*sGetNumEventsAvailable)(); | 
 | static void (*sInjectAsyncEvent)(int32_t index); | 
 |  | 
 | Manager & GetManager() | 
 | { | 
 |     if (0 == sManager.GetNumFaults()) | 
 |     { | 
 |         sManager.Init(kFault_NumberOfFaultIdentifiers, sFaultRecordArray, sManagerName, sFaultNames); | 
 |  | 
 |         memset(&sFault_AsyncEvent_Arguments, 0, sizeof(sFault_AsyncEvent_Arguments)); | 
 |         sFaultRecordArray[kFault_AsyncEvent].mArguments = sFault_AsyncEvent_Arguments; | 
 |         sFaultRecordArray[kFault_AsyncEvent].mLengthOfArguments = | 
 |             static_cast<uint16_t>(sizeof(sFault_AsyncEvent_Arguments) / sizeof(sFault_AsyncEvent_Arguments[0])); | 
 |     } | 
 |  | 
 |     return sManager; | 
 | } | 
 |  | 
 | void InjectAsyncEvent() | 
 | { | 
 |     int32_t numEventsAvailable               = 0; | 
 |     chip::System::FaultInjection::Id faultID = kFault_AsyncEvent; | 
 |  | 
 |     if (sGetNumEventsAvailable) | 
 |     { | 
 |         numEventsAvailable = sGetNumEventsAvailable(); | 
 |  | 
 |         if (numEventsAvailable) | 
 |         { | 
 |             FaultInjection::Manager & mgr         = chip::System::FaultInjection::GetManager(); | 
 |             const FaultInjection::Record * record = &(mgr.GetFaultRecords()[faultID]); | 
 |  | 
 |             if (record->mNumArguments == 0) | 
 |             { | 
 |                 int32_t maxEventIndex = numEventsAvailable - 1; | 
 |  | 
 |                 mgr.StoreArgsAtFault(faultID, 1, &maxEventIndex); | 
 |             } | 
 |  | 
 |             nlFAULT_INJECT_WITH_ARGS( | 
 |                 mgr, faultID, | 
 |                 // Code executed with the Manager's lock: | 
 |                 int32_t index = 0; | 
 |                 if (numFaultArgs > 0) { index = faultArgs[0]; }, | 
 |                 // Code executed without the Manager's lock: | 
 |                 if (sInjectAsyncEvent) { sInjectAsyncEvent(index); }); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | void SetAsyncEventCallbacks(int32_t (*aGetNumEventsAvailable)(), void (*aInjectAsyncEvent)(int32_t index)) | 
 | { | 
 |     sGetNumEventsAvailable = aGetNumEventsAvailable; | 
 |     sInjectAsyncEvent      = aInjectAsyncEvent; | 
 | } | 
 |  | 
 | } // namespace FaultInjection | 
 | } // namespace System | 
 | } // namespace chip |