]> git.saurik.com Git - wxWidgets.git/blame - tests/test.cpp
add header required for PCH-less mingw32 compilation (closes #10196)
[wxWidgets.git] / tests / test.cpp
CommitLineData
670ec357
VS
1///////////////////////////////////////////////////////////////////////////////
2// Name: test.cpp
3// Purpose: Test program for wxWidgets
4// Author: Mike Wetherell
5// RCS-ID: $Id$
6// Copyright: (c) 2004 Mike Wetherell
7// Licence: wxWidgets licence
8///////////////////////////////////////////////////////////////////////////////
9
8899b155
RN
10// For compilers that support precompilation, includes "wx/wx.h"
11// and "wx/cppunit.h"
12#include "testprec.h"
670ec357
VS
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18// for all others, include the necessary headers
19#ifndef WX_PRECOMP
20 #include "wx/wx.h"
21#endif
22
afd90468
VZ
23#include "wx/beforestd.h"
24#include <cppunit/TestListener.h>
25#include <cppunit/Test.h>
26#include <cppunit/TestResult.h>
27#include "wx/afterstd.h"
28
670ec357 29#include "wx/cmdline.h"
670ec357
VS
30#include <iostream>
31
3e5f6c1c
WS
32using CppUnit::Test;
33using CppUnit::TestSuite;
34using CppUnit::TestFactoryRegistry;
3e5f6c1c 35
afd90468
VZ
36
37// Displays the test name. This allow for quick investigation on which test hangs
38class DetailListener : public CppUnit::TestListener
39{
40public:
41 DetailListener(bool doTiming = false):
42 CppUnit::TestListener(),
43 m_timing(doTiming)
44 {
45 }
46
47 virtual void startTest(CppUnit::Test *test)
48 {
49 CppUnit::stdCOut() << test->getName () << " ";
50 m_watch.Start();
51 }
52
53 virtual void endTest(CppUnit::Test * WXUNUSED(test))
54 {
55 m_watch.Pause();
56 if ( m_timing )
57 CppUnit::stdCOut() << " (in "<< m_watch.Time() << " ms )";
58 CppUnit::stdCOut() << "\n";
59 }
60
61protected :
62 bool m_timing;
63 wxStopWatch m_watch;
64};
65
5098c258 66using namespace std;
670ec357 67
c0d9b217
VZ
68#if wxUSE_GUI
69 typedef wxApp TestAppBase;
70#else
71 typedef wxAppConsole TestAppBase;
72#endif
73
670ec357
VS
74// The application class
75//
c0d9b217 76class TestApp : public TestAppBase
670ec357
VS
77{
78public:
79 TestApp();
80
81 // standard overrides
c0d9b217
VZ
82 virtual void OnInitCmdLine(wxCmdLineParser& parser);
83 virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
84 virtual bool OnInit();
85 virtual int OnRun();
86 virtual int OnExit();
670ec357
VS
87
88private:
8dae9169 89 void List(Test *test, const string& parent = "") const;
670ec357
VS
90
91 // command lines options/parameters
92 bool m_list;
a81f3066 93 bool m_longlist;
afd90468
VZ
94 bool m_detail;
95 bool m_timing;
a81f3066 96 vector<string> m_registries;
670ec357
VS
97};
98
99IMPLEMENT_APP_CONSOLE(TestApp)
100
101TestApp::TestApp()
8dae9169
VS
102 : m_list(false),
103 m_longlist(false)
670ec357
VS
104{
105}
106
107// Init
108//
109bool TestApp::OnInit()
110{
c0d9b217
VZ
111 if ( !TestAppBase::OnInit() )
112 return false;
113
670ec357 114 cout << "Test program for wxWidgets\n"
3e5f6c1c 115 << "build: " << WX_BUILD_OPTIONS_SIGNATURE << std::endl;
9f7a07ab 116
c0d9b217
VZ
117#if wxUSE_GUI
118 // create a hidden parent window to be used as parent for the GUI controls
119 new wxFrame(NULL, wxID_ANY, "Hidden wx test frame");
120#endif // wxUSE_GUI
121
122 return true;
9f10e7c7 123}
670ec357
VS
124
125// The table of command line options
126//
127void TestApp::OnInitCmdLine(wxCmdLineParser& parser)
128{
c0d9b217 129 TestAppBase::OnInitCmdLine(parser);
670ec357
VS
130
131 static const wxCmdLineEntryDesc cmdLineDesc[] = {
aa3b041e
VZ
132 { wxCMD_LINE_SWITCH, "l", "list",
133 "list the test suites, do not run them",
a81f3066 134 wxCMD_LINE_VAL_NONE, 0 },
aa3b041e
VZ
135 { wxCMD_LINE_SWITCH, "L", "longlist",
136 "list the test cases, do not run them",
670ec357 137 wxCMD_LINE_VAL_NONE, 0 },
afd90468
VZ
138 { wxCMD_LINE_SWITCH, "d", "detail",
139 "print the test case names, run them",
140 wxCMD_LINE_VAL_NONE, 0 },
141 { wxCMD_LINE_SWITCH, "t", "timing",
142 "print names and mesure running time of individual test, run them",
143 wxCMD_LINE_VAL_NONE, 0 },
aa3b041e 144 { wxCMD_LINE_PARAM, NULL, NULL, "REGISTRY", wxCMD_LINE_VAL_STRING,
a81f3066 145 wxCMD_LINE_PARAM_OPTIONAL | wxCMD_LINE_PARAM_MULTIPLE },
aa3b041e 146 wxCMD_LINE_DESC_END
670ec357
VS
147 };
148
149 parser.SetDesc(cmdLineDesc);
150}
151
152// Handle command line options
153//
154bool TestApp::OnCmdLineParsed(wxCmdLineParser& parser)
155{
a81f3066
VS
156 if (parser.GetParamCount())
157 for (size_t i = 0; i < parser.GetParamCount(); i++)
158 m_registries.push_back(string(parser.GetParam(i).mb_str()));
159 else
160 m_registries.push_back("");
3e5f6c1c 161
a81f3066
VS
162 m_longlist = parser.Found(_T("longlist"));
163 m_list = m_longlist || parser.Found(_T("list"));
afd90468
VZ
164 m_timing = parser.Found(_T("timing"));
165 m_detail = !m_timing && parser.Found(_T("detail"));
670ec357 166
c0d9b217 167 return TestAppBase::OnCmdLineParsed(parser);
670ec357
VS
168}
169
170// Run
171//
172int TestApp::OnRun()
173{
2976d6cb 174 CppUnit::TextTestRunner runner;
a81f3066
VS
175
176 for (size_t i = 0; i < m_registries.size(); i++) {
177 auto_ptr<Test> test(m_registries[i].empty() ?
178 TestFactoryRegistry::getRegistry().makeTest() :
179 TestFactoryRegistry::getRegistry(m_registries[i]).makeTest());
180
181 TestSuite *suite = dynamic_cast<TestSuite*>(test.get());
182
183 if (suite && suite->countTestCases() == 0)
184 wxLogError(_T("No such test suite: %s"),
185 wxString(m_registries[i].c_str(), wxConvUTF8).c_str());
186 else if (m_list)
187 List(test.get());
188 else
189 runner.addTest(test.release());
670ec357 190 }
a81f3066 191
2976d6cb
VZ
192 if ( m_list )
193 return EXIT_SUCCESS;
194
195 runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), cout));
14dc53b2 196
86ca2b4c 197#if wxUSE_LOG
a81f3066 198 // Switch off logging unless --verbose
3e5f6c1c
WS
199 bool verbose = wxLog::GetVerbose();
200 wxLog::EnableLogging(verbose);
86ca2b4c 201#else
3e5f6c1c
WS
202 bool verbose = false;
203#endif
204
2976d6cb
VZ
205 // there is a bug
206 // (http://sf.net/tracker/index.php?func=detail&aid=1649369&group_id=11795&atid=111795)
207 // in some versions of cppunit: they write progress dots to cout (and not
208 // cerr) and don't flush it so all the dots appear at once at the end which
209 // is not very useful so unbuffer cout to work around this
210 cout.setf(ios::unitbuf);
211
afd90468
VZ
212 // add detail listener if needed
213 DetailListener detailListener(m_timing);
214 if ( m_detail || m_timing )
215 runner.eventManager().addListener(&detailListener);
216
2976d6cb 217 return runner.run("", false, true, !verbose) ? EXIT_SUCCESS : EXIT_FAILURE;
670ec357
VS
218}
219
c0d9b217
VZ
220int TestApp::OnExit()
221{
222#if wxUSE_GUI
223 delete GetTopWindow();
224#endif // wxUSE_GUI
225
226 return 0;
227}
228
670ec357
VS
229// List the tests
230//
8dae9169 231void TestApp::List(Test *test, const string& parent /*=""*/) const
670ec357 232{
670ec357 233 TestSuite *suite = dynamic_cast<TestSuite*>(test);
8dae9169
VS
234 string name;
235
bc10103e 236 if (suite) {
8dae9169
VS
237 // take the last component of the name and append to the parent
238 name = test->getName();
239 string::size_type i = name.find_last_of(".:");
f44eaed6
RN
240 if (i != string::npos)
241 name = name.substr(i + 1);
242 name = parent + "." + name;
8dae9169
VS
243
244 // drop the 1st component from the display and indent
245 if (parent != "") {
246 string::size_type j = i = name.find('.', 1);
247 while ((j = name.find('.', j + 1)) != string::npos)
248 cout << " ";
249 cout << " " << name.substr(i + 1) << "\n";
250 }
a81f3066 251
f69577be 252 typedef vector<Test*> Tests;
670ec357
VS
253 typedef Tests::const_iterator Iter;
254
f69577be 255 const Tests& tests = suite->getTests();
670ec357
VS
256
257 for (Iter it = tests.begin(); it != tests.end(); ++it)
8dae9169 258 List(*it, name);
670ec357 259 }
bc10103e
VS
260 else if (m_longlist) {
261 string::size_type i = 0;
262 while ((i = parent.find('.', i + 1)) != string::npos)
263 cout << " ";
264 cout << " " << test->getName() << "\n";
265 }
670ec357 266}