1 krisbash 1.1 //*****************************************************************************
2 // Copyright (C) 2007 Microsoft Corporation
3 // All rights reserved.
4 //*****************************************************************************
5
6 #include "Run.h"
7 #include <iostream>
8 #ifdef _MSC_VER
9 #include <Switch.tmh>
10 #endif
11 #include <pal/palcommon.h>
12 #include <pal/strings.h>
13
14 using namespace std;
15 using namespace TestSystem;
16
17 #define IsSetupFixture(fixtureType) ((fixtureType == SetupFixture) || (fixtureType == SplitFixture))
18
19 NITS_EXPORT void NITS_CALL NitsSwitchCreate(
20 _Inout_ Switch *test,
21 _In_ const PAL_Char * name,
22 krisbash 1.1 _In_ void (NITS_CALL *setup)(Switch &),
23 bool group)
24 {
25 test->m_name = name;
26 test->m_setup = setup;
27 test->m_cleanup = NULL;
28 test->m_choice = group ? Switch::AllChildren : 0;
29 test->m_index = 0;
30 test->m_refs = 0;
31 test->m_children = new ChildList;
32 test->m_registration = NULL;
33 test->m_prevLayerContinuation = NULL;
34 test->m_sameLayerContinuation = NULL;
35 test->m_prevSwitchOnSelectedTestStack = NULL;
36 test->m_rootSwitch = NULL;
37 test->m_dryRunToFindChildren = 0;
38 test->m_someoneCalledOmit = 0;
39 test->m_filteredOutByUser = 0;
40 test->m_notRunInCurrentTestChoice = 0;
41 test->m_switchState = TestSystem::Switch::NotRunYet;
42
43 krisbash 1.1 if (test->m_children == NULL)
44 {
45 FatalError();
46 }
47 }
48
49 NITS_EXPORT void NITS_CALL NitsSwitchDelete(
50 _Inout_ Switch *test)
51 {
52 struct RegistrationInfo *r = (struct RegistrationInfo *) (test->m_registration);
53 int count = 0;
54 delete test->m_children;
55 if(r)
56 {
57 if(r->arrayOfInitializers)
58 {
59 while(count < r->numberOfParents)
60 {
61 free(r->arrayOfInitializers[count]);
62 count++;
63 }
64 krisbash 1.1 free(r->arrayOfInitializers);
65 }
66
67 if(r->parentArray)
68 {
69 free(r->parentArray);
70 }
71
72 free(r);
73 }
74 }
75
76 NITS_EXPORT void NITS_CALL NitsSetTeardownSwitch(_Inout_ Switch *test, Switch *teardownSwitch, int isCleanup)
77 {
78 if(test->m_registration)
79 {
80 struct RegistrationInfo *r = (struct RegistrationInfo *) (test->m_registration);
81 if(isCleanup)
82 {
83 r->cleanupSwitch = teardownSwitch;
84 }
85 krisbash 1.1 else
86 {
87 r->crashSwitch = teardownSwitch;
88 }
89 }
90 }
91
92 NITS_EXPORT void ** NITS_CALL NitsGetInitArray(_Inout_ Switch *test)
93 {
94 if(!test->IsNewInterfaceTest())
95 return NULL;
96
97 struct RegistrationInfo *r = (struct RegistrationInfo *) (test->m_registration);
98
99 return r->arrayOfInitializers;
100 }
101
102 NITS_EXPORT int NITS_CALL NitsIsSplitFixture(_In_ Switch *test)
103 {
104 if(!test->IsNewInterfaceTest())
105 return 0;
106 krisbash 1.1
107 struct RegistrationInfo *r = (struct RegistrationInfo *) (test->m_registration);
108
109 return (r->fixtureType == SplitFixture);
110 }
111
112 PAL_Boolean Switch::IsBodyFixture()
113 {
114 if(!IsNewInterfaceTest())
115 return PAL_FALSE;
116
117 struct RegistrationInfo *r = (struct RegistrationInfo *) (m_registration);
118
119 return ((r->fixtureType == BodyFixture) || (r->fixtureType == ModuleSetupFixture));
120 }
121
122 bool Switch::IsChildSelected(int index) const
123 {
124 return IsGroup() || index == m_choice;
125 }
126
127 krisbash 1.1 //Registers and runs child switches from setup().
128 //Caller must not change the child sequence when repeating its own variations.
129 NITS_EXPORT void NITS_CALL NitsSwitchChild(
130 _Inout_ Switch *test,
131 _In_ Switch &child)
132 {
133 vector<Switch *> &list = *test->m_children;
134
135 if (test->m_index == list.size())
136 {
137 //Register a new child.
138 list.push_back(&child);
139 }
140 else if (list[test->m_index] != &child)
141 {
142 //Caller previously registered children in a different order!
143 FatalError();
144 }
145
146 if (test->IsChildSelected(test->m_index++))
147 {
148 krisbash 1.1 child.RunSetup();
149 }
150 }
151
152 NITS_EXPORT bool NITS_CALL NitsSwitchGetEnabled(
153 _Inout_ Switch const *test)
154 {
155 PAL_UNUSED(test);
156 return Run::GetInstance().GetEnabled();
157 }
158
159 NITS_EXPORT void NITS_CALL NitsSwitchSetFaultMode(
160 _Inout_ Switch *test,
161 NitsFaultMode mode)
162 {
163 PAL_UNUSED(test);
164
165 Run::GetInstance().SetFaultMode(mode);
166 }
167
168 NITS_EXPORT void NITS_CALL NitsSwitchSetEnabled(
169 krisbash 1.1 _Inout_ Switch *test,
170 bool enabled)
171 {
172 PAL_UNUSED(test);
173
174 Run::GetInstance().SetEnabled(enabled);
175 }
176
177 NITS_EXPORT void NITS_CALL NitsSwitchSetFlaky(
178 _Inout_ Switch *test,
179 bool flaky)
180 {
181 PAL_UNUSED(test);
182
183 Run::GetInstance().SetFlaky(flaky);
184 }
185
186 NITS_EXPORT void NITS_CALL NitsSwitchFaultExclude(
187 _Inout_ Switch *test,
188 _In_reads_opt_(count) int sites[],
189 int count)
190 krisbash 1.1 {
191 PAL_UNUSED(test);
192
193 Run::GetInstance().SetExclusions(sites, count);
194 }
195
196 NITS_EXPORT void NITS_CALL NitsSwitchFaultOff(
197 _Inout_ Switch *test)
198 {
199 PAL_UNUSED(test);
200
201 GetGlobals().SetFault(CallSite_NONE, 0, S_OK, PAL_T(""));
202 }
203
204 NITS_EXPORT void NITS_CALL NitsSwitchFaultHresult(
205 _Inout_ Switch *test,
206 int site,
207 HRESULT error,
208 int attempt)
209 {
210 PAL_UNUSED(test);
211 krisbash 1.1
212 GetGlobals().SetFault(site, attempt, error, PAL_T(""));
213 }
214
215 NITS_EXPORT void NITS_CALL NitsSwitchFaultError(
216 _Inout_ Switch *test,
217 int site,
218 DWORD error,
219 int attempt)
220 {
221 PAL_UNUSED(test);
222
223 GetGlobals().SetFault(site, attempt, HRESULT_FROM_WIN32(error), PAL_T(""));
224 }
225
226 NITS_EXPORT void NITS_CALL NitsSwitchFaultWait(
227 _Inout_ Switch *test,
228 int site,
229 _In_ Event const &event,
230 int attempt)
231 {
232 krisbash 1.1 PAL_UNUSED(test);
233
234 GetGlobals().SetFault(site, attempt, S_OK, event);
235 }
236
237 NITS_EXPORT const PAL_Char *NITS_CALL NitsTestGetParam(_In_z_ const PAL_Char *paramName)
238 {
239 return Run::GetInstance().GetParam(paramName);
240 }
241
242 void Switch::RunSetup()
243 {
244 if (++m_refs > 1)
245 {
246 if (IsChoice())
247 {
248 //Sanity check: choices must NOT have multiple parents.
249 //This causes confusion when choosing children.
250 throw Exception();
251 }
252
253 krisbash 1.1 return;
254 }
255
256 //The setup call registers and calls children through Child().
257 //Child call order is determined by setup.
258 m_setup(*this);
259 }
260
261 void Switch::RunCleanup()
262 {
263 if (m_refs <= 0)
264 {
265 throw Exception();
266 }
267
268 if (--m_refs > 0)
269 {
270 return;
271 }
272
273 //Shut down the parent first.
274 krisbash 1.1 //Then shut down children that called setup, in reverse order.
275 if (m_cleanup)
276 {
277 m_cleanup(*this);
278 }
279
280 while (m_index > 0)
281 {
282 vector<Switch *> &list = *m_children;
283 Switch &child = *list[--m_index];
284 if (IsChildSelected(m_index))
285 {
286 child.RunCleanup();
287 }
288 }
289 }
290
291 Switch *Switch::GetFirstSelectedChild()
292 {
293 vector<Switch *> &list = *m_children;
294 int index = 0;
295 krisbash 1.1 int sizeOfChildrenList = (int)list.size();
296
297 while (index < sizeOfChildrenList)
298 {
299 if (IsChildSelected(index))
300 {
301 return list[index];
302 }
303 index++;
304 }
305
306 return NULL;
307 }
308
309 void Switch::Reset()
310 {
311 if (IsChoice())
312 {
313 m_choice = 0;
314 }
315
316 krisbash 1.1 if (m_index != 0 || m_refs > 0)
317 {
318 throw Exception();
319 }
320
321 //TODO: Is this really necessary?
322 vector<Switch *> &list = *m_children;
323 for (DWORD i = 0; i < list.size(); i++)
324 {
325 list[i]->Reset();
326 }
327
328 m_prevLayerContinuation = NULL;
329 m_sameLayerContinuation = NULL;
330 m_prevSwitchOnSelectedTestStack = NULL;
331 m_rootSwitch = NULL;
332 m_switchState = TestSystem::Switch::NotRunYet;
333
334 list.clear(); //Allows a later test to declare different children.
335 }
336
337 krisbash 1.1 bool Switch::Next()
338 {
339 vector<Switch *> &list = *m_children;
340 if (IsGroup())
341 {
342 //Lexicographic search.
343 //Start with the lowest-order "digit" and increment.
344 //If that is done, reset and move to the next-order "digit".
345 for (int i = (int)list.size() - 1; i >= 0; i--)
346 {
347 Switch &child = *list[i];
348 if (child.Next())
349 {
350 return true;
351 }
352
353 child.Reset();
354 }
355
356 return false;
357 }
358 krisbash 1.1 else
359 {
360 if (list.size() == 0)
361 {
362 //Choice nodes with no children run like a group node.
363 return false;
364 }
365
366 //Iterative search.
367 //Each child contains at least one position.
368 Switch &child = *list[m_choice];
369 if (child.Next())
370 {
371 return true;
372 }
373
374 child.Reset();
375 return ((unsigned long)(++m_choice)) < list.size();
376 }
377 }
378
379 krisbash 1.1 void Switch::PrintChoices(Buffer &data)
380 {
381 wostringstream &buf = data;
382 vector<Switch *> &list = *m_children;
383 if (IsChoice())
384 {
385 if (list.size() > 0)
386 {
387 buf << L"/" << list[m_choice]->GetName();
388 list[m_choice]->PrintChoices(data);
389 }
390 }
391 else for (DWORD i = 0; i < list.size(); i++)
392 {
393 list[i]->PrintChoices(data);
394 }
395 }
396
397 bool Switch::SelectChoices(_Inout_z_ PAL_Char * &choices)
398 {
399 vector<Switch *> &list = *m_children;
400 krisbash 1.1
401 //NOTE: Have to run setup at least once to discover children.
402 if (list.size() == 0)
403 {
404 RunSetup();
405 RunCleanup();
406 }
407
408 //Recursively traverse the choices and groups.
409 if (IsChoice())
410 {
411 PAL_Char *item = choices;
412 PAL_Char *slash = Tcschr(choices, PAL_T('/'));
413 if (slash)
414 {
415 //Advance to next choice.
416 *slash = PAL_T('\0');
417 choices = slash + 1;
418 }
419 else
420 {
421 krisbash 1.1 //No more choices. Just advance to the end.
422 choices += Tcslen(choices);
423 }
424
425 for (DWORD i = 0; i < list.size(); i++)
426 {
427 if (Equals(list[i]->GetName(), item))
428 {
429 m_choice = i;
430 return list[i]->SelectChoices(choices);
431 }
432 }
433
434 //Choice was not found.
435 return false;
436 }
437 else
438 {
439 for (DWORD i = 0; i < list.size(); i++)
440 {
441 if (!list[i]->SelectChoices(choices))
442 krisbash 1.1 {
443 return false;
444 }
445 }
446
447 return true;
448 }
449 }
450
451 NITS_EXPORT void NITS_CALL NitsTestCreate(
452 _Inout_ Test *test,
453 _In_ const PAL_Char * name,
454 _In_ void (NITS_CALL *setup)(Switch &),
455 _In_ void (NITS_CALL *body)(Switch &),
456 bool deleteMeAfterRun /* = false */)
457 {
458 PAL_UNUSED(name);
459 PAL_UNUSED(setup);
460 PAL_UNUSED(body);
461
462 test->m_body = body;
463 krisbash 1.1 test->m_deleteMeAfterRun = deleteMeAfterRun;
464
465 if (!Run::IsValid())
466 {
467 return;
468 }
469
470 Module &module = Run::GetInstance().GetCurrentModule();
471 if (&module == NULL)
472 {
473 return;
474 }
475
476 test->m_module = module.GetName();
477 module.AddTest(test);
478
479 test->m_timeout = test->s_nextTimeout;
480 test->m_isolation = test->s_nextIsolation;
481
482 test->s_nextTimeout = 60;
483 test->s_nextIsolation = false;
484 krisbash 1.1 test->m_startTicks = 0;
485 test->m_testRunState = TestSystem::Test::BodyYetToRun;
486 test->m_cleanupMode = TestSystem::Test::ImmediateCleanup;
487 }
488
489 void Test::PrintName(Buffer &data, bool choices)
490 {
491 wostringstream &buf = data;
492 buf << GetModule()
493 #ifdef _MSC_VER
494 << L"!"
495 #else
496 << L":"
497 #endif
498 << GetName();
499 if (choices)
500 {
501 PrintChoices(data);
502 }
503 }
504
505 krisbash 1.1 void Test::RunDeferredCleanup()
506 {
507 RunCleanup();
508 struct RegistrationInfo *myRegistration = (struct RegistrationInfo *)(m_registration);
509 myRegistration->cleanupFunc(myRegistration->selfContext);
510 }
511
512 void Test::Execute(_In_opt_z_ const PAL_Char * choices)
513 {
514 Reset();
515 Run &run = Run::GetInstance();
516 run.SetDefaultOptions();
517
518
519 if(!IsNewInterfaceTest() && (m_cleanupMode == DeferredCleanup))
520 {
521 NitsErr << PAL_T("ERROR: Only new interface tests can run deferred cleanup");
522 throw Exception();
523 }
524
525 if (choices == NULL)
526 krisbash 1.1 {
527 do {
528 RunVariation();
529 }
530 while (Next());
531 }
532 else
533 {
534 PAL_Char *temp = Copy(choices);
535 PAL_Char *temp2 = temp;
536 SetDryRun(1);
537 bool success = SelectChoices(temp2) && temp2[0] == L'\0';
538 SetDryRun(0);
539 delete [] temp;
540
541 if (!success)
542 {
543 NitsErr << PAL_T("ERROR: Invalid test variation '") << choices << PAL_T("'\n");
544 return;
545 }
546
547 krisbash 1.1 RunVariation();
548 }
549 }
550
551 void Test::ContinueProcessingAfterBody()
552 {
553 if(m_testRunState == PartAfterBodyRan)
554 return;
555
556 m_testRunState = PartAfterBodyRan;
557
558
559 Globals &globals = GetGlobals();
560 Run &run = Run::GetInstance();
561
562 Fault &fault = globals.GetAutoFault();
563 bool failTest = false;
564
565 if (globals.GetResult() == Error)
566 {
567 //Asserts attempted to fail fault sim.
568 krisbash 1.1 //During the regular body this is an ordinary failure.
569 globals.SetResult(Failed);
570 }
571 else if (globals.GetResult() == Skipped && Run::GetInstance().GetEnabled())
572 {
573 if(!NitsNotRunInCurrentTestChoice())
574 {
575 //No asserts were attempted and the test wasn't disabled.
576 globals.SetResult(Error);
577 NitsAssert(0, PAL_T("The test case contains no assertions!"));
578 }
579 else
580 {
581 globals.SetResult((m_filteredOutByUser) ? Skipped : Omitted);
582 }
583 }
584
585 int tempSwitchState = m_switchState;
586
587 bool runFaultInjection = Run::GetInstance().GetFaultMode() == Automatic &&
588 globals.GetConfiguration().mode >= NitsTestIterativeFault;
589 krisbash 1.1
590 Configuration const &config = Run::GetInstance().GetConfiguration();
591
592 bool filteringDetected = false;
593 ptrdiff_t limit = 0;
594
595 if (!runFaultInjection ||
596 globals.GetResult() != Passed)
597 {
598 goto NoFaultSim;
599 }
600
601 enum
602 {
603 MainThreadOnly,
604 IncreasingAttemptOnly,
605 Delayed
606 } state;
607
608 state = MainThreadOnly;
609 globals.m_simAuto.m_minimumAttemptDifferentThread = INT_MAX;
610 krisbash 1.1
611 #if defined(_MSC_VER)
612 # pragma warning(disable : 4127)
613 #endif
614
615 //Automatic fault simulation loop.
616 for (int i = 1; true; i++)
617 {
618 globals.ResetIgnoredErrorReporting();
619 if (state == Delayed)
620 {
621 //When filtering is disabled, threads from previous iterations
622 // might interfere with us. Wait some time for them to go away.
623 Sleep_Milliseconds(10);
624 }
625
626 //Do NOT reset globals here, or information from setup will be erased.
627 //Set automatic fault sim parameters.
628 bool faultBP = false;
629
630 if (config.breakFault)
631 krisbash 1.1 {
632 vector<int> const &list = Run::GetInstance().GetFaultBreakpointList();
633 for (unsigned j = 0; j < list.size(); j++)
634 {
635 if (list[j] == i)
636 {
637 faultBP = true;
638 break;
639 }
640 }
641 }
642 globals.SetResult(Passed);
643 fault.Reset(CallSite_ALL, i, faultBP);
644
645 wostringstream buf;
646 buf << L"Starting fault simulation iteration #" << i << L"...";
647 NitsTraceExW(buf.str().c_str(), TLINE, NitsAutomatic);
648 #ifdef _MSC_VER
649 DoTraceMessage(TestLifetime, L"Starting fault simulation iteration #%d...", i);
650 #endif
651 globals.GetStats().faultIterations++;
652 krisbash 1.1
653 // making switch state NotRunYet so that running the body does not skip the body
654 m_switchState = NotRunYet;
655
656 m_body(*this);
657
658 // putting the state back to what it was before we started fault sim so that further code path continues from the place where fault sim started
659 m_switchState = tempSwitchState;
660
661 if (globals.m_simAuto.m_filtered)
662 {
663 filteringDetected = true;
664 }
665
666 if (state == MainThreadOnly)
667 {
668 limit = max(limit, globals.m_simAuto.m_firstAttemptDifferentThread);
669 globals.m_simAuto.m_firstAttemptDifferentThread = 0;
670 }
671 else if (state == IncreasingAttemptOnly)
672 {
673 krisbash 1.1 limit = max(limit, globals.m_simAuto.m_faultedAttempt + 1);
674 globals.m_simAuto.m_minimumAttemptDifferentThread = limit;
675 globals.m_simAuto.m_firstAttemptDifferentThread = 0;
676 }
677
678 if (globals.GetResult() == Failed)
679 {
680 if (fault.DidFault())
681 {
682 //Expected behavior.
683 //Proceed to the next iteration.
684 continue;
685 }
686
687 //The test hit asserts before the fault was simulated.
688 //Stop here and report failure.
689 failTest = true;
690 NitsTraceEx(PAL_T("UNEXPECTED FAULT SIM FAILURE"), NitsHere(), NitsManual);
691 #ifdef _MSC_VER
692 DoTraceMessage(TestLifetime, L"UNEXPECTED FAULT SIM FAILURE");
693 #endif
694 krisbash 1.1 }
695 else if (globals.GetResult() == Error)
696 {
697 //Asserts attempted to fail fault sim.
698 //Don't abort the test.
699 failTest = true;
700 continue;
701 }
702 else if (globals.GetResult() != Passed)
703 {
704 throw Exception();
705 }
706
707 //The test body passed.
708 //This may or may not be expected.
709 if (!fault.DidFault())
710 {
711 if (filteringDetected)
712 {
713 if (state == MainThreadOnly)
714 {
715 krisbash 1.1 //Rerun with all threads, using the calculated limit.
716 globals.m_simAuto.m_minimumAttemptDifferentThread = limit;
717 state = IncreasingAttemptOnly;
718 }
719 else if (state == IncreasingAttemptOnly)
720 {
721 //Need to rerun with delays and without filtering.
722 globals.m_simAuto.m_minimumAttemptDifferentThread = 0;
723 state = Delayed;
724 }
725 filteringDetected = false;
726 continue;
727 }
728
729 //Loop complete.
730 fault.Reset(CallSite_NONE, 0, false);
731 globals.SetResult(failTest ? Failed : Faulted);
732 #ifdef _MSC_VER
733 DoTraceMessage(TestLifetime, L"Fault simulation loop completed");
734 #endif
735 goto NoFaultSim;
736 krisbash 1.1 }
737
738 if (Run::GetInstance().IsSiteExcluded(fault.m_hit) ||
739 !globals.ShouldReportIgnoredErrors())
740 {
741 //The test expected faults not to propagate properly here.
742 continue;
743 }
744
745 //This iteration should not have succeeded.
746 //Report the problem and continue running the test.
747 failTest = true;
748 if (GetGlobals().GetConfiguration().traces >= NitsTraceAsserts)
749 {
750 NitsTraceEx(PAL_T("UNEXPECTED FAULT SIM SUCCESS"),
751 fault.GetFaultedSite(), NitsManual);
752 }
753 #ifdef _MSC_VER
754 DoTraceMessage(TestLifetime, L"UNEXPECTED FAULT SIM SUCCESS");
755 #endif
756 if (config.breakAssert)
757 krisbash 1.1 {
758 MyDebugBreak;
759 }
760 }
761
762 NoFaultSim:
763
764 wostringstream testName;
765
766 Buffer wrappedTestName(testName);
767 PrintName(wrappedTestName, true);
768
769 if(m_cleanupMode == TestSystem::Test::ImmediateCleanup)
770 {
771 #ifdef _MSC_VER
772 DoTraceMessage(TestLifetime, "Running test cleanup: %S", testName.str().c_str());
773 #endif
774
775 RunCleanup();
776 }
777
778 krisbash 1.1 Result temp = globals.GetResult();
779 globals.SetResult(Skipped);
780
781 if(NitsNotRunInCurrentTestChoice())
782 {
783 #ifdef _MSC_VER
784 DoTraceMessage(TestLifetime, "Test choice ommited: %S", testName.str().c_str());
785 #endif
786 }
787 else
788 {
789 #ifdef _MSC_VER
790 DoTraceMessage(TestLifetime, "Test completed: %S", testName.str().c_str());
791 #endif
792 }
793
794 #ifdef _MSC_VER
795 //Reset all shared memory helpers except the NITS shared memory.
796 //This prevents badly-behaved tests from interfering with future tests.
797 System::GetInstance().ResetClientMappings();
798 #endif
799 krisbash 1.1
800 if (globals.GetResult() == Failed)
801 {
802 globals.SetResult(Error);
803 }
804 else
805 {
806 globals.SetResult(temp);
807 }
808
809 ptrdiff_t stopTicks = CPU_GetTimeStamp();
810 double seconds = float(stopTicks - m_startTicks) / 1000000.0;
811 globals.SetRunTime(seconds);
812
813 run.ReportResult();
814 }
815
816 static void FilterOutTestIfRequired()
817 {
818 Run &run = Run::GetInstance();
819 if(!(run.CurrentTestMatchesTestFilter()))
820 krisbash 1.1 {
821 run.GetCurrentTest().m_filteredOutByUser = 1;
822 GetGlobals().SetResult(Skipped);
823 }
824 }
825
826 void Test::ContinueProcessingAfterSetup()
827 {
828 if(m_testRunState == BodyRan)
829 return;
830
831 m_testRunState = BodyRan;
832
833 Globals &globals = GetGlobals();
834 Run &run = Run::GetInstance();
835 wostringstream testName;
836
837 Buffer wrappedTestName(testName);
838 PrintName(wrappedTestName, true);
839 #ifdef _MSC_VER
840 DoTraceMessage(TestLifetime, "Running test setup: %S", testName.str().c_str());
841 krisbash 1.1 #endif
842
843 FilterOutTestIfRequired();
844
845 if ((globals.GetConfiguration().traces >= NitsTraceAllTests) &&
846 (!m_filteredOutByUser))
847 {
848 wostringstream buf;
849 buf << L"\t " << testName.str().c_str() << L"...\n";
850
851 PAL_Char *postPipeStr = ConvertStringWToPalChar(buf.str().c_str());
852 globals.PostPipe(postPipeStr);
853 delete [] postPipeStr;
854 }
855
856 if (globals.GetResult() == Failed)
857 {
858 globals.SetResult(Error);
859 }
860 else if (globals.GetResult() == Passed)
861 {
862 krisbash 1.1 globals.SetResult(Skipped);
863 }
864
865 BOOL testEnabled = TRUE;
866 if (!run.GetEnabled())
867 {
868 testEnabled = FALSE;
869 }
870 if (globals.GetConfiguration().skipFlakyTests)
871 {
872 if (run.GetFlaky())
873 {
874 testEnabled = FALSE;
875 }
876 }
877
878 if (testEnabled &&
879 globals.GetResult() == Skipped)
880 {
881 #ifdef _MSC_VER
882 DoTraceMessage(TestLifetime, "Running test: %S", testName.str().c_str());
883 krisbash 1.1 #endif
884 RunBody();
885
886 if(m_testRunState == BodyRan)
887 {
888 if(!IsNewInterfaceTest())
889 {
890 ContinueProcessingAfterBody();
891 }
892 else
893 {
894 // we do not want test writers to use "return;" to exit the test fixtures, we want them to use "NitsReturn;"
895 // if they use "return;" then we hit this code path where the Setup is not followed by a continuation function call leading to the body and so on.
896 // so if we hit this code path when running new interface tests, we should error out
897 throw Exception();
898 }
899 }
900 }
901 else
902 {
903 #ifdef _MSC_VER
904 krisbash 1.1 DoTraceMessage(TestLifetime, "Skipping test body: %S", testName.str().c_str());
905 #endif
906 ContinueProcessingAfterBody();
907 }
908 }
909
910 void Test::RunVariation()
911 {
912 Run &run = Run::GetInstance();
913
914 run.ClearTestVaritionNodes();
915
916 //Copy settings from command line options.
917 run.SetDefaultOptions();
918
919 m_startTicks = CPU_GetTimeStamp();
920
921 m_testRunState = BodyYetToRun;
922 m_prevLayerContinuation = NULL;
923 m_sameLayerContinuation = NULL;
924 m_prevSwitchOnSelectedTestStack = NULL;
925 krisbash 1.1 m_someoneCalledOmit = 0;
926 m_filteredOutByUser = 0;
927 m_switchState = TestSystem::Switch::NotRunYet;
928
929 //Status is 'Skipped'.
930 RunSetup();
931
932 if(m_testRunState == BodyYetToRun)
933 {
934 vector<Switch *> &list = *(m_children);
935 // if it is not new interface test or there were no children registered then we will continue from here since setup would not have ran continuation
936 if(!IsNewInterfaceTest() || (list.size() == 0))
937 {
938 ContinueProcessingAfterSetup();
939 }
940 else
941 {
942 // we do not want test writers to use "return;" to exit the test fixtures, we want them to use "NitsReturn;"
943 // if they use "return;" then we hit this code path where the Setup is not followed by a continuation function call leading to the body and so on.
944 // so if we hit this code path when running new interface tests, we should error out
945 throw Exception();
946 krisbash 1.1 }
947 }
948 }
949
950
951 void Test::RunBody()
952 {
953 Globals &globals = GetGlobals();
954
955 //N.B. When nits.exe is running tests in-proc, we need to bootstrap
956 // the debugger before the test. Otherwise, the test could call
957 // LoadLibrary, and CheckDebugger() could get called inside the
958 // loader lock of our process, which can prevent us from actually
959 // creating the debugger process indefinitely.
960 globals.CheckDebugger();
961
962 globals.m_simAuto.m_firstAttemptDifferentThread = 0;
963 globals.m_simAuto.m_minimumAttemptDifferentThread = 0;
964 globals.m_simAuto.m_mainThread = Thread_ID();
965 globals.m_simAuto.m_faultedAttempt = 0;
966
967 krisbash 1.1 //Run the regular test body.
968 m_body(*this);
969 }
970
971 int Test::s_nextTimeout = 60;
972 bool Test::s_nextIsolation = false;
973
974 NITS_EXPORT void NITS_CALL NitsTestSetIsolationHelper(_In_ Test &test)
975 {
976 PAL_UNUSED(test);
977
978 Test::s_nextIsolation = true;
979 }
980
981 NITS_EXPORT void NITS_CALL NitsTestSetTimeoutHelper(_In_ Test &test, int seconds)
982 {
983 PAL_UNUSED(test);
984
985 Test::s_nextTimeout = seconds;
986 }
987
988 krisbash 1.1 NITS_EXPORT void NITS_CALL NitsSetRegistrationInfo(struct RegistrationInfo *r,
989 int selfContextSize,
990 int selfStructSize,
991 int numberOfParents,
992 Switch **parentArray,
993 void *(*creationFunc)(),
994 void (*initFunc)(void *, void *),
995 void (*bodyFunc)(void *),
996 void (*cleanupFunc)(void *),
997 enum TestFixtureType fixtureType,
998 void **arrayOfInitializers)
999 {
1000 r->selfContext = 0;
1001 r->selfStruct = 0;
1002 r->countOfLinks = 0;
1003 r->selfContextSize = selfContextSize;
1004 r->selfStructSize = selfStructSize;
1005 r->numberOfParents = numberOfParents;
1006 r->parentArray = parentArray;
1007 r->creationFunc = creationFunc;
1008 r->initFunc = initFunc;
1009 krisbash 1.1 r->bodyFunc = bodyFunc;
1010 r->cleanupFunc = cleanupFunc;
1011 r->fixtureType = fixtureType;
1012 r->arrayOfInitializers = arrayOfInitializers;
1013 r->cleanupSwitch = 0;
1014 r->crashSwitch = 0;
1015 }
1016
1017 NITS_EXPORT void NITS_CALL NitsCreateStruct(TestSystem::Switch &myFixture, void **selfContext, void **selfStruct)
1018 {
1019 struct RegistrationInfo *myFixtureRegistration = (struct RegistrationInfo *) (myFixture.m_registration);
1020
1021 // this should not happen
1022 if(!selfContext || !selfStruct)
1023 return;
1024
1025 // this is for virtual inheritance kind of semantics; if there is already a structure allocated through one route in inheritance, we will not allocate it again but use the same one
1026 if(myFixtureRegistration->countOfLinks > 0)
1027 {
1028 *selfContext = myFixtureRegistration->selfContext;
1029 *selfStruct = myFixtureRegistration->selfStruct;
1030 krisbash 1.1 }
1031 else
1032 {
1033 int isSplitFixture = (myFixtureRegistration->fixtureType == SplitFixture);
1034 // for splitfixtures, the context comes from their parents; they do not have a context;
1035 // pointer adjustment is done during the call of the splitfixture by walking back the call chain
1036 *selfContext = malloc(myFixtureRegistration->selfContextSize);
1037 *selfStruct = (isSplitFixture ? 0 : malloc(myFixtureRegistration->selfStructSize));
1038 myFixtureRegistration->selfContext = *selfContext;
1039 myFixtureRegistration->selfStruct = *selfStruct;
1040 }
1041 (myFixtureRegistration->countOfLinks)++;
1042 }
1043
1044 NITS_EXPORT void NITS_CALL NitsDestroyStruct(TestSystem::Switch &myFixture)
1045 {
1046 struct RegistrationInfo *myFixtureRegistration = (struct RegistrationInfo *) (myFixture.m_registration);
1047 (myFixtureRegistration->countOfLinks)--;
1048
1049 if(myFixtureRegistration->countOfLinks == 0)
1050 {
1051 krisbash 1.1 free(myFixtureRegistration->selfContext);
1052
1053 if(myFixtureRegistration->fixtureType != SplitFixture)
1054 {
1055 free(myFixtureRegistration->selfStruct);
1056 }
1057 myFixtureRegistration->selfContext = 0;
1058 myFixtureRegistration->selfStruct = 0;
1059 }
1060 }
1061
1062 NITS_EXPORT void * NITS_CALL NitsGetSelfStruct(TestSystem::Switch &myFixture)
1063 {
1064 struct RegistrationInfo *myFixtureRegistration = (struct RegistrationInfo *) (myFixture.m_registration);
1065
1066 return myFixtureRegistration->selfStruct;
1067 }
1068
1069 NITS_EXPORT void NITS_CALL NitsBody_NewInterfaceTest(TestSystem::Switch &test)
1070 {
1071 struct RegistrationInfo *testRegistration = (struct RegistrationInfo *) (test.m_registration);
1072 krisbash 1.1
1073 FilterOutTestIfRequired();
1074
1075 if(test.m_switchState == TestSystem::Switch::NotRunYet)
1076 {
1077 test.m_switchState = TestSystem::Switch::RunOnce;
1078 testRegistration->bodyFunc(testRegistration->selfContext);
1079 }
1080 else
1081 {
1082 NitsRunContinuation(test);
1083 }
1084 }
1085
1086 NITS_EXPORT void NITS_CALL NitsSetup_NewInterfaceTest(TestSystem::Switch &test)
1087 {
1088 struct RegistrationInfo *testRegistration = (struct RegistrationInfo *) (test.m_registration);
1089 int parentCount = 0;
1090 Switch *currentParent = 0;
1091 // when doing dryRun, it is needed only to make engine aware of children; so skip all other steps.
1092 int isDryRun = Run::GetInstance().GetCurrentTest().IsDryRunToIdentifyChildren();// test.IsDryRunToIdentifyChildren();
1093 krisbash 1.1
1094 if(test.IsBodyFixture() ||
1095 IsSetupFixture(testRegistration->fixtureType))
1096 {
1097 if(!isDryRun)
1098 {
1099 Run::GetInstance().AddTestVariationNode(&test);
1100 }
1101
1102 if(test.IsBodyFixture() && !isDryRun)
1103 {
1104 if(testRegistration->selfContext == 0)
1105 {
1106 // this creationFunc will recurse through the entire test structure and create selfContext for each node following the virtual inheritance way of creating common node only once
1107 // TODO: implement multiple inheritance; will the common nodes need to register switches multiple times; who will create those switches?
1108 testRegistration->creationFunc();
1109 }
1110 // the initFunc is passed in the created context and a NULL for the initValues since the test itself does not provide any init values; the initFunc is supposed zero out its structure if init values are not provided.
1111 testRegistration->initFunc(testRegistration->selfContext, 0);
1112
1113 test.m_sameLayerContinuation = 0;
1114 krisbash 1.1
1115 test.m_prevLayerContinuation = &test;
1116 }
1117
1118 if(testRegistration->parentArray != 0)
1119 {
1120 while(parentCount < testRegistration->numberOfParents)
1121 {
1122 // register the child by calling Test.Child; this helps the test engine identify children/pick up the current chain of children to be run in this iteration
1123 currentParent = testRegistration->parentArray[parentCount];
1124
1125 // in both test setup and body cases, you need continuation switch set to your currentParent;
1126 // but in SetupFixture case the continuation is the body of this current testRegistration whereas in
1127 // in BodyFixture case continuation is the ContinueProcessingAfterSetup
1128 if(!isDryRun)
1129 {
1130 currentParent->m_sameLayerContinuation = 0;
1131
1132 if(test.IsGroup() && (parentCount >= 1))
1133 {
1134 Switch *prevParent = testRegistration->parentArray[parentCount - 1];
1135 krisbash 1.1 prevParent->m_sameLayerContinuation = currentParent;
1136 }
1137
1138 // this helps with multiple inheritance; if some other fixture already put the prevLayerContiuationLink into current parent, that is sufficient; the second link is not required
1139 if(currentParent->m_prevLayerContinuation == 0)
1140 {
1141 currentParent->m_prevLayerContinuation = &test;
1142 }
1143 }
1144
1145 test.Child(*currentParent);
1146
1147 parentCount++;
1148 }
1149
1150 // once we found what is the root node in current iteration; invoke its body; that will keep calling continuation till we run the test body and cleanup by nesting them on the same stack
1151 if(!isDryRun && test.IsBodyFixture() && (test.m_rootSwitch != 0))
1152 {
1153 (test.m_rootSwitch)->m_prevSwitchOnSelectedTestStack = 0;
1154 NitsBody_NewInterfaceTest(*(test.m_rootSwitch));
1155 test.m_rootSwitch = 0;
1156 krisbash 1.1 }
1157 }
1158 else
1159 {
1160 if(!isDryRun)
1161 {
1162 // when we reach the root of the tree; run the body of the fixture
1163 if(IsSetupFixture(testRegistration->fixtureType))
1164 {
1165 Switch *continuationSwitch = test.m_prevLayerContinuation;
1166 while(continuationSwitch)
1167 {
1168 if(continuationSwitch->m_prevLayerContinuation == 0 || (continuationSwitch->m_prevLayerContinuation == continuationSwitch))
1169 {
1170 break;
1171 }
1172 continuationSwitch = continuationSwitch->m_prevLayerContinuation;
1173 }
1174
1175 if (continuationSwitch == NULL)
1176 {
1177 krisbash 1.1 FatalError();
1178 return;
1179 }
1180
1181 // only first root node i.e. when m_rootSwitch = 0 does this assignment; others do not since the first one will continue to run others
1182 if(continuationSwitch->m_rootSwitch == 0)
1183 {
1184 continuationSwitch->m_rootSwitch = &test;
1185 }
1186 }
1187 }
1188 }
1189 }
1190 }
1191
1192 NITS_EXPORT void NITS_CALL NitsCleanup_NewInterfaceTest(TestSystem::Switch &test)
1193 {
1194 struct RegistrationInfo *testRegistration = (struct RegistrationInfo *) (test.m_registration);
1195
1196 if(Run::GetInstance().GetCurrentTest().IsDryRunToIdentifyChildren())
1197 return;
1198 krisbash 1.1
1199 struct RegistrationInfo *cleanupRegistration = (struct RegistrationInfo *) ((testRegistration->cleanupSwitch) ? testRegistration->cleanupSwitch->m_registration : 0);
1200
1201 if(cleanupRegistration && !(test.m_notRunInCurrentTestChoice))
1202 {
1203 if(test.m_switchState == TestSystem::Switch::RunOnce)
1204 {
1205 test.m_switchState = TestSystem::Switch::CleanupRun;
1206 cleanupRegistration->bodyFunc(testRegistration->selfContext);
1207 }
1208 }
1209
1210 test.m_switchState = TestSystem::Switch::NotRunYet;
1211 test.m_notRunInCurrentTestChoice = 0;
1212 }
1213
1214 NITS_EXPORT void NITS_CALL NitsRunContinuation(TestSystem::Switch &test)
1215 {
1216 // start psuedo code
1217 TestSystem::Switch *continuationSwitch = test.m_sameLayerContinuation;
1218 struct RegistrationInfo *continuationRegistration = 0;
1219 krisbash 1.1
1220 // this will get run now or it will go to its parent; so we should reset it to avoid infinite loop if any
1221 test.m_sameLayerContinuation = NULL;
1222
1223 while(continuationSwitch)
1224 {
1225 continuationRegistration = (struct RegistrationInfo *) (continuationSwitch->m_registration);
1226
1227 if(continuationRegistration->parentArray == 0)
1228 {
1229 continuationSwitch->m_prevSwitchOnSelectedTestStack = &test;
1230 continuationSwitch->m_notRunInCurrentTestChoice = NitsNotRunInCurrentTestChoice();
1231 if(continuationRegistration->fixtureType == SplitFixture)
1232 {
1233 continuationRegistration->selfStruct = NitsGetSelfStruct(test);
1234 }
1235 NitsBody_NewInterfaceTest(*continuationSwitch);
1236 // continuationRegistration->bodyFunc(continuationRegistration->selfContext);
1237 return;
1238 }
1239 else
1240 krisbash 1.1 {
1241 Switch *tempSwitch = continuationSwitch;
1242 continuationSwitch = continuationSwitch->GetFirstSelectedChild();
1243 if(continuationSwitch && (continuationSwitch->m_prevLayerContinuation != tempSwitch))
1244 {
1245 // this helps with multiple inheritance; before going to the next parent;
1246 // you set the prevLayerContinuation to yourself so that when it comes down, it does not go the current prevLayer instead comes back to you
1247 continuationSwitch->m_prevLayerContinuation = tempSwitch;
1248 }
1249 }
1250 }
1251
1252 continuationSwitch = test.m_prevLayerContinuation;
1253
1254 if(continuationSwitch)
1255 {
1256 continuationRegistration = (struct RegistrationInfo *) (continuationSwitch->m_registration);
1257
1258 if(IsSetupFixture(continuationRegistration->fixtureType))
1259 {
1260 continuationSwitch->m_prevSwitchOnSelectedTestStack = &test;
1261 krisbash 1.1 continuationSwitch->m_notRunInCurrentTestChoice = NitsNotRunInCurrentTestChoice();
1262 if(continuationRegistration->fixtureType == SplitFixture)
1263 {
1264 continuationRegistration->selfStruct = NitsGetSelfStruct(test);
1265 }
1266 NitsBody_NewInterfaceTest(*continuationSwitch);
1267 // continuationRegistration->bodyFunc(continuationRegistration->selfContext);
1268 }
1269 else if(continuationSwitch->IsBodyFixture())
1270 {
1271 TestSystem::Test *continuationTest = (TestSystem::Test *)continuationSwitch;
1272
1273 if(continuationTest->m_testRunState == TestSystem::Test::BodyYetToRun)
1274 {
1275 continuationSwitch->m_prevSwitchOnSelectedTestStack = &test;
1276 continuationSwitch->m_notRunInCurrentTestChoice = NitsNotRunInCurrentTestChoice();
1277 continuationTest->ContinueProcessingAfterSetup();
1278 }
1279 else if(continuationTest->m_testRunState == TestSystem::Test::BodyRan)
1280 {
1281 continuationTest->ContinueProcessingAfterBody();
1282 krisbash 1.1
1283 if(continuationTest->m_cleanupMode == TestSystem::Test::ImmediateCleanup)
1284 {
1285 // the main thread which was running body and possibly faultsim will then call clean up on the test related context objects
1286 // this is separate from the cleanup functions explicitly defined by the user to clean up the stuff the user wants to.
1287 continuationRegistration->cleanupFunc(continuationRegistration->selfContext);
1288 }
1289 }
1290 }
1291 }
1292 }
1293
1294 NITS_EXPORT int NITS_CALL NitsIsFixtureSelectedSoFar(TestSystem::Switch ¤tSwitch, TestSystem::Switch &searchSwitch)
1295 {
1296 Switch *currentNode = ¤tSwitch;
1297
1298 while(currentNode->m_prevSwitchOnSelectedTestStack)
1299 {
1300 if(currentNode->m_prevSwitchOnSelectedTestStack == &searchSwitch)
1301 return 1;
1302
1303 krisbash 1.1 currentNode = currentNode->m_prevSwitchOnSelectedTestStack;
1304 }
1305
1306 return 0;
1307 }
1308
1309 #define FIXTURE_STRING PAL_T("Fixture ")
1310 #define OMITTED_MESSAGE PAL_T(" omitted the test choice\n")
1311
1312 NITS_EXPORT void NITS_CALL NitsOmit(TestSystem::Switch ¤tSwitch)
1313 {
1314 Run::GetInstance().GetCurrentTest().m_someoneCalledOmit = 1;
1315 GetGlobals().SetResult(Skipped);
1316
1317 int totalLen = (int)(Tcslen(FIXTURE_STRING) + Tcslen(currentSwitch.GetName()) + Tcslen(OMITTED_MESSAGE)) + 1;
1318 PAL_Char *outString = (PAL_Char *)(malloc(totalLen*sizeof(PAL_Char)));
1319 if(outString)
1320 {
1321 Tcslcpy(outString, FIXTURE_STRING, totalLen);
1322 Tcscat(outString, totalLen, currentSwitch.GetName());
1323 Tcscat(outString, totalLen, OMITTED_MESSAGE);
1324 krisbash 1.1 GetGlobals().PostPipe(outString);
1325 free(outString);
1326 }
1327 else
1328 {
1329 GetGlobals().PostPipe(PAL_T("Some Fixture omitted the test choice"));
1330 }
1331 }
1332
1333 NITS_EXPORT int NITS_CALL NitsAreWeInOmitMode()
1334 {
1335 return (Run::GetInstance().GetCurrentTest().m_someoneCalledOmit);
1336 }
1337
1338 NITS_EXPORT int NITS_CALL NitsIsTestFiltered()
1339 {
1340 return (Run::GetInstance().GetCurrentTest().m_filteredOutByUser);
1341 }
1342
1343 NITS_EXPORT_DEF struct EmptyStruct sEmptyStruct = {0};
1344
|