xref: /haiku/src/tools/cppunit/ThreadedTestCase.cpp (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 #include <TestShell.h>
2 #include <ThreadedTestCase.h>
3 #include <Autolock.h>
4 #include <stdio.h>
5 #include <stdarg.h>
6 
7 using std::map;
8 using std::string;
9 using std::vector;
10 
11 _EXPORT
12 BThreadedTestCase::BThreadedTestCase(string name, string progressSeparator)
13 	: BTestCase(name)
14 	, fInUse(false)
15 	, fProgressSeparator(progressSeparator)
16 	, fUpdateLock(new BLocker())
17 {
18 }
19 
20 _EXPORT
21 BThreadedTestCase::~BThreadedTestCase() {
22 	// Kill our locker
23 	delete fUpdateLock;
24 
25 	// Clean up
26 	for (map<thread_id, ThreadSubTestInfo*>::iterator i = fNumberMap.begin();
27 		   i != fNumberMap.end();
28 		     i++)
29 	{
30 		delete i->second;
31 	}
32 }
33 
34 _EXPORT
35 void
36 BThreadedTestCase::NextSubTest() {
37 	// Find out what thread we're in
38 	thread_id id = find_thread(NULL);
39 
40 	{
41 		// Acquire the update lock
42 		BAutolock lock(fUpdateLock);
43 		map<thread_id, ThreadSubTestInfo*>::iterator i = fNumberMap.find(id);
44 		if (i != fNumberMap.end() && i->second) {
45 			// Handle multi-threaded case
46 			ThreadSubTestInfo *info = i->second;
47 			char num[32];
48 			sprintf(num, "%ld", info->subTestNum++);
49 			string str = string("[") + info->name + fProgressSeparator + num + "]";
50 			fUpdateList.push_back(str);
51 			return;
52 		}
53 	}
54 
55 	// Handle single-threaded case
56 	BTestCase::NextSubTest();
57 }
58 
59 _EXPORT
60 void
61 BThreadedTestCase::Outputf(const char *str, ...) {
62 	if (BTestShell::GlobalBeVerbose()) {
63 		// Figure out if this is a multithreaded test or not
64 		thread_id id = find_thread(NULL);
65 		bool isSingleThreaded;
66 		{
67 			BAutolock lock(fUpdateLock);
68 			isSingleThreaded = fNumberMap.find(id) == fNumberMap.end();
69 		}
70 		if (isSingleThreaded) {
71 			va_list args;
72 			va_start(args, str);
73 			vprintf(str, args);
74 			va_end(args);
75 			fflush(stdout);
76 		} else {
77 			va_list args;
78 			va_start(args, str);
79 			char msg[1024];	// Need a longer string? Change the constant or change the function. :-)
80 			vsprintf(msg, str, args);
81 			va_end(args);
82 			{
83 				// Acquire the update lock and post our update
84 				BAutolock lock(fUpdateLock);
85 				fUpdateList.push_back(string(msg));
86 			}
87 		}
88 	}
89 }
90 
91 _EXPORT
92 void
93 BThreadedTestCase::InitThreadInfo(thread_id id, string threadName) {
94 	BAutolock lock(fUpdateLock);	// Lock the number map
95 	map<thread_id, ThreadSubTestInfo*>::iterator i = fNumberMap.find(id);
96 	if (i != fNumberMap.end() && i->second) {
97 		i->second->name = threadName;
98 		i->second->subTestNum = 0;
99 	} else {
100 		// New addition
101 		ThreadSubTestInfo *info = new ThreadSubTestInfo();
102 		info->name = threadName;
103 		info->subTestNum = 0;
104 		fNumberMap[id] = info;
105 	}
106 }
107 
108 _EXPORT
109 bool
110 BThreadedTestCase::RegisterForUse() {
111 	if (!fInUse) {
112 		fInUse = true;
113 		return true;
114 	} else
115 		return false;
116 }
117 
118 _EXPORT
119 void
120 BThreadedTestCase::UnregisterForUse() {
121 	fInUse = false;
122 }
123 
124 _EXPORT
125 vector<string>&
126 BThreadedTestCase::AcquireUpdateList() {
127 	fUpdateLock->Lock();
128 	return fUpdateList;
129 }
130 
131 _EXPORT
132 void
133 BThreadedTestCase::ReleaseUpdateList() {
134 	fUpdateLock->Unlock();
135 }
136