TestShell.h revision 73e180c9
1#ifndef _beos_test_shell_h_
2#define _beos_test_shell_h_
3
4#include <LockerSyncObject.h>
5#include <cppunit/Exception.h>
6#include <cppunit/Test.h>
7#include <cppunit/TestListener.h>
8#include <cppunit/TestResult.h>
9#include <cppunit/TestResultCollector.h>
10#include <image.h>
11#include <TestSuite.h>
12#include <map>
13#include <set>
14#include <string>
15
16class BDirectory;
17class BLocker;
18class BPath;
19
20class ElfSymbolPatchGroup;
21
22// Defines SuiteFunction to be a pointer to a function that
23// takes no arguments and returns a pointer to a CppUnit::Test
24typedef CppUnit::Test* (*SuiteFunction)(void);
25
26// This is just absurd to have to type...
27typedef CppUnit::SynchronizedObject::SynchronizationObject SyncObject;
28
29/*!	\brief Executes a statement that is supposed to call debugger().
30	An exception is thrown if the debugger is not invoked by the
31	statement.
32*/
33#define CPPUNIT_ASSERT_DEBUGGER(statement)					\
34	BTestShell::GlobalShell()->ExpectDebuggerCall();		\
35	statement;												\
36	::CppUnit::Asserter::failIf(							\
37		!BTestShell::GlobalShell()->WasDebuggerCalled(),	\
38		(#statement),										\
39		CPPUNIT_SOURCELINE() );
40
41
42//! BeOS savvy command line interface for the CppUnit testing framework.
43/*! This class provides a fully functional command-line testing interface
44	built on top of the CppUnit testing library. You add named test suites
45	via AddSuite(), and then call Run(), which does all the dirty work. The
46	user can get a list of each test installed via AddSuite(), and optionally
47	can opt to run only a specified set of them.
48*/
49class CPPUNIT_API BTestShell {
50public:
51	BTestShell(const std::string &description = "", SyncObject *syncObject = 0);
52	virtual ~BTestShell();
53
54	// This function is used to add the tests for a given kit (as contained
55	// in a BTestSuite object) to the list of available tests. The shell assumes
56	// ownership of the BTestSuite object. Each test in the kit is added to
57	// the list of tests via a call to AddTest(string
58	status_t AddSuite(BTestSuite *kit);
59
60	// This function is used to add test suites to the list of available
61	// tests. The test pointer may not be NULL. The name given is the name that
62	// will be presented when the program is run with "--list" as an argument.
63	// Usually the given suite would be a test suite for an entire class, but
64	// that's not a requirement.
65	void AddTest(const std::string &name, CppUnit::Test* test);
66
67	// This function loads all the test addons it finds in the given
68	// directory, returning the number of tests actually loaded.
69	int32 LoadSuitesFrom(BDirectory *libDir);
70
71	// This is the function you call after you've added all your test
72	// suites with calls to AddSuite(). It runs the test, or displays
73	// help, or lists installed tests, or whatever, depending on the
74	// command-line arguments passed in.
75	int Run(int argc, char *argv[]);
76
77	// Verbosity Level enumeration and accessor function
78	enum VerbosityLevel { v0, v1, v2, v3, v4 };
79	VerbosityLevel Verbosity() const;
80
81	// Returns true if verbosity is high enough that individual tests are
82	// allowed to make noise.
83	bool BeVerbose() const { return Verbosity() >= v2; };
84
85	static bool GlobalBeVerbose() { return (fGlobalShell ? fGlobalShell->BeVerbose() : true); };
86
87	// Returns a pointer to a global BTestShell object. This function is
88	// something of a hack, used to give BTestCase and its subclasses
89	// access to verbosity information. Don't rely on it if you don't
90	// have to (and always make sure the pointer it returns isn't NULL
91	// before you try to use it :-).
92	static BTestShell* GlobalShell() { return fGlobalShell; };
93
94	// Sets the global BTestShell pointer. The BTestShell class does
95	// not assume ownership of the object.
96	static void SetGlobalShell(BTestShell *shell) { fGlobalShell = shell; };
97
98	const char* TestDir() const;
99	static const char* GlobalTestDir() { return (fGlobalShell ? fGlobalShell->TestDir() : NULL); };
100
101	void ExpectDebuggerCall();
102	bool WasDebuggerCalled();
103
104protected:
105	typedef std::map<std::string, CppUnit::Test*> TestMap;
106	typedef std::map<std::string, BTestSuite*> SuiteMap;
107
108	VerbosityLevel fVerbosityLevel;
109	std::set<std::string> fTestsToRun;
110	std::set<std::string> fSuitesToRun;
111	TestMap fTests;
112	SuiteMap fSuites;
113	std::set<std::string> fLibDirs;
114	CppUnit::TestResult fTestResults;
115	CppUnit::TestResultCollector fResultsCollector;
116	std::string fDescription;
117	static BTestShell* fGlobalShell;
118	static const char indent[];
119	bool fListTestsAndExit;
120	BPath *fTestDir;
121	int32 fTLSDebuggerCall;
122
123	BLocker *fPatchGroupLocker;
124	ElfSymbolPatchGroup *fPatchGroup;
125	void (*fOldDebuggerHook)(const char*);
126	image_id (*fOldLoadAddOnHook)(const char*);
127	status_t (*fOldUnloadAddOnHook)(image_id);
128
129	//! Prints a brief description of the program.
130	virtual void PrintDescription(int argc, char *argv[]);
131
132	//! Prints out command line argument instructions
133	void PrintHelp();
134
135	/*! \brief Prints out the list of valid command line arguments.
136		Called by PrintHelp().
137	*/
138	virtual void PrintValidArguments();
139
140	//! Prints out a list of all the currently available tests
141	void PrintInstalledTests();
142
143	/*! \brief Handles command line arguments; returns true if everything goes
144		okay, false if not (or if the program just needs to terminate without
145		running any tests). Modifies settings in "settings" as necessary.
146	*/
147	bool ProcessArguments(int argc, char *argv[]);
148
149	//! Processes a single argument, given by the \c arg parameter.
150	virtual bool ProcessArgument(std::string arg, int argc, char *argv[]);
151
152	//! Makes any necessary pre-test preparations
153	void InitOutput();
154
155	/*! \brief Prints out the test results in the proper format per
156		the specified verbosity level.
157	*/
158	void PrintResults();
159
160	/*! \brief Searches all the paths in \c fLibDirs, loading any dynamically
161		loadable suites it finds.
162	*/
163	virtual void LoadDynamicSuites();
164
165	//! Sets the current test directory.
166	void UpdateTestDir(char *argv[]);
167
168	void InstallPatches();
169	void UninstallPatches();
170
171private:
172	//! Prevents the use of the copy constructor.
173	BTestShell( const BTestShell &copy );
174
175	//! Prevents the use of the copy operator.
176	void operator =( const BTestShell &copy );
177
178	void _Debugger(const char* message);
179	image_id _LoadAddOn(const char* path);
180	status_t _UnloadAddOn(image_id image);
181
182	static void _DebuggerHook(const char* message);
183	static image_id _LoadAddOnHook(const char* path);
184	static status_t _UnloadAddOnHook(image_id image);
185};	// class BTestShell
186
187#endif // _beos_test_shell_h_
188