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 21_EXPORT 22BThreadedTestCase::~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 36void 37BThreadedTestCase::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 63void 64BThreadedTestCase::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 98void 99BThreadedTestCase::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 116bool 117BThreadedTestCase::RegisterForUse() { 118 if (!fInUse) { 119 fInUse = true; 120 return true; 121 } else 122 return false; 123} 124 125 126_EXPORT 127void 128BThreadedTestCase::UnregisterForUse() { 129 fInUse = false; 130} 131 132 133_EXPORT 134vector<string>& 135BThreadedTestCase::AcquireUpdateList() { 136 fUpdateLock->Lock(); 137 return fUpdateList; 138} 139 140 141_EXPORT 142void 143BThreadedTestCase::ReleaseUpdateList() { 144 fUpdateLock->Unlock(); 145} 146