| /* |
| * |
| * 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 <nlassert.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 |