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