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