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
BThreadedTestCase(string name,string progressSeparator)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
~BThreadedTestCase()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
NextSubTest()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
Outputf(const char * str,...)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
InitThreadInfo(thread_id id,string threadName)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
RegisterForUse()117 BThreadedTestCase::RegisterForUse() {
118 if (!fInUse) {
119 fInUse = true;
120 return true;
121 } else
122 return false;
123 }
124
125
126 _EXPORT
127 void
UnregisterForUse()128 BThreadedTestCase::UnregisterForUse() {
129 fInUse = false;
130 }
131
132
133 _EXPORT
134 vector<string>&
AcquireUpdateList()135 BThreadedTestCase::AcquireUpdateList() {
136 fUpdateLock->Lock();
137 return fUpdateList;
138 }
139
140
141 _EXPORT
142 void
ReleaseUpdateList()143 BThreadedTestCase::ReleaseUpdateList() {
144 fUpdateLock->Unlock();
145 }
146