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 _EXPORT 21 BThreadedTestCase::~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 35 void 36 BThreadedTestCase::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 60 void 61 BThreadedTestCase::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 92 void 93 BThreadedTestCase::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 109 bool 110 BThreadedTestCase::RegisterForUse() { 111 if (!fInUse) { 112 fInUse = true; 113 return true; 114 } else 115 return false; 116 } 117 118 _EXPORT 119 void 120 BThreadedTestCase::UnregisterForUse() { 121 fInUse = false; 122 } 123 124 _EXPORT 125 vector<string>& 126 BThreadedTestCase::AcquireUpdateList() { 127 fUpdateLock->Lock(); 128 return fUpdateList; 129 } 130 131 _EXPORT 132 void 133 BThreadedTestCase::ReleaseUpdateList() { 134 fUpdateLock->Unlock(); 135 } 136