Changeset 2273
- Timestamp:
- 06/09/2008 11:52:56 (3 years ago)
- Location:
- box/chris/general/lib/common
- Files:
-
- 1 edited
- 1 copied
-
Test.cpp (copied) (copied from box/chris/general/lib/common/Test.h) (16 diffs)
-
Test.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
box/chris/general/lib/common/Test.cpp
r1969 r2273 2 2 // 3 3 // File 4 // Name: Test. h4 // Name: Test.cpp 5 5 // Purpose: Useful stuff for tests 6 // Created: 200 3/07/116 // Created: 2007/12/09 7 7 // 8 8 // -------------------------------------------------------------------------- 9 9 10 #ifndef TEST__H 11 #define TEST__H 10 #include "Box.h" 12 11 13 12 #include <errno.h> … … 25 24 #include <string> 26 25 27 #ifdef WIN32 28 #define BBACKUPCTL "..\\..\\bin\\bbackupctl\\bbackupctl.exe" 29 #define BBACKUPD "..\\..\\bin\\bbackupd\\bbackupd.exe" 30 #define BBSTORED "..\\..\\bin\\bbstored\\bbstored.exe" 31 #define BBACKUPQUERY "..\\..\\bin\\bbackupquery\\bbackupquery.exe" 32 #define BBSTOREACCOUNTS "..\\..\\bin\\bbstoreaccounts\\bbstoreaccounts.exe" 33 #define TEST_RETURN(actual, expected) TEST_THAT(actual == expected); 34 #else 35 #define BBACKUPCTL "../../bin/bbackupctl/bbackupctl" 36 #define BBACKUPD "../../bin/bbackupd/bbackupd" 37 #define BBSTORED "../../bin/bbstored/bbstored" 38 #define BBACKUPQUERY "../../bin/bbackupquery/bbackupquery" 39 #define BBSTOREACCOUNTS "../../bin/bbstoreaccounts/bbstoreaccounts" 40 #define TEST_RETURN(actual, expected) TEST_THAT(actual == expected*256); 41 #endif 42 43 extern int failures; 44 extern int first_fail_line; 45 extern std::string first_fail_file; 46 extern std::string bbackupd_args, bbstored_args, bbackupquery_args; 47 48 #define TEST_FAIL_WITH_MESSAGE(msg) \ 49 { \ 50 if (failures == 0) \ 51 { \ 52 first_fail_file = __FILE__; \ 53 first_fail_line = __LINE__; \ 54 } \ 55 failures++; \ 56 printf("FAILURE: " msg " at " __FILE__ "(%d)\n", __LINE__); \ 57 } 58 59 #define TEST_ABORT_WITH_MESSAGE(msg) {TEST_FAIL_WITH_MESSAGE(msg); return 1;} 60 61 #define TEST_THAT(condition) {if(!(condition)) TEST_FAIL_WITH_MESSAGE("Condition [" #condition "] failed")} 62 #define TEST_THAT_ABORTONFAIL(condition) {if(!(condition)) TEST_ABORT_WITH_MESSAGE("Condition [" #condition "] failed")} 63 64 // NOTE: The 0- bit is to allow this to work with stuff which has negative constants for flags (eg ConnectionException) 65 #define TEST_CHECK_THROWS(statement, excepttype, subtype) \ 66 { \ 67 bool didthrow = false; \ 68 try \ 69 { \ 70 statement; \ 71 } \ 72 catch(excepttype &e) \ 73 { \ 74 if(e.GetSubType() != ((unsigned int)excepttype::subtype) \ 75 && e.GetSubType() != (unsigned int)(0-excepttype::subtype)) \ 76 { \ 77 throw; \ 78 } \ 79 didthrow = true; \ 80 } \ 81 catch(...) \ 82 { \ 83 throw; \ 84 } \ 85 if(!didthrow) \ 86 { \ 87 TEST_FAIL_WITH_MESSAGE("Didn't throw exception " #excepttype "(" #subtype ")") \ 88 } \ 89 } 90 91 inline bool TestFileExists(const char *Filename) 26 #include "Test.h" 27 28 bool TestFileExists(const char *Filename) 92 29 { 93 30 struct stat st; … … 95 32 } 96 33 97 inlinebool TestDirExists(const char *Filename)34 bool TestDirExists(const char *Filename) 98 35 { 99 36 struct stat st; … … 102 39 103 40 // -1 if doesn't exist 104 in line int TestGetFileSize(const char *Filename)41 int TestGetFileSize(const char *Filename) 105 42 { 106 43 struct stat st; … … 112 49 } 113 50 114 inlinestd::string ConvertPaths(const std::string& rOriginal)51 std::string ConvertPaths(const std::string& rOriginal) 115 52 { 116 53 #ifdef WIN32 … … 136 73 } 137 74 138 in line int RunCommand(const std::string& rCommandLine)75 int RunCommand(const std::string& rCommandLine) 139 76 { 140 77 return ::system(ConvertPaths(rCommandLine).c_str()); … … 145 82 #endif 146 83 147 inline bool ServerIsAlive(int pid) 148 { 149 #ifdef WIN32 150 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid); 151 if (hProcess == NULL) 152 { 153 if (GetLastError() != ERROR_INVALID_PARAMETER) 154 { 155 printf("Failed to open process %d: error %d\n", 156 pid, (int)GetLastError()); 157 } 84 bool ServerIsAlive(int pid) 85 { 86 #ifdef WIN32 87 88 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 89 false, pid); 90 if (hProcess == NULL) 91 { 92 if (GetLastError() != ERROR_INVALID_PARAMETER) 93 { 94 BOX_ERROR("Failed to open process " << pid << 95 ": " << 96 GetErrorMessage(GetLastError())); 97 } 98 return false; 99 } 100 101 DWORD exitCode; 102 BOOL result = GetExitCodeProcess(hProcess, &exitCode); 103 CloseHandle(hProcess); 104 105 if (result == 0) 106 { 107 BOX_ERROR("Failed to get exit code for process " << 108 pid << ": " << 109 GetErrorMessage(GetLastError())) 110 return false; 111 } 112 113 if (exitCode == STILL_ACTIVE) 114 { 115 return true; 116 } 117 158 118 return false; 159 } 160 CloseHandle(hProcess);161 return true; 162 #else // !WIN32 163 if(pid == 0) return false;164 return ::kill(pid, 0) != -1; 165 #endif // WIN32166 } 167 168 in line int ReadPidFile(const char *pidFile)119 120 #else // !WIN32 121 122 if(pid == 0) return false; 123 return ::kill(pid, 0) != -1; 124 125 #endif // WIN32 126 } 127 128 int ReadPidFile(const char *pidFile) 169 129 { 170 130 if(!TestFileExists(pidFile)) … … 188 148 } 189 149 190 in line int LaunchServer(const std::string& rCommandLine, const char *pidFile)150 int LaunchServer(const std::string& rCommandLine, const char *pidFile) 191 151 { 192 152 #ifdef WIN32 … … 321 281 } 322 282 323 #define TestRemoteProcessMemLeaks(filename) \ 324 TestRemoteProcessMemLeaksFunc(filename, __FILE__, __LINE__) 325 326 inline void TestRemoteProcessMemLeaksFunc(const char *filename, 283 void TestRemoteProcessMemLeaksFunc(const char *filename, 327 284 const char* file, int line) 328 285 { … … 370 327 } 371 328 372 inlinevoid force_sync()329 void force_sync() 373 330 { 374 331 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " … … 377 334 } 378 335 379 inlinevoid wait_for_sync_start()336 void wait_for_sync_start() 380 337 { 381 338 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " … … 384 341 } 385 342 386 inlinevoid wait_for_sync_end()343 void wait_for_sync_end() 387 344 { 388 345 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " … … 391 348 } 392 349 393 inlinevoid sync_and_wait()350 void sync_and_wait() 394 351 { 395 352 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " … … 398 355 } 399 356 400 inlinevoid terminate_bbackupd(int pid)357 void terminate_bbackupd(int pid) 401 358 { 402 359 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " … … 418 375 419 376 // Wait a given number of seconds for something to complete 420 inlinevoid wait_for_operation(int seconds)377 void wait_for_operation(int seconds) 421 378 { 422 379 printf("Waiting: "); … … 432 389 } 433 390 434 inline void safe_sleep(int seconds) 435 { 391 void safe_sleep(int seconds) 392 { 393 BOX_TRACE("sleeping for " << seconds << " seconds"); 394 436 395 #ifdef WIN32 437 396 Sleep(seconds * 1000); 438 397 #else 439 398 struct timespec ts; 399 memset(&ts, 0, sizeof(ts)); 440 400 ts.tv_sec = seconds; 441 401 ts.tv_nsec = 0; 442 402 while (nanosleep(&ts, &ts) == -1 && errno == EINTR) 443 { /* sleep again */ } 403 { 404 BOX_TRACE("safe_sleep interrupted with " << 405 ts.tv_sec << "." << ts.tv_nsec << 406 " secs remaining, sleeping again"); 407 /* sleep again */ 408 } 444 409 #endif 445 } 446 447 #endif // TEST__H 410 411 BOX_TRACE("sleep finished"); 412 } -
box/chris/general/lib/common/Test.h
r2005 r2273 11 11 #define TEST__H 12 12 13 #include <errno.h> 14 #include <signal.h> 15 #include <stdio.h> 16 #include <stdlib.h> 13 #include <string> 17 14 18 #include <sys/stat.h> 19 #include <sys/types.h> 20 21 #ifdef HAVE_UNISTD_H 22 #include <unistd.h> 23 #endif 24 25 #include <string> 15 #include "Logging.h" 26 16 27 17 #ifdef WIN32 … … 54 44 } \ 55 45 failures++; \ 56 printf("FAILURE: " msg " at " __FILE__ "(%d)\n",__LINE__); \46 BOX_ERROR("FAILURE: " msg " at " __FILE__ ":" << __LINE__); \ 57 47 } 58 48 … … 63 53 64 54 // NOTE: The 0- bit is to allow this to work with stuff which has negative constants for flags (eg ConnectionException) 65 #define TEST_CHECK_THROWS(statement, excepttype, subtype) \66 { \67 bool didthrow = false; \68 try \69 { \70 statement; \71 } \72 catch(excepttype &e) \73 { \74 if(e.GetSubType() != ((unsigned int)excepttype::subtype) \75 && e.GetSubType() != (unsigned int)(0-excepttype::subtype)) \76 { \77 throw; \78 } \79 didthrow = true; \80 } \81 catch(...) \82 { \83 throw; \84 } \85 if(!didthrow) \86 { \87 TEST_FAIL_WITH_MESSAGE("Didn't throw exception " #excepttype "(" #subtype ")") \88 } \55 #define TEST_CHECK_THROWS(statement, excepttype, subtype) \ 56 { \ 57 bool didthrow = false; \ 58 try \ 59 { \ 60 statement; \ 61 } \ 62 catch(excepttype &e) \ 63 { \ 64 if(e.GetSubType() != ((unsigned int)excepttype::subtype) \ 65 && e.GetSubType() != (unsigned int)(0-excepttype::subtype)) \ 66 { \ 67 throw; \ 68 } \ 69 didthrow = true; \ 70 } \ 71 catch(...) \ 72 { \ 73 throw; \ 74 } \ 75 if(!didthrow) \ 76 { \ 77 TEST_FAIL_WITH_MESSAGE("Didn't throw exception " #excepttype "(" #subtype ")") \ 78 } \ 89 79 } 90 80 91 inline bool TestFileExists(const char *Filename) 92 { 93 struct stat st; 94 return ::stat(Filename, &st) == 0 && (st.st_mode & S_IFDIR) == 0; 95 } 81 bool TestFileExists(const char *Filename); 82 bool TestDirExists(const char *Filename); 96 83 97 inline bool TestDirExists(const char *Filename) 98 { 99 struct stat st; 100 return ::stat(Filename, &st) == 0 && (st.st_mode & S_IFDIR) == S_IFDIR; 101 } 102 103 // -1 if doesn't exist 104 inline int TestGetFileSize(const char *Filename) 105 { 106 struct stat st; 107 if(::stat(Filename, &st) == 0) 108 { 109 return st.st_size; 110 } 111 return -1; 112 } 113 114 inline std::string ConvertPaths(const std::string& rOriginal) 115 { 116 #ifdef WIN32 117 // convert UNIX paths to native 118 119 std::string converted; 120 for (size_t i = 0; i < rOriginal.size(); i++) 121 { 122 if (rOriginal[i] == '/') 123 { 124 converted += '\\'; 125 } 126 else 127 { 128 converted += rOriginal[i]; 129 } 130 } 131 return converted; 132 133 #else // !WIN32 134 return rOriginal; 135 #endif 136 } 137 138 inline int RunCommand(const std::string& rCommandLine) 139 { 140 return ::system(ConvertPaths(rCommandLine).c_str()); 141 } 142 143 #ifdef WIN32 144 #include <windows.h> 145 #endif 146 147 inline bool ServerIsAlive(int pid) 148 { 149 #ifdef WIN32 150 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid); 151 if (hProcess == NULL) 152 { 153 if (GetLastError() != ERROR_INVALID_PARAMETER) 154 { 155 printf("Failed to open process %d: error %d\n", 156 pid, (int)GetLastError()); 157 } 158 return false; 159 } 160 CloseHandle(hProcess); 161 return true; 162 #else // !WIN32 163 if(pid == 0) return false; 164 return ::kill(pid, 0) != -1; 165 #endif // WIN32 166 } 167 168 inline int ReadPidFile(const char *pidFile) 169 { 170 if(!TestFileExists(pidFile)) 171 { 172 TEST_FAIL_WITH_MESSAGE("Server didn't save PID file " 173 "(perhaps one was already running?)"); 174 return -1; 175 } 176 177 int pid = -1; 178 179 FILE *f = fopen(pidFile, "r"); 180 if(f == NULL || fscanf(f, "%d", &pid) != 1) 181 { 182 TEST_FAIL_WITH_MESSAGE("Couldn't read PID file"); 183 return -1; 184 } 185 fclose(f); 186 187 return pid; 188 } 189 190 inline int LaunchServer(const std::string& rCommandLine, const char *pidFile) 191 { 192 #ifdef WIN32 193 194 PROCESS_INFORMATION procInfo; 195 196 STARTUPINFO startInfo; 197 startInfo.cb = sizeof(startInfo); 198 startInfo.lpReserved = NULL; 199 startInfo.lpDesktop = NULL; 200 startInfo.lpTitle = NULL; 201 startInfo.dwFlags = 0; 202 startInfo.cbReserved2 = 0; 203 startInfo.lpReserved2 = NULL; 204 205 std::string cmd = ConvertPaths(rCommandLine); 206 CHAR* tempCmd = strdup(cmd.c_str()); 207 208 DWORD result = CreateProcess 209 ( 210 NULL, // lpApplicationName, naughty! 211 tempCmd, // lpCommandLine 212 NULL, // lpProcessAttributes 213 NULL, // lpThreadAttributes 214 false, // bInheritHandles 215 0, // dwCreationFlags 216 NULL, // lpEnvironment 217 NULL, // lpCurrentDirectory 218 &startInfo, // lpStartupInfo 219 &procInfo // lpProcessInformation 220 ); 221 222 free(tempCmd); 223 224 if (result == 0) 225 { 226 DWORD err = GetLastError(); 227 printf("Launch failed: %s: error %d\n", rCommandLine.c_str(), 228 (int)err); 229 return -1; 230 } 231 232 CloseHandle(procInfo.hProcess); 233 CloseHandle(procInfo.hThread); 234 235 #else // !WIN32 236 237 if(RunCommand(rCommandLine) != 0) 238 { 239 printf("Server: %s\n", rCommandLine.c_str()); 240 TEST_FAIL_WITH_MESSAGE("Couldn't start server"); 241 return -1; 242 } 243 244 #endif // WIN32 245 246 #ifdef WIN32 247 // on other platforms there is no other way to get 248 // the PID, so a NULL pidFile doesn't make sense. 249 250 if (pidFile == NULL) 251 { 252 return (int)procInfo.dwProcessId; 253 } 254 #endif 255 256 // time for it to start up 257 ::fprintf(stdout, "Starting server: %s\n", rCommandLine.c_str()); 258 ::fprintf(stdout, "Waiting for server to start: "); 259 260 for (int i = 0; i < 15; i++) 261 { 262 if (TestFileExists(pidFile)) 263 { 264 break; 265 } 266 267 #ifdef WIN32 268 if (!ServerIsAlive((int)procInfo.dwProcessId)) 269 { 270 break; 271 } 272 #endif 273 274 ::fprintf(stdout, "."); 275 ::fflush(stdout); 276 ::sleep(1); 277 } 278 279 #ifdef WIN32 280 // on Win32 we can check whether the process is alive 281 // without even checking the PID file 282 283 if (!ServerIsAlive((int)procInfo.dwProcessId)) 284 { 285 ::fprintf(stdout, "server died!\n"); 286 TEST_FAIL_WITH_MESSAGE("Server died!"); 287 return -1; 288 } 289 #endif 290 291 if (!TestFileExists(pidFile)) 292 { 293 ::fprintf(stdout, "timed out!\n"); 294 TEST_FAIL_WITH_MESSAGE("Server didn't save PID file"); 295 return -1; 296 } 297 298 ::fprintf(stdout, "done.\n"); 299 300 // wait a second for the pid to be written to the file 301 ::sleep(1); 302 303 // read pid file 304 int pid = ReadPidFile(pidFile); 305 306 #ifdef WIN32 307 // On Win32 we can check whether the PID in the pidFile matches 308 // the one returned by the system, which it always should. 309 310 if (pid != (int)procInfo.dwProcessId) 311 { 312 printf("Server wrote wrong pid to file (%s): expected %d " 313 "but found %d\n", pidFile, 314 (int)procInfo.dwProcessId, pid); 315 TEST_FAIL_WITH_MESSAGE("Server wrote wrong pid to file"); 316 return -1; 317 } 318 #endif 319 320 return pid; 321 } 84 // TestGetFileSize() returns -1 if the file doesn't exist 85 int TestGetFileSize(const char *Filename); 86 std::string ConvertPaths(const std::string& rOriginal); 87 int RunCommand(const std::string& rCommandLine); 88 bool ServerIsAlive(int pid); 89 int ReadPidFile(const char *pidFile); 90 int LaunchServer(const std::string& rCommandLine, const char *pidFile); 322 91 323 92 #define TestRemoteProcessMemLeaks(filename) \ 324 93 TestRemoteProcessMemLeaksFunc(filename, __FILE__, __LINE__) 325 94 326 inline void TestRemoteProcessMemLeaksFunc(const char *filename, 327 const char* file, int line) 328 { 329 #ifdef BOX_MEMORY_LEAK_TESTING 330 // Does the file exist? 331 if(!TestFileExists(filename)) 332 { 333 if (failures == 0) 334 { 335 first_fail_file = file; 336 first_fail_line = line; 337 } 338 ++failures; 339 printf("FAILURE: MemLeak report not available (file %s) " 340 "at %s:%d\n", filename, file, line); 341 } 342 else 343 { 344 // Is it empty? 345 if(TestGetFileSize(filename) > 0) 346 { 347 if (failures == 0) 348 { 349 first_fail_file = file; 350 first_fail_line = line; 351 } 352 ++failures; 353 printf("FAILURE: Memory leaks found in other process " 354 "(file %s) at %s:%d\n==========\n", 355 filename, file, line); 356 FILE *f = fopen(filename, "r"); 357 char linebuf[512]; 358 while(::fgets(linebuf, sizeof(linebuf), f) != 0) 359 { 360 printf("%s", linebuf); 361 } 362 fclose(f); 363 printf("==========\n"); 364 } 365 366 // Delete it 367 ::unlink(filename); 368 } 369 #endif 370 } 95 void TestRemoteProcessMemLeaksFunc(const char *filename, 96 const char* file, int line); 371 97 372 inline void force_sync() 373 { 374 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " 375 "force-sync") == 0); 376 TestRemoteProcessMemLeaks("bbackupctl.memleaks"); 377 } 378 379 inline void wait_for_sync_start() 380 { 381 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " 382 "wait-for-sync") == 0); 383 TestRemoteProcessMemLeaks("bbackupctl.memleaks"); 384 } 385 386 inline void wait_for_sync_end() 387 { 388 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " 389 "wait-for-end") == 0); 390 TestRemoteProcessMemLeaks("bbackupctl.memleaks"); 391 } 392 393 inline void sync_and_wait() 394 { 395 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " 396 "sync-and-wait") == 0); 397 TestRemoteProcessMemLeaks("bbackupctl.memleaks"); 398 } 399 400 inline void terminate_bbackupd(int pid) 401 { 402 TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " 403 "terminate") == 0); 404 TestRemoteProcessMemLeaks("bbackupctl.memleaks"); 405 406 for (int i = 0; i < 20; i++) 407 { 408 if (!ServerIsAlive(pid)) break; 409 fprintf(stdout, "."); 410 fflush(stdout); 411 sleep(1); 412 } 413 414 TEST_THAT(!ServerIsAlive(pid)); 415 TestRemoteProcessMemLeaks("bbackupd.memleaks"); 416 } 417 98 // functions to send commands to bbackupd 99 void force_sync(); 100 void wait_for_sync_start(); 101 void wait_for_sync_end(); 102 void sync_and_wait(); 103 void terminate_bbackupd(int pid); 418 104 419 105 // Wait a given number of seconds for something to complete 420 inline void wait_for_operation(int seconds) 421 { 422 printf("Waiting: "); 423 fflush(stdout); 424 for(int l = 0; l < seconds; ++l) 425 { 426 sleep(1); 427 printf("."); 428 fflush(stdout); 429 } 430 printf(" done.\n"); 431 fflush(stdout); 432 } 106 void wait_for_operation(int seconds); 433 107 434 inline void safe_sleep(int seconds) 435 { 436 #ifdef WIN32 437 Sleep(seconds * 1000); 438 #else 439 struct timespec ts; 440 memset(&ts, 0, sizeof(ts)); 441 ts.tv_sec = seconds; 442 ts.tv_nsec = 0; 443 BOX_TRACE("sleeping for " << seconds << " seconds"); 444 while (nanosleep(&ts, &ts) == -1 && errno == EINTR) 445 { 446 BOX_TRACE("safe_sleep interrupted with " << 447 ts.tv_sec << "." << ts.tv_nsec << 448 " secs remaining, sleeping again"); 449 /* sleep again */ 450 } 451 #endif 452 } 108 // Sleep without interruption on Unix (resleep if interrupted) 109 void safe_sleep(int seconds); 453 110 454 111 #endif // TEST__H
Note: See TracChangeset
for help on using the changeset viewer.
