1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "TestSuite.h" 8 9 #include <new> 10 11 #include <string.h> 12 13 #include "TestVisitor.h" 14 15 16 TestSuite::TestSuite(const char* name) 17 : 18 Test(name), 19 fTests(NULL), 20 fTestCount(0) 21 { 22 } 23 24 25 TestSuite::~TestSuite() 26 { 27 for (int32 i = 0; i < fTestCount; i++) 28 delete fTests[i]; 29 delete[] fTests; 30 } 31 32 33 int32 34 TestSuite::CountTests() const 35 { 36 return fTestCount; 37 } 38 39 40 Test* 41 TestSuite::TestAt(int32 index) const 42 { 43 return index >= 0 && index < fTestCount ? fTests[index] : NULL; 44 } 45 46 47 Test* 48 TestSuite::FindTest(const char* name, int32 nameLength) const 49 { 50 if (nameLength < 0) 51 nameLength = strlen(name); 52 53 for (int32 i = 0; Test* test = TestAt(i); i++) { 54 if (strlen(test->Name()) == (size_t)nameLength 55 && strncmp(test->Name(), name, nameLength) == 0) { 56 return test; 57 } 58 } 59 60 return NULL; 61 } 62 63 64 bool 65 TestSuite::AddTest(Test* test) 66 { 67 if (test == NULL) 68 return test; 69 70 Test** tests = new(std::nothrow) Test*[fTestCount + 1]; 71 if (tests == NULL) { 72 delete test; 73 return false; 74 } 75 76 if (fTestCount > 0) 77 memcpy(tests, fTests, sizeof(Test*) * fTestCount); 78 79 delete[] fTests; 80 81 fTests = tests; 82 fTests[fTestCount++] = test; 83 84 test->SetSuite(this); 85 86 return true; 87 } 88 89 90 bool 91 TestSuite::IsLeafTest() const 92 { 93 return false; 94 } 95 96 97 bool 98 TestSuite::Run(TestContext& context) 99 { 100 for (int32 i = 0; Test* test = TestAt(i); i++) { 101 bool result = _Run(context, test, NULL); 102 if (!result && context.Options().quitAfterFailure) 103 return false; 104 } 105 106 return true; 107 } 108 109 110 bool 111 TestSuite::Run(TestContext& context, const char* name) 112 { 113 const char* separator = strstr(name, "::"); 114 Test* test = FindTest(name, separator != NULL ? separator - name : -1); 115 if (test == NULL) { 116 context.Print("No such test: \"%.*s\"\n", 117 int(separator != NULL ? separator - name : strlen(name)), name); 118 return !context.Options().quitAfterFailure; 119 } 120 121 return _Run(context, test, separator != NULL ? separator + 2 : NULL) 122 || !context.Options().quitAfterFailure; 123 } 124 125 126 Test* 127 TestSuite::Visit(TestVisitor& visitor) 128 { 129 if (visitor.VisitTestSuitePre(this)) 130 return this; 131 132 for (int32 i = 0; Test* test = TestAt(i); i++) { 133 if (Test* foundTest = test->Visit(visitor)) 134 return foundTest; 135 } 136 137 return visitor.VisitTestSuitePost(this) ? this : NULL; 138 } 139 140 141 bool 142 TestSuite::_Run(TestContext& context, Test* test, const char* name) 143 { 144 TestContext subContext(context, test); 145 146 status_t error = test->Setup(subContext); 147 if (error != B_OK) { 148 subContext.Error("setup failed\n"); 149 test->Cleanup(subContext, false); 150 subContext.TestDone(false); 151 return false; 152 } 153 154 bool result = name != NULL 155 ? test->Run(subContext, name) : test->Run(subContext); 156 test->Cleanup(subContext, true); 157 158 subContext.TestDone(result); 159 160 return result; 161 } 162