2 * Copyright (c) 2014, 2015 JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 #ifndef _1_cppunit_cpp_
36 #define _1_cppunit_cpp_
39 * Copyright (c) 2008, Robert Emerson
40 * All rights reserved.
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions are met:
44 * * Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * * Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * * Neither the name of Robert Emerson nor the
50 * names of its contributors may be used to endorse or promote products
51 * derived from this software without specific prior written permission.
53 * THIS SOFTWARE IS PROVIDED BY ROBERT EMERSON ''AS IS'' AND ANY
54 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
55 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
56 * DISCLAIMED. IN NO EVENT SHALL ROBERT EMERSON BE LIABLE FOR ANY
57 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
58 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
59 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
60 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
62 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 #include <cppunit/CompilerOutputter.h>
74 #include <cppunit/TextOutputter.h>
75 #include <cppunit/XmlOutputter.h>
76 #include <cppunit/extensions/TestFactoryRegistry.h>
77 #include <cppunit/TestResult.h>
78 #include <cppunit/TestResultCollector.h>
79 #include <cppunit/TestRunner.h>
80 #include <cppunit/TextTestProgressListener.h>
81 #include <cppunit/BriefTestProgressListener.h>
82 #include <cppunit/TestSuccessListener.h>
83 #include <cppunit/Portability.h>
85 using namespace CPPUNIT_NS;
96 static const int RET_OK = 0;
97 static const int RET_USAGE = -1;
98 static const int RET_BAD_OUTPUTTER = -2;
99 static const int RET_BAD_LISTENER = -3;
100 static const int RET_BAD_TEST = -4;
102 typedef map<string, Outputter *> OutputterMap;
103 typedef map<string, TestListener *> ListenerMap;
105 void usage(const char *image,
106 const char *defaultTest,
107 const OutputterMap &outputters,
108 const ListenerMap &listeners)
111 cout << "Usage: " << basename(image)
112 << " (-o outputter) (-p progress) (-t test) (-r count)" << endl;
113 cout << " " << basename(image)
114 << " [ -l | -h ]" << endl;
116 cout << "A CppUnit command line test execution tool. " << endl;
118 cout << "Built against cppunit version: " << CPPUNIT_VERSION << endl;
120 cout << "Options:" << endl;
122 cout << " -o Output style. Choices: ";
125 OutputterMap::const_iterator it = outputters.begin();
127 while (it != outputters.end()) {
128 cout << it->first << " ";
133 cout << "Default: compiler" << endl;
134 cout << " -p Progress style. Choices: ";
136 ListenerMap::const_iterator it = listeners.begin();
138 while (it != listeners.end()) {
139 cout << it->first << " ";
144 cout << "Default: dots";
146 cout << " -t Runs given the test only. Default: \"" << defaultTest << "\"" << endl;
147 cout << " -r Repeat count. Default: 1" << endl;
149 cout << " -l List all available tests." << endl;
150 cout << " -h Print this usage message." << endl;
152 cout << "Returns 0 on success, negative for usage errors, positive errors plus failures." << endl;
154 cout << "If the image name is a valid test name, then this is the default test executed." << endl;
160 // Recursive dumps the given Test heirarchy to cout
161 void dump(Test *test)
163 if (0 == test) return;
165 cout << test->getName() << endl;
167 if (0 == test->getChildTestCount()) return;
169 for (int i = 0; i < test->getChildTestCount(); i++) {
170 dump(test->getChildTestAt(i));
176 // Recursively seeks the Test matching the given name, returns 0 otherwise.
177 Test *find(Test *test, const string &name)
179 if (0 == test) return 0;
180 if (name == test->getName()) return test;
181 if (0 == test->getChildTestCount()) return 0;
183 for (int i = 0; i < test->getChildTestCount(); i++) {
184 Test *found = find(test->getChildTestAt(i), name);
185 if (found) return found;
191 int main(int argc, char **argv)
194 TestResultCollector collector;
195 result.addListener(&collector);
197 OutputterMap allOutputters;
199 allOutputters.insert(make_pair("compiler",
200 new CompilerOutputter(&collector, cout)));
201 allOutputters.insert(make_pair("text",
202 new TextOutputter(&collector, cout)));
203 allOutputters.insert(make_pair("xml",
204 new XmlOutputter(&collector, cout)));
205 allOutputters.insert(make_pair("none", static_cast<Outputter *>(0)));
207 Outputter *outputter = allOutputters.find("compiler")->second;
209 ListenerMap allListeners;
211 allListeners.insert(make_pair("dots", new TextTestProgressListener()));
212 allListeners.insert(make_pair("brief", new BriefTestProgressListener()));
213 allListeners.insert(make_pair("none", static_cast<TestListener *>(0)));
215 TestListener *listener = allListeners.find("dots")->second;
217 string runTest = basename(argv[0]);
219 if (!find(TestFactoryRegistry::getRegistry().makeTest(), runTest)) {
220 runTest = "All Tests";
225 while ((flag = getopt(argc, argv, "r:t:o:p:lh")) != -1) {
230 repeat = atoi(optarg);
235 OutputterMap::const_iterator it = allOutputters.find(optarg);
236 if (it == allOutputters.end()) {
237 cerr << "Unknown outputter: " << optarg << endl;
238 return RET_BAD_OUTPUTTER;
240 outputter = it->second;
246 string progress(optarg);
247 ListenerMap::const_iterator it = allListeners.find(optarg);
248 if (it == allListeners.end()) {
249 cerr << "Unknown listener: " << optarg << endl;
250 return RET_BAD_LISTENER;
252 listener = it->second;
258 Test *all = TestFactoryRegistry::getRegistry().makeTest();
262 break; // not reached
272 usage(argv[0], runTest.c_str(), allOutputters, allListeners);
274 break; // not reached
277 if (listener != 0) result.addListener(listener);
279 Test *run = find(TestFactoryRegistry::getRegistry().makeTest(), runTest);
281 cerr << "Unknown test case: " << runTest << endl;
288 for (int i = 0; i < repeat; i++) {
292 if (outputter) outputter->write();
294 return collector.testErrors() + collector.testFailures();
298 #endif // _1_cppunit_cpp_