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