diff options
author | Chris Wilson <chris+github@qwirx.com> | 2007-03-10 16:12:01 +0000 |
---|---|---|
committer | Chris Wilson <chris+github@qwirx.com> | 2007-03-10 16:12:01 +0000 |
commit | 7ee217c02aa7265f3253781b1a4eece198fb6e3d (patch) | |
tree | 18075de1884bf33f0bf99c7f135f4419a3f67cb4 /lib/common/Test.h | |
parent | 61af1d8fe20580d59a760f53e63cc984861e7324 (diff) |
Moved SendCommands(), HUPServer(), KillServer() to lib/server/ServerCommands.h.
All of these use lib/server/WinNamedPipeStream on Win32, so they don't
belong in lib/common.
Made LaunchServer() work on Win32.
Added constants for paths to executables, for use in tests, removing the
need for #ifdefs and clumsy DIRECTORY_SEPARATORs in paths.
Added terminate_bbackupd() and wait_for_operation() functions.
Update unit tests to #include "ServerControl.h" if they need it.
(refs #3)
Diffstat (limited to 'lib/common/Test.h')
-rw-r--r-- | lib/common/Test.h | 331 |
1 files changed, 177 insertions, 154 deletions
diff --git a/lib/common/Test.h b/lib/common/Test.h index b7b96c06..6a517b1a 100644 --- a/lib/common/Test.h +++ b/lib/common/Test.h @@ -92,7 +92,7 @@ inline int TestGetFileSize(const char *Filename) return -1; } -inline int RunCommand(const char *pCommandLine) +inline std::string ConvertPaths(const char *pCommandLine) { #ifdef WIN32 // convert UNIX paths to native @@ -114,7 +114,37 @@ inline int RunCommand(const char *pCommandLine) std::string command = pCommandLine; #endif - return ::system(command.c_str()); + return command; +} + +inline int RunCommand(const char *pCommandLine) +{ + return ::system(ConvertPaths(pCommandLine).c_str()); +} + +#ifdef WIN32 +#include <windows.h> +#endif + +inline bool ServerIsAlive(int pid) +{ +#ifdef WIN32 + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, pid); + if (hProcess == NULL) + { + if (GetLastError() != ERROR_INVALID_PARAMETER) + { + printf("Failed to open process %d: error %d\n", + pid, (int)GetLastError()); + } + return false; + } + CloseHandle(hProcess); + return true; +#else // !WIN32 + if(pid == 0) return false; + return ::kill(pid, 0) != -1; +#endif // WIN32 } inline int ReadPidFile(const char *pidFile) @@ -141,192 +171,136 @@ inline int ReadPidFile(const char *pidFile) inline int LaunchServer(const char *pCommandLine, const char *pidFile) { - if(RunCommand(pCommandLine) != 0) - { - printf("Server: %s\n", pCommandLine); - TEST_FAIL_WITH_MESSAGE("Couldn't start server"); - return -1; - } - - // give it time to start up - ::sleep(1); - - // read pid file - int pid = ReadPidFile(pidFile); +#ifdef WIN32 - if(pid == -1) + PROCESS_INFORMATION procInfo; + + STARTUPINFO startInfo; + startInfo.cb = sizeof(startInfo); + startInfo.lpReserved = NULL; + startInfo.lpDesktop = NULL; + startInfo.lpTitle = NULL; + startInfo.dwFlags = 0; + startInfo.cbReserved2 = 0; + startInfo.lpReserved2 = NULL; + + std::string cmd = ConvertPaths(pCommandLine); + CHAR* tempCmd = strdup(cmd.c_str()); + + DWORD result = CreateProcess + ( + NULL, // lpApplicationName, naughty! + tempCmd, // lpCommandLine + NULL, // lpProcessAttributes + NULL, // lpThreadAttributes + false, // bInheritHandles + 0, // dwCreationFlags + NULL, // lpEnvironment + NULL, // lpCurrentDirectory + &startInfo, // lpStartupInfo + &procInfo // lpProcessInformation + ); + + free(tempCmd); + + if (result == 0) { - // helps with debugging: - printf("Server: %s (pidfile %s)\n", pCommandLine, pidFile); + DWORD err = GetLastError(); + printf("Launch failed: %s: error %d\n", pCommandLine, (int)err); + return -1; } - return pid; -} - -#ifdef WIN32 - -#include "WinNamedPipeStream.h" -#include "IOStreamGetLine.h" -#include "BoxPortsAndFiles.h" + CloseHandle(procInfo.hProcess); + CloseHandle(procInfo.hThread); -bool SendCommands(const std::string& rCmd) -{ - WinNamedPipeStream connection; +#else // !WIN32 - try - { - connection.Connect(BOX_NAMED_PIPE_NAME); - } - catch(...) + if(RunCommand(pCommandLine) != 0) { - printf("Failed to connect to daemon control socket.\n"); - return false; + printf("Server: %s\n", pCommandLine); + TEST_FAIL_WITH_MESSAGE("Couldn't start server"); + return -1; } - // For receiving data - IOStreamGetLine getLine(connection); - - // Wait for the configuration summary - std::string configSummary; - if(!getLine.GetLine(configSummary)) - { - printf("Failed to receive configuration summary from daemon\n"); - return false; - } +#endif // WIN32 - // Was the connection rejected by the server? - if(getLine.IsEOF()) - { - printf("Server rejected the connection.\n"); - return false; - } + #ifdef WIN32 + // on other platforms there is no other way to get + // the PID, so a NULL pidFile doesn't make sense. - // Decode it - int autoBackup, updateStoreInterval, minimumFileAge, maxUploadWait; - if(::sscanf(configSummary.c_str(), "bbackupd: %d %d %d %d", - &autoBackup, &updateStoreInterval, - &minimumFileAge, &maxUploadWait) != 4) + if (pidFile == NULL) { - printf("Config summary didn't decode\n"); - return false; + return (int)procInfo.dwProcessId; } + #endif - std::string cmds; - bool expectResponse; - - if (rCmd != "") - { - cmds = rCmd; - cmds += "\nquit\n"; - expectResponse = true; - } - else - { - cmds = "quit\n"; - expectResponse = false; - } - - connection.Write(cmds.c_str(), cmds.size()); - - // Read the response - std::string line; - bool statusOk = !expectResponse; + // time for it to start up + ::fprintf(stdout, "Starting server: %s\n", pCommandLine); + ::fprintf(stdout, "Waiting for server to start: "); - while (expectResponse && !getLine.IsEOF() && getLine.GetLine(line)) + for (int i = 0; i < 15; i++) { - // Is this an OK or error line? - if (line == "ok") - { - statusOk = true; - } - else if (line == "error") + if (TestFileExists(pidFile)) { - printf("ERROR (%s)\n", rCmd.c_str()); break; } - else + + #ifdef WIN32 + if (!ServerIsAlive((int)procInfo.dwProcessId)) { - printf("WARNING: Unexpected response to command '%s': " - "%s", rCmd.c_str(), line.c_str()); + break; } - } - - return statusOk; -} + #endif -inline bool ServerIsAlive(int pid) -{ - return SendCommands(""); -} - -inline bool HUPServer(int pid) -{ - return SendCommands("reload"); -} - -inline bool KillServerInternal(int pid) -{ - bool sent = SendCommands("terminate"); - TEST_THAT(sent); - return sent; -} - -#else // !WIN32 - -inline bool ServerIsAlive(int pid) -{ - if(pid == 0) return false; - return ::kill(pid, 0) != -1; -} - -inline bool HUPServer(int pid) -{ - if(pid == 0) return false; - return ::kill(pid, SIGHUP) != -1; -} - -inline bool KillServerInternal(int pid) -{ - if(pid == 0 || pid == -1) return false; - bool killed = (::kill(pid, SIGTERM) == 0); - TEST_THAT(killed); - return killed; -} + ::fprintf(stdout, "."); + ::fflush(stdout); + ::sleep(1); + } -#endif // WIN32 + #ifdef WIN32 + // on Win32 we can check whether the process is alive + // without even checking the PID file -inline bool KillServer(int pid) -{ - if (!KillServerInternal(pid)) + if (!ServerIsAlive((int)procInfo.dwProcessId)) { - return false; + ::fprintf(stdout, "server died!\n"); + TEST_FAIL_WITH_MESSAGE("Server died!"); + return -1; } + #endif - for (int i = 0; i < 30; i++) + if (!TestFileExists(pidFile)) { - if (!ServerIsAlive(pid)) break; - ::sleep(1); - if (!ServerIsAlive(pid)) break; - - if (i == 0) - { - printf("waiting for server to die"); - } - printf("."); - fflush(stdout); + ::fprintf(stdout, "timed out!\n"); + TEST_FAIL_WITH_MESSAGE("Server didn't save PID file"); + return -1; } - - if (!ServerIsAlive(pid)) + else { - printf("done.\n"); + ::fprintf(stdout, "done.\n"); } - else + + // wait a second for the pid to be written to the file + ::sleep(1); + + // read pid file + int pid = ReadPidFile(pidFile); + + #ifdef WIN32 + // On Win32 we can check whether the PID in the pidFile matches + // the one returned by the system, which it always should. + + if (pid != (int)procInfo.dwProcessId) { - printf("failed!\n"); + printf("Server wrote wrong pid to file (%s): expected %d " + "but found %d\n", pidFile, + (int)procInfo.dwProcessId, pid); + TEST_FAIL_WITH_MESSAGE("Server wrote wrong pid to file"); + return -1; } - fflush(stdout); + #endif - return !ServerIsAlive(pid); + return pid; } inline void TestRemoteProcessMemLeaks(const char *filename) @@ -361,4 +335,53 @@ inline void TestRemoteProcessMemLeaks(const char *filename) #endif } +#ifdef WIN32 +#define BBACKUPCTL "..\\..\\bin\\bbackupctl\\bbackupctl.exe" +#define BBACKUPD "..\\..\\bin\\bbackupd\\bbackupd.exe" +#define BBSTORED "..\\..\\bin\\bbstored\\bbstored.exe" +#define BBACKUPQUERY "..\\..\\bin\\bbackupquery\\bbackupquery.exe" +#define BBSTOREACCOUNTS "..\\..\\bin\\bbstoreaccounts\\bbstoreaccounts.exe" +#define TEST_RETURN(actual, expected) TEST_THAT(actual == expected); +#else +#define BBACKUPCTL "../../bin/bbackupctl/bbackupctl" +#define BBACKUPD "../../bin/bbackupd/bbackupd" +#define BBSTORED "../../bin/bbackupd/bbstored" +#define BBACKUPQUERY "../../bin/bbackupquery/bbackupquery" +#define BBSTOREACCOUNTS "../../bin/bbstoreaccounts/bbstoreaccounts" +#define TEST_RETURN(actual, expected) TEST_THAT(actual == expected*256); +#endif + +inline void terminate_bbackupd(int pid) +{ + TEST_THAT(::system(BBACKUPCTL " -q -c testfiles/bbackupd.conf " + "terminate") == 0); + TestRemoteProcessMemLeaks("bbackupctl.memleaks"); + + for (int i = 0; i < 20; i++) + { + if (!ServerIsAlive(pid)) break; + fprintf(stdout, "."); + fflush(stdout); + sleep(1); + } + + TEST_THAT(!ServerIsAlive(pid)); + TestRemoteProcessMemLeaks("bbackupd.memleaks"); +} + + +// Wait a given number of seconds for something to complete +inline void wait_for_operation(int seconds) +{ + printf("waiting: "); + fflush(stdout); + for(int l = 0; l < seconds; ++l) + { + sleep(1); + printf("."); + fflush(stdout); + } + printf("\n"); +} + #endif // TEST__H |