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