/// Sets a collection of configuration variables in the environment. /// /// \param user_variables Set of configuration variables to pass to the test. /// This is an array of strings of the form var=value and must have been /// previously sanity-checked with kyua_env_check_configuration. /// /// \return An error if there is a problem allocating memory. /// /// \post The environment contains a new collection of TEST_ENV_* variables that /// matches the input user_variables. kyua_error_t kyua_env_set_configuration(const char* const user_variables[]) { const char* const* iter; for (iter = user_variables; *iter != NULL; ++iter) { kyua_error_t error; char* var_value = strdup(*iter); if (var_value == NULL) return kyua_oom_error_new(); char* value = strchr(var_value, '='); assert(value != NULL); // Must have been validated. *value = '\0'; value += 1; char* var; error = kyua_text_printf(&var, "TEST_ENV_%s", var_value); if (kyua_error_is_set(error)) { free(var_value); return error; } error = kyua_env_set(var, value); if (kyua_error_is_set(error)) { free(var_value); return error; } } return kyua_error_ok(); }
ATF_TC_BODY(work_directory__env_tmpdir, tc) { char* tmpdir; RE(kyua_fs_make_absolute("worktest", &tmpdir)); ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); RE(kyua_env_set("TMPDIR", tmpdir)); char* work_directory; RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(), &work_directory)); { char* template_test; RE(kyua_fs_concat(&template_test, atf_tc_get_config_var(tc, "srcdir"), "worktest", "template.XXXXXX", NULL)); ATF_REQUIRE(access(template_test, X_OK) == -1); free(template_test); } ATF_REQUIRE(access(work_directory, X_OK) != -1); ATF_REQUIRE(rmdir(tmpdir) == -1); // Not yet empty. RE(kyua_run_work_directory_leave(&work_directory)); ATF_REQUIRE(rmdir(tmpdir) != -1); free(tmpdir); }
/// Unsets an environment variable. /// /// \param name Name of the environment variable to unset. /// /// \return An error object. kyua_error_t kyua_env_unset(const char* name) { #if defined(HAVE_UNSETENV) if (unsetenv(name) == -1) return kyua_libc_error_new( errno, "Failed to unset environment variable %s", name); else return kyua_error_ok(); #elif defined(HAVE_PUTENV) return kyua_env_set(name, ""); #else # error "Don't know how to unset an environment variable." #endif }
ATF_TC_BODY(work_directory__sanitized, tc) { ATF_REQUIRE(mkdir("foo", 0755) != -1); ATF_REQUIRE(mkdir("foo/bar", 0755) != -1); char* tmpdir; RE(kyua_fs_make_absolute("foo///bar/./", &tmpdir)); RE(kyua_env_set("TMPDIR", tmpdir)); char* work_directory; RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(), &work_directory)); ATF_REQUIRE(strstr(work_directory, "/foo/bar/template.") != NULL); RE(kyua_run_work_directory_leave(&work_directory)); free(tmpdir); }
ATF_TC_BODY(work_directory__permissions_error, tc) { char* tmpdir; RE(kyua_fs_make_absolute("worktest", &tmpdir)); ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); RE(kyua_env_set("TMPDIR", tmpdir)); char* work_directory; const kyua_error_t error = kyua_run_work_directory_enter( "template.XXXXXX", getuid() + 1, getgid(), &work_directory); ATF_REQUIRE(kyua_error_is_set(error)); ATF_REQUIRE(kyua_error_is_type(error, "libc")); ATF_REQUIRE_EQ(EPERM, kyua_libc_error_errno(error)); kyua_error_free(error); ATF_REQUIRE(rmdir(tmpdir) != -1); // Empty; subdirectory not created. free(tmpdir); }
/// Performs a signal delivery test to the work directory handling code. /// /// \param signo The signal to deliver. static void work_directory_signal_check(const int signo) { char* tmpdir; RE(kyua_fs_make_absolute("worktest", &tmpdir)); ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); RE(kyua_env_set("TMPDIR", tmpdir)); char* work_directory; RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(), &work_directory)); kyua_run_params_t run_params; kyua_run_params_init(&run_params); run_params.work_directory = work_directory; pid_t pid; RE(kyua_run_fork(&run_params, &pid)); if (pid == 0) { sleep(run_params.timeout_seconds * 2); abort(); } // This should cause the handled installed by the work_directory management // code to terminate the subprocess so that we get a chance to run the // cleanup code ourselves. kill(getpid(), signo); int status; bool timed_out; RE(kyua_run_wait(pid, &status, &timed_out)); ATF_REQUIRE(!timed_out); ATF_REQUIRE(WIFSIGNALED(status)); ATF_REQUIRE_EQ(SIGKILL, WTERMSIG(status)); ATF_REQUIRE(rmdir(tmpdir) == -1); // Not yet empty. RE(kyua_run_work_directory_leave(&work_directory)); ATF_REQUIRE(rmdir(tmpdir) != -1); free(tmpdir); }
ATF_TC_BODY(set, tc) { ATF_REQUIRE(strcmp(getenv("PATH"), "new value") != 0); kyua_env_set("PATH", "new value"); ATF_REQUIRE(strcmp(getenv("PATH"), "new value") == 0); }
ATF_TC_BODY(fork_wait__env, tc) { kyua_env_set("HOME", "/non-existent/directory"); kyua_env_set("LANG", "C"); kyua_env_set("LC_ALL", "C"); kyua_env_set("LC_COLLATE", "C"); kyua_env_set("LC_CTYPE", "C"); kyua_env_set("LC_MESSAGES", "C"); kyua_env_set("LC_MONETARY", "C"); kyua_env_set("LC_NUMERIC", "C"); kyua_env_set("LC_TIME", "C"); kyua_env_set("LEAVE_ME_ALONE", "kill-some-day"); kyua_env_set("TZ", "EST+5"); ATF_REQUIRE_MSG(fork_check(NULL, check_env, NULL), "Unclean environment in subprocess"); }