blob: 11544096742b8ab41f564df1da0d9339e40c8a8b [file] [log] [blame]
/*
*
* 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