xref: /haiku/src/tests/system/kernel/unit/TestSuite.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
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