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
TestSuite(const char * name)16 TestSuite::TestSuite(const char* name)
17 :
18 Test(name),
19 fTests(NULL),
20 fTestCount(0)
21 {
22 }
23
24
~TestSuite()25 TestSuite::~TestSuite()
26 {
27 for (int32 i = 0; i < fTestCount; i++)
28 delete fTests[i];
29 delete[] fTests;
30 }
31
32
33 int32
CountTests() const34 TestSuite::CountTests() const
35 {
36 return fTestCount;
37 }
38
39
40 Test*
TestAt(int32 index) const41 TestSuite::TestAt(int32 index) const
42 {
43 return index >= 0 && index < fTestCount ? fTests[index] : NULL;
44 }
45
46
47 Test*
FindTest(const char * name,int32 nameLength) const48 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
AddTest(Test * test)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
IsLeafTest() const91 TestSuite::IsLeafTest() const
92 {
93 return false;
94 }
95
96
97 bool
Run(TestContext & context)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
Run(TestContext & context,const char * name)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*
Visit(TestVisitor & visitor)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
_Run(TestContext & context,Test * test,const char * name)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