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