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