diff options
Diffstat (limited to 'src/test.cc')
-rw-r--r-- | src/test.cc | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/test.cc b/src/test.cc index 925a6cb..f5b037f 100644 --- a/src/test.cc +++ b/src/test.cc @@ -16,7 +16,57 @@ #include <algorithm> +#include <errno.h> + #include "parsers.h" +#include "util.h" + +namespace { + +#ifdef _WIN32 +#ifndef _mktemp_s +/// mingw has no mktemp. Implement one with the same type as the one +/// found in the Windows API. +int _mktemp_s(char* templ) { + char* ofs = strchr(templ, 'X'); + sprintf(ofs, "%d", rand() % 1000000); + return 0; +} +#endif + +/// Windows has no mkdtemp. Implement it in terms of _mktemp_s. +char* mkdtemp(char* name_template) { + int err = _mktemp_s(name_template); + if (err < 0) { + perror("_mktemp_s"); + return NULL; + } + + err = _mkdir(name_template); + if (err < 0) { + perror("mkdir"); + return NULL; + } + + return name_template; +} +#endif // WIN32 + +string GetSystemTempDir() { +#ifdef _WIN32 + char buf[1024]; + if (!GetTempPath(sizeof(buf), buf)) + return ""; + return buf; +#else + const char* tempdir = getenv("TMPDIR"); + if (tempdir) + return tempdir; + return "/tmp"; +#endif +} + +} // anonymous namespace StateTestWithBuiltinRules::StateTestWithBuiltinRules() { AssertParse(&state_, @@ -74,3 +124,44 @@ int VirtualFileSystem::RemoveFile(const string& path) { return 1; } } + +void ScopedTempDir::CreateAndEnter(const string& name) { + // First change into the system temp dir and save it for cleanup. + start_dir_ = GetSystemTempDir(); + if (start_dir_.empty()) + Fatal("couldn't get system temp dir"); + if (chdir(start_dir_.c_str()) < 0) + Fatal("chdir: %s", strerror(errno)); + + // Create a temporary subdirectory of that. + char name_template[1024]; + strcpy(name_template, name.c_str()); + strcat(name_template, "-XXXXXX"); + char* tempname = mkdtemp(name_template); + if (!tempname) + Fatal("mkdtemp: %s", strerror(errno)); + temp_dir_name_ = tempname; + + // chdir into the new temporary directory. + if (chdir(temp_dir_name_.c_str()) < 0) + Fatal("chdir: %s", strerror(errno)); +} + +void ScopedTempDir::Cleanup() { + if (temp_dir_name_.empty()) + return; // Something went wrong earlier. + + // Move out of the directory we're about to clobber. + if (chdir(start_dir_.c_str()) < 0) + Fatal("chdir: %s", strerror(errno)); + +#ifdef _WIN32 + string command = "rmdir /s /q " + temp_dir_name_; +#else + string command = "rm -rf " + temp_dir_name_; +#endif + if (system(command.c_str()) < 0) + Fatal("system: %s", strerror(errno)); + + temp_dir_name_.clear(); +} |