mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-22 06:26:26 +00:00
clar: tempdir and sandboxes are now separate entities
clar now has the concept of a _temporary directory_, which is the temporary directory for the entirety of a `clar` invocation (a set of test runs) and a sandbox, which is the temporary directory for a single test invocation. This allows us to ensure that a well-written test (that only writes into its sandbox) doesn't poison the well for future test invocations if it fails to clean up its sandbox.
This commit is contained in:
@@ -195,8 +195,10 @@ static void clar_print_onsuite(const char *suite_name, int suite_index);
|
||||
static void clar_print_onabort(const char *msg, ...);
|
||||
|
||||
/* From clar_sandbox.c */
|
||||
static void clar_unsandbox(void);
|
||||
static int clar_sandbox(void);
|
||||
static int clar_tempdir_init(void);
|
||||
static void clar_tempdir_shutdown(void);
|
||||
static int clar_sandbox_create(void);
|
||||
static int clar_sandbox_cleanup(void);
|
||||
|
||||
/* From summary.h */
|
||||
static struct clar_summary *clar_summary_init(const char *filename);
|
||||
@@ -293,6 +295,8 @@ clar_run_test(
|
||||
|
||||
CL_TRACE(CL_TRACE__TEST__BEGIN);
|
||||
|
||||
clar_sandbox_create();
|
||||
|
||||
_clar.last_report->start = time(NULL);
|
||||
clar_time_now(&start);
|
||||
|
||||
@@ -320,6 +324,8 @@ clar_run_test(
|
||||
if (cleanup->ptr != NULL)
|
||||
cleanup->ptr();
|
||||
|
||||
clar_sandbox_cleanup();
|
||||
|
||||
CL_TRACE(CL_TRACE__TEST__END);
|
||||
|
||||
_clar.tests_ran++;
|
||||
@@ -575,8 +581,8 @@ clar_test_init(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (clar_sandbox() < 0) {
|
||||
clar_print_onabort("Failed to sandbox the test runner.\n");
|
||||
if (clar_tempdir_init() < 0) {
|
||||
clar_print_onabort("Failed to create tempdir for the test runner.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
@@ -610,7 +616,7 @@ clar_test_shutdown(void)
|
||||
_clar.total_errors
|
||||
);
|
||||
|
||||
clar_unsandbox();
|
||||
clar_tempdir_shutdown();
|
||||
|
||||
if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) {
|
||||
clar_print_onabort("Failed to write the summary file\n");
|
||||
|
||||
@@ -30,6 +30,7 @@ void clar_test_shutdown(void);
|
||||
int clar_test(int argc, char *argv[]);
|
||||
|
||||
const char *clar_sandbox_path(void);
|
||||
const char *clar_tempdir_path(void);
|
||||
|
||||
void cl_set_cleanup(void (*cleanup)(void *), void *opaque);
|
||||
void cl_fs_cleanup(void);
|
||||
|
||||
@@ -28,7 +28,7 @@ const char *cl_fixture(const char *fixture_name)
|
||||
|
||||
void cl_fixture_sandbox(const char *fixture_name)
|
||||
{
|
||||
fs_copy(cl_fixture(fixture_name), _clar_path);
|
||||
fs_copy(cl_fixture(fixture_name), clar_sandbox_path());
|
||||
}
|
||||
|
||||
const char *cl_fixture_basename(const char *fixture_name)
|
||||
@@ -45,6 +45,6 @@ const char *cl_fixture_basename(const char *fixture_name)
|
||||
|
||||
void cl_fixture_cleanup(const char *fixture_name)
|
||||
{
|
||||
fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name)));
|
||||
fs_rm(fixture_path(clar_sandbox_path(), cl_fixture_basename(fixture_name)));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -146,7 +146,7 @@ fs_rm_wait(WCHAR *_wpath)
|
||||
ERROR_PATH_NOT_FOUND == last_error)
|
||||
return 0;
|
||||
|
||||
Sleep(RM_RETRY_DELAY * retries * retries);
|
||||
Sleep(RM_RETRY_DELAY * retries * retries);
|
||||
}
|
||||
while (retries++ <= RM_RETRY_COUNT);
|
||||
|
||||
@@ -516,7 +516,7 @@ fs_rm(const char *path)
|
||||
void
|
||||
cl_fs_cleanup(void)
|
||||
{
|
||||
clar_unsandbox();
|
||||
clar_sandbox();
|
||||
clar_tempdir_shutdown();
|
||||
clar_tempdir_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2,8 +2,17 @@
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The tempdir is the temporary directory for the entirety of the clar
|
||||
* process execution. The sandbox is an individual temporary directory
|
||||
* for the execution of an individual test. Sandboxes are deleted
|
||||
* entirely after test execution to avoid pollution across tests.
|
||||
*/
|
||||
#define CLAR_PATH_MAX 4096
|
||||
static char _clar_path[CLAR_PATH_MAX];
|
||||
static char _clar_tempdir[CLAR_PATH_MAX];
|
||||
size_t _clar_tempdir_len;
|
||||
|
||||
static char _clar_sandbox[CLAR_PATH_MAX];
|
||||
|
||||
static int
|
||||
is_valid_tmp_path(const char *path)
|
||||
@@ -99,17 +108,17 @@ static int canonicalize_tmp_path(char *buffer)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void clar_unsandbox(void)
|
||||
static void clar_tempdir_shutdown(void)
|
||||
{
|
||||
if (_clar_path[0] == '\0')
|
||||
if (_clar_tempdir[0] == '\0')
|
||||
return;
|
||||
|
||||
cl_must_pass(chdir(".."));
|
||||
|
||||
fs_rm(_clar_path);
|
||||
fs_rm(_clar_tempdir);
|
||||
}
|
||||
|
||||
static int build_sandbox_path(void)
|
||||
static int build_tempdir_path(void)
|
||||
{
|
||||
#ifdef CLAR_TMPDIR
|
||||
const char path_tail[] = CLAR_TMPDIR "_XXXXXX";
|
||||
@@ -119,61 +128,111 @@ static int build_sandbox_path(void)
|
||||
|
||||
size_t len;
|
||||
|
||||
if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0 ||
|
||||
canonicalize_tmp_path(_clar_path) < 0)
|
||||
if (find_tmp_path(_clar_tempdir, sizeof(_clar_tempdir)) < 0 ||
|
||||
canonicalize_tmp_path(_clar_tempdir) < 0)
|
||||
return -1;
|
||||
|
||||
len = strlen(_clar_path);
|
||||
len = strlen(_clar_tempdir);
|
||||
|
||||
#ifdef _WIN32
|
||||
{ /* normalize path to POSIX forward slashes */
|
||||
size_t i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (_clar_path[i] == '\\')
|
||||
_clar_path[i] = '/';
|
||||
if (_clar_tempdir[i] == '\\')
|
||||
_clar_tempdir[i] = '/';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_clar_path[len - 1] != '/') {
|
||||
_clar_path[len++] = '/';
|
||||
if (_clar_tempdir[len - 1] != '/') {
|
||||
_clar_tempdir[len++] = '/';
|
||||
}
|
||||
|
||||
strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
|
||||
strncpy(_clar_tempdir + len, path_tail, sizeof(_clar_tempdir) - len);
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
if (_mktemp(_clar_path) == NULL)
|
||||
if (_mktemp(_clar_tempdir) == NULL)
|
||||
return -1;
|
||||
|
||||
if (mkdir(_clar_path, 0700) != 0)
|
||||
if (mkdir(_clar_tempdir, 0700) != 0)
|
||||
return -1;
|
||||
#elif defined(_WIN32)
|
||||
if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
|
||||
if (_mktemp_s(_clar_tempdir, sizeof(_clar_tempdir)) != 0)
|
||||
return -1;
|
||||
|
||||
if (mkdir(_clar_path, 0700) != 0)
|
||||
if (mkdir(_clar_tempdir, 0700) != 0)
|
||||
return -1;
|
||||
#else
|
||||
if (mkdtemp(_clar_path) == NULL)
|
||||
if (mkdtemp(_clar_tempdir) == NULL)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
_clar_tempdir_len = strlen(_clar_tempdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clar_tempdir_init(void)
|
||||
{
|
||||
if (_clar_tempdir[0] == '\0' && build_tempdir_path() < 0)
|
||||
return -1;
|
||||
|
||||
if (chdir(_clar_tempdir) != 0)
|
||||
return -1;
|
||||
|
||||
srand(clock() ^ time(NULL) ^ (getpid() << 16));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clar_sandbox(void)
|
||||
static int clar_sandbox_create(void)
|
||||
{
|
||||
if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
|
||||
char alpha[] = "0123456789abcdef";
|
||||
int num = rand();
|
||||
|
||||
cl_assert(_clar_sandbox[0] == '\0');
|
||||
|
||||
strcpy(_clar_sandbox, _clar_tempdir);
|
||||
_clar_sandbox[_clar_tempdir_len] = '/';
|
||||
|
||||
_clar_sandbox[_clar_tempdir_len + 1] = alpha[(num & 0xf0000000) >> 28];
|
||||
_clar_sandbox[_clar_tempdir_len + 2] = alpha[(num & 0x0f000000) >> 24];
|
||||
_clar_sandbox[_clar_tempdir_len + 3] = alpha[(num & 0x00f00000) >> 20];
|
||||
_clar_sandbox[_clar_tempdir_len + 4] = alpha[(num & 0x000f0000) >> 16];
|
||||
_clar_sandbox[_clar_tempdir_len + 5] = alpha[(num & 0x0000f000) >> 12];
|
||||
_clar_sandbox[_clar_tempdir_len + 6] = alpha[(num & 0x00000f00) >> 8];
|
||||
_clar_sandbox[_clar_tempdir_len + 7] = alpha[(num & 0x000000f0) >> 4];
|
||||
_clar_sandbox[_clar_tempdir_len + 8] = alpha[(num & 0x0000000f) >> 0];
|
||||
_clar_sandbox[_clar_tempdir_len + 9] = '\0';
|
||||
|
||||
if (mkdir(_clar_sandbox, 0700) != 0)
|
||||
return -1;
|
||||
|
||||
if (chdir(_clar_path) != 0)
|
||||
if (chdir(_clar_sandbox) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clar_sandbox_cleanup(void)
|
||||
{
|
||||
cl_assert(_clar_sandbox[0] != '\0');
|
||||
|
||||
fs_rm(_clar_sandbox);
|
||||
_clar_sandbox[0] = '\0';
|
||||
|
||||
if (chdir(_clar_tempdir) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *clar_tempdir_path(void)
|
||||
{
|
||||
return _clar_tempdir;
|
||||
}
|
||||
|
||||
const char *clar_sandbox_path(void)
|
||||
{
|
||||
return _clar_path;
|
||||
return _clar_sandbox;
|
||||
}
|
||||
|
||||
|
||||
@@ -649,7 +649,7 @@ void cl_sandbox_set_homedir(const char *home)
|
||||
if (home) {
|
||||
git_libgit2_opts(GIT_OPT_SET_HOMEDIR, home);
|
||||
} else {
|
||||
git_str_joinpath(&path, clar_sandbox_path(), "__home");
|
||||
git_str_joinpath(&path, clar_tempdir_path(), "__home");
|
||||
|
||||
if (!git_fs_path_exists(path.ptr))
|
||||
cl_must_pass(p_mkdir(path.ptr, 0777));
|
||||
@@ -664,7 +664,7 @@ void cl_sandbox_set_search_path_defaults(void)
|
||||
{
|
||||
git_str path = GIT_STR_INIT;
|
||||
|
||||
git_str_joinpath(&path, clar_sandbox_path(), "__config");
|
||||
git_str_joinpath(&path, clar_tempdir_path(), "__config");
|
||||
|
||||
if (!git_fs_path_exists(path.ptr))
|
||||
cl_must_pass(p_mkdir(path.ptr, 0777));
|
||||
@@ -694,7 +694,7 @@ bool cl_sandbox_supports_8dot3(void)
|
||||
bool supported;
|
||||
|
||||
cl_git_pass(
|
||||
git_str_joinpath(&longpath, clar_sandbox_path(), "longer_than_8dot3"));
|
||||
git_str_joinpath(&longpath, clar_tempdir_path(), "longer_than_8dot3"));
|
||||
|
||||
cl_git_write2file(longpath.ptr, "", 0, O_RDWR|O_CREAT, 0666);
|
||||
shortname = git_win32_path_8dot3_name(longpath.ptr);
|
||||
|
||||
Reference in New Issue
Block a user