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