3 * Copyright 2016-2017 The nlfaultinjection Authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 * This file implements unit tests for FaultInjection.{h,cpp}
28 #include <nlunit-test.h>
29 #include <nlfaultinjection.hpp>
31 using namespace nl::FaultInjection;
34 * The list of fault IDs
38 kTestFaultInjectionID_A,
39 kTestFaultInjectionID_B,
40 kTestFaultInjectionID_NumItems,
42 } TestFaultInjectionID;
44 static const char *sFaultNames[kTestFaultInjectionID_NumItems] = {
49 static const char *sManagerName = "TestFaultMgr";
52 * Storage for the FaultInjectionManager
54 static Record sFaultRecordArray[kTestFaultInjectionID_NumItems];
56 static int32_t sFaultAArguments[4];
62 static class Manager sTestFaultInMgr;
64 static int sNumTimesRebooted = 0;
70 static int sNumTimesPrinted = 0;
71 void PostInjectionCB(Manager *aManager, Identifier aId, Record *aFaultRecord)
74 printf("PostInjectionCB: %s, fault %d - %s, numTimesChecked: %u\n",
75 aManager->GetName(), aId, aManager->GetFaultNames()[aId], aFaultRecord->mNumTimesChecked);
78 static GlobalContext sGlobalContext = {
86 * Getter for the manager object
88 static Manager &GetTestFIMgr(void)
90 if (0 == sTestFaultInMgr.GetNumFaults())
92 sTestFaultInMgr.Init(kTestFaultInjectionID_NumItems, sFaultRecordArray, sManagerName, sFaultNames);
93 memset(&sFaultAArguments, 0, sizeof(sFaultAArguments));
94 sFaultRecordArray[kTestFaultInjectionID_A].mArguments = sFaultAArguments;
95 sFaultRecordArray[kTestFaultInjectionID_A].mLengthOfArguments =
96 static_cast<uint8_t>(sizeof(sFaultAArguments)/sizeof(sFaultAArguments[0]));
98 return sTestFaultInMgr;
101 static int sLockCounter = 0;
102 static nlTestSuite *sSuite;
103 void TestLock(void *inLockContext)
105 int *counter = static_cast<int *>(inLockContext);
107 NL_TEST_ASSERT(sSuite, *counter == 0);
112 void TestUnlock(void *inLockContext)
114 int *counter = static_cast<int *>(inLockContext);
116 NL_TEST_ASSERT(sSuite, *counter == 1);
121 #define TEST_FAULT_INJECT( aId, aStatements ) \
122 nlFAULT_INJECT(GetTestFIMgr(), aId, aStatements)
124 #define TEST_FAULT_INJECT_WITH_ARGS( aId, aProtectedStatements, aUnprotectedStatements ) \
125 nlFAULT_INJECT_WITH_ARGS(GetTestFIMgr(), aId, aProtectedStatements, aUnprotectedStatements )
131 // Show that we can compile in a whole block; the simplest form is:
132 // TEST_FAULT_INJECT(kTestFaultInjectionID_A, retval = true);
134 TEST_FAULT_INJECT(kTestFaultInjectionID_A,
145 static int DoAWithArgs()
149 // Show that we can access the arguments saved in the Record
151 TEST_FAULT_INJECT_WITH_ARGS(kTestFaultInjectionID_A,
154 for (i = 0; i < numFaultArgs; i++)
156 printf("arg %d: %d\n", i, faultArgs[i]);
157 retval += faultArgs[i];
161 printf("printing without the lock: counter: %d\n", sLockCounter);
162 NL_TEST_ASSERT(sSuite, sLockCounter == 0);
168 static int DoAExportingArgs()
172 // Show that we can save arguments in the Record from the fault injection
173 // location as a way to export them to the test harness
176 // Usually this block would be implemented with a macro
178 nl::FaultInjection::Manager &mgr = GetTestFIMgr();
179 const nl::FaultInjection::Record *records = mgr.GetFaultRecords();
181 // Check for existing arguments to tell if the harness has
182 // installed arguments already, not to override them.
183 if (records[kTestFaultInjectionID_A].mNumArguments == 0)
185 // Assuming this fault id takes two arguments, lets save 4 values,
186 // as to tell the harness that there are two interesting test cases here
187 // The application developer needs to reserve enough space in
188 // records[kTestFaultInjectionID_A].mArguments
189 int32_t args[] = { 1, 2, 10, 20 };
190 uint16_t numArgs = 4;
191 mgr.StoreArgsAtFault(kTestFaultInjectionID_A, numArgs, args);
195 TEST_FAULT_INJECT_WITH_ARGS(kTestFaultInjectionID_A,
198 for (i = 0; i < numFaultArgs; i++)
200 printf("arg %d: %d\n", i, faultArgs[i]);
201 retval += faultArgs[i];
205 printf("printing without the lock: counter: %d\n", sLockCounter);
206 NL_TEST_ASSERT(sSuite, sLockCounter == 0);
212 * This test uses three callbacks; they are stored in an array so
213 * the test can iterate over them
220 * Array of counters, one per callback
222 static int sCbFnCalled[kNumCallbacks];
225 * Array or values to be returned by the callbacks
227 static bool sCbFnRetval[kNumCallbacks];
230 * Whether callbacks should remove themself
232 static bool sCbRemoveItself[kNumCallbacks];
235 * Boolean to tell callback 0 to enable the second fault
237 static bool sTriggerFault2;
239 static bool cbFn0(Identifier aFaultID, Record *aFaultRecord, void *aContext);
240 static bool cbFn1(Identifier aFaultID, Record *aFaultRecord, void *aContext);
241 static bool cbFn2(Identifier aFaultID, Record *aFaultRecord, void *aContext);
243 static Callback sCb[kNumCallbacks] = { { cbFn0, NULL, NULL }, { cbFn1, NULL, NULL }, { cbFn2, NULL, NULL } };
245 static bool cbFn0(Identifier aFaultID, Record *aFaultRecord, void *aContext)
251 Manager fMgr = GetTestFIMgr();
257 (void)fMgr.FailAtFault(kTestFaultInjectionID_B, 0, 1, Manager::kMutexDoNotTake);
260 if (sCbRemoveItself[0])
262 (void)fMgr.RemoveCallbackAtFault(aFaultID, &sCb[0], Manager::kMutexDoNotTake);
266 return sCbFnRetval[0];
269 static bool cbFn1(Identifier aFaultID, Record *aFaultRecord, void *aContext)
276 return sCbFnRetval[1];
278 static bool cbFn2(Identifier aFaultID, Record *aFaultRecord, void *aContext)
285 return sCbFnRetval[2];
288 static nl::FaultInjection::Callback sHarvestArgsID_ACb;
289 static bool cbToHarvestArgs(Identifier aFaultID, Record *aFaultRecord, void *aContext)
291 nl::FaultInjection::Manager &mgr = GetTestFIMgr();
292 const char *faultName = mgr.GetFaultNames()[aFaultID];
295 if (aFaultID == kTestFaultInjectionID_A)
297 uint16_t numArgs = aFaultRecord->mNumArguments;
303 // The harness can grep for strings like this and find the test cases to run
304 // in subsequent executions
305 printf("Found test case: %s_%s_s%u_a%u_a%u;\n", mgr.GetName(), faultName, aFaultRecord->mNumTimesChecked,
306 aFaultRecord->mArguments[i], aFaultRecord->mArguments[i+1]);
310 // also just copy the array out for the sake of this test
311 int32_t *output = static_cast<int32_t *>(aContext);
312 memcpy(output, aFaultRecord->mArguments, aFaultRecord->mNumArguments * sizeof(aFaultRecord->mArguments[0]));
316 // This callback never triggers the fault
324 void TestFailAtFault(nlTestSuite *inSuite, void *inContext)
327 Manager &fMgr = GetTestFIMgr();
329 nl::FaultInjection::Identifier id;
331 uint32_t maxTimesToFail = 10;
332 uint32_t maxTimesToSkip = 10;
333 uint32_t timesToFail = 0;
334 uint32_t timesToSkip = 0;
340 // fMgr is a singleton, get it twice
341 fMgr = GetTestFIMgr();
343 SetGlobalContext(&sGlobalContext);
345 for (id = 0; id < kTestFaultInjectionID_NumItems; id++)
347 shouldFail = fMgr.CheckFault(id);
348 NL_TEST_ASSERT(inSuite, shouldFail == false);
352 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_NumItems);
353 NL_TEST_ASSERT(inSuite, shouldFail == false);
355 // Test a few combinations of timesToSkip and timesToFail
356 for (timesToFail = 0; timesToFail <= maxTimesToFail; timesToFail++)
358 for (timesToSkip = 0; timesToSkip <= maxTimesToSkip; timesToSkip++)
360 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
361 NL_TEST_ASSERT(inSuite, err == 0);
363 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_B);
364 NL_TEST_ASSERT(inSuite, shouldFail == false);
366 for (i = 0; i < timesToSkip; i++)
368 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
369 NL_TEST_ASSERT(inSuite, shouldFail == false);
372 for (i = 0; i < timesToFail; i++)
374 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
375 NL_TEST_ASSERT(inSuite, shouldFail);
378 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
379 NL_TEST_ASSERT(inSuite, shouldFail == false);
385 * TestRebootAndPrintAtFault
387 void TestRebootAndPrintAtFault(nlTestSuite *inSuite, void *inContext)
390 Manager &fMgr = GetTestFIMgr();
392 uint32_t timesToFail = 1;
393 uint32_t timesToSkip = 0;
399 // fMgr is a singleton, get it twice
400 fMgr = GetTestFIMgr();
402 SetGlobalContext(&sGlobalContext);
404 // Enable logging, to see that it works
405 sNumTimesPrinted = 0;
406 sGlobalContext.mCbTable.mPostInjectionCb = PostInjectionCB;
408 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
409 NL_TEST_ASSERT(inSuite, sNumTimesPrinted == 0);
411 sNumTimesRebooted = 0;
413 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
414 NL_TEST_ASSERT(inSuite, err == 0);
416 err = fMgr.RebootAtFault(kTestFaultInjectionID_NumItems);
417 NL_TEST_ASSERT(inSuite, err == -EINVAL);
419 err = fMgr.RebootAtFault(kTestFaultInjectionID_A);
420 NL_TEST_ASSERT(inSuite, err == 0);
422 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
423 NL_TEST_ASSERT(inSuite, shouldFail == true);
424 NL_TEST_ASSERT(inSuite, sNumTimesRebooted == 1);
425 NL_TEST_ASSERT(inSuite, sNumTimesPrinted == 1);
427 sGlobalContext.mCbTable.mPostInjectionCb = NULL;
433 void TestTheMacro(nlTestSuite *inSuite, void *inContext)
436 Manager &fMgr = GetTestFIMgr();
438 uint32_t timesToSkip = 0;
439 uint32_t timesToFail = 1;
446 NL_TEST_ASSERT(inSuite, failed == false);
448 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
449 NL_TEST_ASSERT(inSuite, err == 0);
452 NL_TEST_ASSERT(inSuite, failed);
458 void TestInsertRemoveCallback(nlTestSuite *inSuite, void *inContext)
461 Manager fMgr = GetTestFIMgr();
469 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_NumItems, &sCb[0]);
470 NL_TEST_ASSERT(inSuite, err == -EINVAL);
472 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, NULL);
473 NL_TEST_ASSERT(inSuite, err == -EINVAL);
475 // Try removing a callback that's not installed
476 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, &sCb[0]);
477 NL_TEST_ASSERT(inSuite, err == 0);
480 err = fMgr.InsertCallbackAtFault(kTestFaultInjectionID_A, &sCb[0]);
481 NL_TEST_ASSERT(inSuite, err == 0);
483 // Add it again, should be a no-op (the callback should be called only once)
484 err = fMgr.InsertCallbackAtFault(kTestFaultInjectionID_A, &sCb[0]);
485 NL_TEST_ASSERT(inSuite, err == 0);
487 // Try removing one that's not installed with a non-empty list
488 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, &sCb[1]);
489 NL_TEST_ASSERT(inSuite, err == 0);
491 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
492 NL_TEST_ASSERT(inSuite, shouldFail == false);
493 NL_TEST_ASSERT(inSuite, sCbFnCalled[0] == 1);
495 NL_TEST_ASSERT(inSuite, sCbFnCalled[1] == 0);
497 // Say the fault is on from the callback
498 sCbFnRetval[0] = true;
499 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
500 NL_TEST_ASSERT(inSuite, shouldFail);
501 sCbFnRetval[0] = false;
503 // Turn on the second fault from the first callback; the first should return false,
504 // and then the second should return true
505 sTriggerFault2 = true;
506 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
507 NL_TEST_ASSERT(inSuite, shouldFail == false);
508 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_B);
509 NL_TEST_ASSERT(inSuite, shouldFail);
512 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, &sCb[0]);
513 NL_TEST_ASSERT(inSuite, err == 0);
516 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
517 NL_TEST_ASSERT(inSuite, shouldFail == false);
518 NL_TEST_ASSERT(inSuite, sCbFnCalled[0] == 0);
520 sTriggerFault2 = false;
522 // Given three callback on the same fault, test removal of the first one, of the
523 // one in the middle and of the last one.
524 // Keep in mind though that the last one is not really the last one of the list:
525 // all lists end in the two default callbacks.
526 for (i = 0; i < kNumCallbacks; i++)
529 for (j = 0; j < kNumCallbacks; j++)
532 err = fMgr.InsertCallbackAtFault(kTestFaultInjectionID_A, &sCb[j]);
533 NL_TEST_ASSERT(inSuite, err == 0);
537 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, &sCb[i]);
538 NL_TEST_ASSERT(inSuite, err == 0);
541 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
542 NL_TEST_ASSERT(inSuite, shouldFail == false);
544 for (j = 0; j < kNumCallbacks; j++)
548 NL_TEST_ASSERT(inSuite, sCbFnCalled[j] == 0);
552 NL_TEST_ASSERT(inSuite, sCbFnCalled[j] == 1);
556 // remove all of them
557 for (j = 0; j < kNumCallbacks; j++)
559 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, &sCb[j]);
560 NL_TEST_ASSERT(inSuite, err == 0);
564 // check that they're all gone
565 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
566 NL_TEST_ASSERT(inSuite, shouldFail == false);
567 for (j = 0; j < kNumCallbacks; j++)
569 NL_TEST_ASSERT(inSuite, sCbFnCalled[j] == 0);
575 * Test a callback that removes itself
577 void TestCallbackRemovesItself(nlTestSuite *inSuite, void *inContext)
580 Manager fMgr = GetTestFIMgr();
587 err = fMgr.InsertCallbackAtFault(kTestFaultInjectionID_A, &sCb[0]);
588 NL_TEST_ASSERT(inSuite, err == 0);
590 sCbRemoveItself[0] = true;
591 sCbFnRetval[0] = true;
593 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
594 NL_TEST_ASSERT(inSuite, shouldFail == true);
596 // Now it returns false, because the callback is gone
597 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
598 NL_TEST_ASSERT(inSuite, shouldFail == false);
600 sCbRemoveItself[0] = false;
601 sCbFnRetval[0] = false;
605 * Test random failures
607 void TestFailRandomly(nlTestSuite *inSuite, void *inContext)
610 Manager fMgr = GetTestFIMgr();
612 uint8_t percentage = 80;
614 int numIterations = 100;
621 err = fMgr.FailRandomlyAtFault(kTestFaultInjectionID_A, percentage);
622 NL_TEST_ASSERT(inSuite, err == 0);
623 for (i = 0; i < numIterations; i++)
625 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
630 printf("numFailures: %d\n", numFailures);
632 // At the time of this writing, I'm getting 75-82 failures out of 100
633 NL_TEST_ASSERT(inSuite, numFailures > (numIterations/2));
637 err = fMgr.FailRandomlyAtFault(kTestFaultInjectionID_A, percentage);
638 NL_TEST_ASSERT(inSuite, err == 0);
639 for (i = 0; i < numIterations; i++)
641 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
646 printf("numFailures: %d\n", numFailures);
648 // At the time of this writing, I'm getting 18-22 failures out of 100
649 NL_TEST_ASSERT(inSuite, numFailures < (numIterations/2));
651 err = fMgr.FailRandomlyAtFault(kTestFaultInjectionID_A, 0);
652 NL_TEST_ASSERT(inSuite, err == 0);
656 * Test StoreArgsAtFault
658 void TestArguments(nlTestSuite *inSuite, void *inContext)
661 Manager fMgr = GetTestFIMgr();
663 uint32_t timesToFail = 1;
664 uint32_t timesToSkip = 0;
665 int32_t args[] = { 42, 24 };
666 uint16_t numArgs = static_cast<uint16_t>(sizeof(args)/sizeof(args[0]));
667 int32_t *outArgs = NULL;
668 uint16_t outNumArgs = 0;
675 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
676 NL_TEST_ASSERT(inSuite, err == 0);
677 err = fMgr.StoreArgsAtFault(kTestFaultInjectionID_A, numArgs, args);
678 NL_TEST_ASSERT(inSuite, err == 0);
679 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A, outNumArgs, outArgs);
680 NL_TEST_ASSERT(inSuite, shouldFail);
681 NL_TEST_ASSERT(inSuite, outNumArgs == numArgs);
682 NL_TEST_ASSERT(inSuite, args[0] == outArgs[0]);
683 NL_TEST_ASSERT(inSuite, args[1] == outArgs[1]);
685 // Now test the handling of arguments in the macro
686 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
687 NL_TEST_ASSERT(inSuite, err == 0);
688 retval = DoAWithArgs();
689 NL_TEST_ASSERT(inSuite, retval == (args[0] + args[1]));
694 * Test ParseFaultInjectionStr
696 void TestParser(nlTestSuite *inSuite, void *inContext)
698 Manager &fMgr = GetTestFIMgr();
701 nl::FaultInjection::Identifier id;
702 nl::FaultInjection::GetManagerFn faultMgrTable[] = {
706 const char *singleConfig = "TestFaultMgr_A_s0_f1";
707 const char *doubleConfig = "TestFaultMgr_A_s0_f1:TestFaultMgr_B_p50";
708 const char *singleConfigWithArgs = "TestFaultMgr_A_s0_f1_a12_a-7";
710 int expectedRetVal = (12 -7);
716 for (id = 0; id < kTestFaultInjectionID_NumItems; id++)
718 shouldFail = fMgr.CheckFault(id);
719 NL_TEST_ASSERT(inSuite, shouldFail == false);
722 strncpy(buffer, singleConfig, sizeof(buffer));
723 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
724 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
725 NL_TEST_ASSERT(inSuite, parserVal == true);
727 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
728 NL_TEST_ASSERT(inSuite, shouldFail == true);
729 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_B);
730 NL_TEST_ASSERT(inSuite, shouldFail == false);
732 strncpy(buffer, doubleConfig, sizeof(buffer));
733 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
734 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
735 NL_TEST_ASSERT(inSuite, parserVal == true);
736 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
737 NL_TEST_ASSERT(inSuite, shouldFail == true);
738 NL_TEST_ASSERT(inSuite, sFaultRecordArray[1].mPercentage == 50);
741 sNumTimesRebooted = 0;
742 singleConfig = "TestFaultMgr_A_s0_f1_r";
743 strncpy(buffer, singleConfig, sizeof(buffer));
744 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
745 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
746 NL_TEST_ASSERT(inSuite, parserVal == true);
747 NL_TEST_ASSERT(inSuite, sFaultRecordArray[0].mReboot == true);
749 /* passing parameters */
750 strncpy(buffer, singleConfigWithArgs, sizeof(buffer));
751 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
752 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
753 NL_TEST_ASSERT(inSuite, parserVal == true);
754 retval = DoAWithArgs();
755 NL_TEST_ASSERT(inSuite, retval == expectedRetVal);
758 singleConfig = "TestFaultMgr_C_s0_f1";
759 doubleConfig = "TestFaultMgr_A_g0_f1:TestFaultMgr_B_r50";
761 strncpy(buffer, singleConfig, sizeof(buffer));
762 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
763 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
764 NL_TEST_ASSERT(inSuite, parserVal == false);
766 strncpy(buffer, doubleConfig, sizeof(buffer));
767 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
768 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
769 NL_TEST_ASSERT(inSuite, parserVal == false);
771 /* Bad percentage values */
772 singleConfig = "TestFaultMgr_A_p101";
773 strncpy(buffer, singleConfig, sizeof(buffer));
774 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
775 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
776 NL_TEST_ASSERT(inSuite, parserVal == false);
778 singleConfig = "TestFaultMgr_A_p-1";
779 strncpy(buffer, singleConfig, sizeof(buffer));
780 parserVal = nl::FaultInjection::ParseFaultInjectionStr(buffer,
781 faultMgrTable, sizeof(faultMgrTable)/sizeof(faultMgrTable[0]));
782 NL_TEST_ASSERT(inSuite, parserVal == false);
786 * Test Exporting argument values to be used in future test runs
788 void TestExportArguments(nlTestSuite *inSuite, void *inContext)
791 Manager fMgr = GetTestFIMgr();
793 int32_t outputContext[4];
799 fMgr.StoreArgsAtFault(kTestFaultInjectionID_A, 0, NULL);
802 * Install a callback to harvest the arguments during a run without
805 memset(&sHarvestArgsID_ACb, 0, sizeof(sHarvestArgsID_ACb));
806 sHarvestArgsID_ACb.mCallBackFn = cbToHarvestArgs;
807 sHarvestArgsID_ACb.mContext = outputContext;
808 fMgr.InsertCallbackAtFault(kTestFaultInjectionID_A, &sHarvestArgsID_ACb);
811 * During a sequence without faults, save useful arguments in the
815 failed = DoAExportingArgs();
816 NL_TEST_ASSERT(inSuite, failed == false);
818 /* Check the right values got exported */
819 NL_TEST_ASSERT(inSuite, outputContext[0] == 1);
820 NL_TEST_ASSERT(inSuite, outputContext[1] == 2);
821 NL_TEST_ASSERT(inSuite, outputContext[2] == 10);
822 NL_TEST_ASSERT(inSuite, outputContext[3] == 20);
824 /* Now a real application would use the values collected above for two more tests */
827 err = fMgr.RemoveCallbackAtFault(kTestFaultInjectionID_A, &sHarvestArgsID_ACb);
828 NL_TEST_ASSERT(inSuite, err == 0);
832 * Test ResetFaultCounters
834 void TestResetFaultCounters(nlTestSuite *inSuite, void *inContext)
837 Manager &fMgr = GetTestFIMgr();
838 nl::FaultInjection::Identifier id = kTestFaultInjectionID_A;
839 uint32_t timesToFail = 2;
840 uint32_t timesToSkip = 2;
848 (void)fMgr.CheckFault(kTestFaultInjectionID_A);
849 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mNumTimesChecked != 0);
851 fMgr.ResetFaultCounters();
852 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mNumTimesChecked == 0);
854 // Now check that resetting the counters does not break the configuration
855 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
856 NL_TEST_ASSERT(inSuite, err == 0);
858 for (i = 0; i < timesToFail + timesToSkip; i++)
860 fMgr.ResetFaultCounters();
861 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mNumTimesChecked == 0);
863 shouldFail = fMgr.CheckFault(kTestFaultInjectionID_A);
866 NL_TEST_ASSERT(inSuite, shouldFail == false);
870 NL_TEST_ASSERT(inSuite, shouldFail == true);
872 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mNumTimesChecked != 0);
877 * Test ResetFaultConfigurations
879 void TestResetFaultConfigurations(nlTestSuite *inSuite, void *inContext)
882 Manager &fMgr = GetTestFIMgr();
883 nl::FaultInjection::Identifier id = kTestFaultInjectionID_A;
884 uint32_t timesToFail = 7;
885 uint32_t timesToSkip = 8;
886 uint8_t percentage = 80;
892 err = fMgr.FailAtFault(kTestFaultInjectionID_A, timesToSkip, timesToFail);
893 NL_TEST_ASSERT(inSuite, err == 0);
895 err = fMgr.ResetFaultConfigurations();
896 NL_TEST_ASSERT(inSuite, err == 0);
897 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mNumCallsToSkip == 0);
898 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mNumCallsToFail == 0);
900 err = fMgr.FailRandomlyAtFault(id, percentage);
901 NL_TEST_ASSERT(inSuite, err == 0);
903 err = fMgr.ResetFaultConfigurations();
904 NL_TEST_ASSERT(inSuite, err == 0);
905 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mPercentage == 0);
907 err = fMgr.InsertCallbackAtFault(id, &sCb[0]);
908 NL_TEST_ASSERT(inSuite, err == 0);
910 err = fMgr.ResetFaultConfigurations();
911 NL_TEST_ASSERT(inSuite, err == 0);
912 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mCallbackList != &sCb[0]);
914 err = fMgr.RebootAtFault(id);
915 NL_TEST_ASSERT(inSuite, err == 0);
917 err = fMgr.ResetFaultConfigurations();
918 NL_TEST_ASSERT(inSuite, err == 0);
919 NL_TEST_ASSERT(inSuite, fMgr.GetFaultRecords()[id].mReboot == false);
923 * Test Suite that lists all the test functions.
925 static const nlTest sTests[] = {
926 NL_TEST_DEF("Test FailAtFault", TestFailAtFault),
927 NL_TEST_DEF("Test RebootAndPrintAtFault", TestRebootAndPrintAtFault),
928 NL_TEST_DEF("Test the macro", TestTheMacro),
929 NL_TEST_DEF("Test InsertRemoveCallback", TestInsertRemoveCallback),
930 NL_TEST_DEF("Test CallbackRemovesItself", TestCallbackRemovesItself),
931 NL_TEST_DEF("Test Random failures", TestFailRandomly),
932 NL_TEST_DEF("Test Parser", TestParser),
933 NL_TEST_DEF("Test Arguments", TestArguments),
934 NL_TEST_DEF("Test Exporting useful arguments", TestExportArguments),
935 NL_TEST_DEF("Test ResetFaultCounters", TestResetFaultCounters),
936 NL_TEST_DEF("Test ResetFaultConfigurations", TestResetFaultConfigurations),
941 * Set up the test suite.
943 static int TestSetup(void *inContext)
951 * Tear down the test suite.
953 static int TestTeardown(void *inContext)
963 int main(int argc, char *argv[])
965 nl::FaultInjection::Manager &mgr = GetTestFIMgr();
969 srand(static_cast<unsigned int>(time(NULL)));
971 nlTestSuite theSuite;
972 memset(&theSuite, 0, sizeof(theSuite));
973 theSuite.name = "fault-injection";
974 theSuite.tests = &sTests[0];
975 theSuite.setup = TestSetup;
976 theSuite.tear_down = TestTeardown;
978 // Set the critical section callbacks once here, instead of in every test
979 mgr.SetLockCallbacks(TestLock, TestUnlock, &sLockCounter);
981 // Generate machine-readable, comma-separated value (CSV) output.
982 nl_test_set_output_style(OUTPUT_CSV);
984 // Run test suit against one context
985 nlTestRunner(&theSuite, NULL);
987 return nlTestRunnerStats(&theSuite);