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