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