Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #ifdef WNT
30 : : #include <windows.h>
31 : : #endif
32 : :
33 : : #include <cstdlib>
34 : : #include <iostream>
35 : : #include <limits>
36 : : #include <string>
37 : : #include <sal/types.h>
38 : : #include "cppunittester/protectorfactory.hxx"
39 : : #include "osl/module.h"
40 : : #include "osl/module.hxx"
41 : : #include "osl/thread.h"
42 : : #include "rtl/process.h"
43 : : #include "rtl/string.h"
44 : : #include "rtl/string.hxx"
45 : : #include "rtl/textcvt.h"
46 : : #include "rtl/ustring.hxx"
47 : : #include "sal/main.h"
48 : : #include "sal/types.h"
49 : :
50 : : #include "cppunit/CompilerOutputter.h"
51 : : #include "cppunit/TestResult.h"
52 : : #include "cppunit/TestResultCollector.h"
53 : : #include "cppunit/TestRunner.h"
54 : : #include "cppunit/extensions/TestFactoryRegistry.h"
55 : : #include "cppunit/plugin/PlugInManager.h"
56 : : #include "cppunit/plugin/DynamicLibraryManagerException.h"
57 : : #include "cppunit/portability/Stream.h"
58 : :
59 : : #include "boost/noncopyable.hpp"
60 : : #include "boost/ptr_container/ptr_vector.hpp"
61 : :
62 : : namespace {
63 : :
64 : 0 : void usageFailure() {
65 : : std::cerr
66 : : << ("Usage: cppunittester (--protector <shared-library-path>"
67 : 0 : " <function-symbol>)* <shared-library-path>")
68 : 0 : << std::endl;
69 : 0 : std::exit(EXIT_FAILURE);
70 : : }
71 : :
72 : 1954 : rtl::OUString getArgument(sal_Int32 index) {
73 : 1954 : rtl::OUString arg;
74 [ + - ]: 1954 : rtl_getAppCommandArg(index, &arg.pData);
75 : 1954 : return arg;
76 : : }
77 : :
78 : 0 : std::string convertLazy(rtl::OUString const & s16) {
79 [ # # ][ # # ]: 0 : rtl::OString s8(rtl::OUStringToOString(s16, osl_getThreadTextEncoding()));
80 : : return std::string(
81 : : s8.getStr(),
82 : 0 : ((static_cast< sal_uInt32 >(s8.getLength())
83 : 0 : > (std::numeric_limits< std::string::size_type >::max)())
84 : : ? (std::numeric_limits< std::string::size_type >::max)()
85 [ # # ][ # # ]: 0 : : static_cast< std::string::size_type >(s8.getLength())));
86 : : }
87 : :
88 : : //Output how long each test took
89 : : class TimingListener
90 : : : public CppUnit::TestListener
91 : : , private boost::noncopyable
92 : : {
93 : : public:
94 : : void startTest( CppUnit::Test *)
95 : : {
96 : : m_nStartTime = osl_getGlobalTimer();
97 : : }
98 : :
99 : : void endTest( CppUnit::Test *test )
100 : : {
101 : : sal_uInt32 nEndTime = osl_getGlobalTimer();
102 : : std::cout << test->getName() << ": " << nEndTime-m_nStartTime
103 : : << "ms" << std::endl;
104 : : }
105 : :
106 : : private:
107 : : sal_uInt32 m_nStartTime;
108 : : };
109 : :
110 : : //Allow the whole uniting testing framework to be run inside a "Protector"
111 : : //which knows about uno exceptions, so it can print the content of the
112 : : //exception before falling over and dying
113 [ - + ]: 428 : class CPPUNIT_API ProtectedFixtureFunctor
114 : : : public CppUnit::Functor
115 : : , private boost::noncopyable
116 : : {
117 : : private:
118 : : const std::string &testlib;
119 : : const std::string &args;
120 : : std::vector<CppUnit::Protector *> &protectors;
121 : : CppUnit::TestResult &result;
122 : : public:
123 : 428 : ProtectedFixtureFunctor(const std::string& testlib_, const std::string &args_, std::vector<CppUnit::Protector*> &protectors_, CppUnit::TestResult &result_)
124 : : : testlib(testlib_)
125 : : , args(args_)
126 : : , protectors(protectors_)
127 : 428 : , result(result_)
128 : : {
129 : 428 : }
130 : 428 : bool run() const
131 : : {
132 : : #ifdef DISABLE_DYNLOADING
133 : : // For iOS cppunit plugins aren't really "plugins" (shared
134 : : // libraries), but just static archives. In the real main
135 : : // program of a cppunit app, which calls the lo_main() that
136 : : // the SAL_IMPLEMENT_MAIN() below expands to, we specifically
137 : : // call the initialize methods of the CppUnitTestPlugIns that
138 : : // we statically link to the app executable.
139 : : #else
140 [ + - ]: 428 : CppUnit::PlugInManager manager;
141 : : try {
142 [ + - ][ + - ]: 428 : manager.load(testlib, args);
[ + - ]
143 [ # # ]: 0 : } catch (const CppUnit::DynamicLibraryManagerException &e) {
144 [ # # ]: 0 : fprintf(stderr, "%s\n", e.what());
145 : 0 : return false;
146 : : }
147 : : #endif
148 [ + - ]: 428 : CppUnit::TestRunner runner;
149 [ + - ][ + - ]: 428 : runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
[ + - ][ + - ]
150 : :
151 [ + - ]: 428 : CppUnit::TestResultCollector collector;
152 [ + - ]: 428 : result.addListener(&collector);
153 : :
154 : : #ifdef TIMETESTS
155 : : TimingListener timer;
156 : : result.addListener(&timer);
157 : : #endif
158 : :
159 [ + + ]: 794 : for (size_t i = 0; i < protectors.size(); ++i)
160 [ + - ]: 366 : result.pushProtector(protectors[i]);
161 : :
162 [ + - ][ + - ]: 428 : runner.run(result);
163 : :
164 [ + + ]: 794 : for (size_t i = 0; i < protectors.size(); ++i)
165 [ + - ]: 366 : result.popProtector();
166 : :
167 [ + - ][ + - ]: 428 : CppUnit::CompilerOutputter(&collector, CppUnit::stdCErr()).write();
[ + - ][ + - ]
168 [ + - ][ + - ]: 428 : return collector.wasSuccessful();
[ + - ][ + - ]
169 : : }
170 : 0 : virtual bool operator()() const
171 : : {
172 : 0 : return run();
173 : : }
174 : : };
175 : :
176 : : }
177 : :
178 : 428 : SAL_IMPLEMENT_MAIN() {
179 : : #ifdef WNT
180 : : //Disable Dr-Watson in order to crash simply without popup dialogs under
181 : : //windows
182 : : DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
183 : : SetErrorMode(SEM_NOGPFAULTERRORBOX|dwMode);
184 : : #ifdef _DEBUG // These functions are present only in the debgging runtime
185 : : _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE);
186 : : _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
187 : : _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE);
188 : : _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
189 : : _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG|_CRTDBG_MODE_FILE);
190 : : _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
191 : : #endif
192 : : #endif
193 : :
194 [ + - ]: 428 : boost::ptr_vector<osl::Module> modules;
195 [ + - ]: 428 : std::vector<CppUnit::Protector *> protectors;
196 [ + - ]: 428 : CppUnit::TestResult result;
197 [ + - ]: 428 : std::string args;
198 [ + - ]: 428 : std::string testlib;
199 : 428 : sal_uInt32 index = 0;
200 [ + - ][ + + ]: 1650 : while (index < rtl_getAppCommandArgCount())
201 : : {
202 [ + - ]: 1222 : rtl::OUString arg = getArgument(index);
203 [ + + ]: 1222 : if ( arg != "--protector" )
204 : : {
205 [ + + ]: 856 : if (testlib.empty())
206 : : {
207 [ + - ][ + - ]: 428 : testlib = rtl::OUStringToOString(arg, osl_getThreadTextEncoding()).getStr();
[ + - ]
208 [ + - ]: 428 : args += testlib;
209 : : }
210 : : else
211 : : {
212 [ + - ]: 428 : args += ' ';
213 [ + - ][ + - ]: 428 : args += rtl::OUStringToOString(arg, osl_getThreadTextEncoding()).getStr();
[ + - ]
214 : : }
215 : 856 : ++index;
216 : 856 : continue;
217 : : }
218 [ + - ][ - + ]: 366 : if (rtl_getAppCommandArgCount() - index < 3) {
219 [ # # ]: 0 : usageFailure();
220 : : }
221 [ + - ]: 366 : rtl::OUString lib(getArgument(index + 1));
222 [ + - ]: 366 : rtl::OUString sym(getArgument(index + 2));
223 : : #ifndef DISABLE_DYNLOADING
224 [ + - ][ + - ]: 366 : modules.push_back(new osl::Module(lib, SAL_LOADMODULE_GLOBAL));
[ + - ]
225 [ + - ][ + - ]: 366 : oslGenericFunction fn = modules.back().getFunctionSymbol(sym);
226 : : #else
227 : : oslGenericFunction fn;
228 : : if (sym == "unoexceptionprotector")
229 : : fn = (oslGenericFunction) unoexceptionprotector;
230 : : else if (sym == "unobootstrapprotector")
231 : : fn = (oslGenericFunction) unobootstrapprotector;
232 : : else
233 : : {
234 : : fprintf(stderr, "Only unoexceptionprotector or unobootstrapprotector protectors allowed\n");
235 : : assert(!"unrecognized protector");
236 : : }
237 : : #endif
238 : : CppUnit::Protector *protector = fn == 0
239 : : ? 0
240 [ + - ][ + - ]: 366 : : (*reinterpret_cast< cppunittester::ProtectorFactory * >(fn))();
241 [ - + ]: 366 : if (protector == 0) {
242 : : std::cerr
243 [ # # ][ # # ]: 0 : << "Failure instantiating protector \"" << convertLazy(lib)
[ # # ]
244 [ # # ][ # # ]: 0 : << "\", \"" << convertLazy(sym) << '"' << std::endl;
[ # # ][ # # ]
[ # # ]
245 : 0 : std::exit(EXIT_FAILURE);
246 : : }
247 [ + - ]: 366 : protectors.push_back(protector);
248 : 366 : index+=3;
249 [ + + ]: 1222 : }
250 : :
251 [ + - ]: 428 : ProtectedFixtureFunctor tests(testlib, args, protectors, result);
252 [ + - ]: 428 : bool ok = tests.run();
253 : :
254 [ + - ][ + - ]: 428 : return ok ? EXIT_SUCCESS : EXIT_FAILURE;
[ + - ][ + - ]
255 [ + - ][ + - ]: 1284 : }
256 : :
257 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|