/// Executes the cleanup of a test case. /// /// \param test_program Path to the test program to execute. /// \param test_case Name of the test case to run. /// \param user_variables Set of configuration variables to pass to the test. static void exec_cleanup(const char* test_program, const char* test_case, const char* const user_variables[]) { char* name; kyua_error_t error = kyua_text_printf(&name, "%s:cleanup", test_case); if (kyua_error_is_set(error)) kyua_error_err(EXIT_FAILURE, error, "Failed to construct argument list"); const size_t nargs = 1 /* test_program */ + + 2 * count_variables(user_variables) /* -v name=value */ + 1 /* test_case */ + 1 /* NULL */; const char** args = malloc(sizeof(const char*) * nargs); if (args == NULL) kyua_error_err(EXIT_FAILURE, kyua_oom_error_new(), "Failed to construct arguments list"); size_t i = 0; args[i++] = test_program; const char* const* iter; for (iter = user_variables; *iter != NULL; ++iter) { args[i++] = "-v"; args[i++] = *iter; } args[i++] = name; args[i++] = NULL; assert(i == nargs); kyua_run_exec(test_program, args); }
ATF_TC_BODY(oom_error_reuse, tc) { { kyua_error_t error = kyua_oom_error_new(); ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); ATF_REQUIRE(kyua_error_data(error) == NULL); kyua_error_free(error); } { kyua_error_t error = kyua_oom_error_new(); ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); ATF_REQUIRE(kyua_error_data(error) == NULL); kyua_error_free(error); } }
/// Executes the body of a test case. /// /// \param test_program Path to the test program to execute. /// \param test_case Name of the test case to run. /// \param result_file Path to the ATF result file to be created. /// \param user_variables Set of configuration variables to pass to the test. static void exec_body(const char* test_program, const char* test_case, const char* result_file, const char* const user_variables[]) { const size_t nargs = 1 /* test_program */ + 2 /* -r result_file */ + 2 * count_variables(user_variables) /* -v name=value */ + 1 /* test_case */ + 1 /* NULL */; const char** args = malloc(sizeof(const char*) * nargs); if (args == NULL) kyua_error_err(EXIT_FAILURE, kyua_oom_error_new(), "Failed to construct arguments list"); size_t i = 0; args[i++] = test_program; args[i++] = "-r"; args[i++] = result_file; const char* const* iter; for (iter = user_variables; *iter != NULL; ++iter) { args[i++] = "-v"; args[i++] = *iter; } args[i++] = test_case; args[i++] = NULL; assert(i == nargs); kyua_run_exec(test_program, args); }
/// Sets an environment variable. /// /// \param name Name of the environment variable to set. /// \param value Value to be set. /// /// \return An error object. kyua_error_t kyua_env_set(const char* name, const char* value) { kyua_error_t error; #if defined(HAVE_SETENV) if (setenv(name, value, 1) == -1) error = kyua_libc_error_new( errno, "Failed to set environment variable %s to %s", name, value); else error = kyua_error_ok(); #elif defined(HAVE_PUTENV) const size_t length = strlen(name) + strlen(value) + 2; char* buffer = (char*)malloc(length); if (buffer == NULL) error = kyua_oom_error_new(); else { const size_t printed_length = snprintf(buffer, length, "%s=%s", name, value); assert(length == printed_length + 1); if (putenv(buffer) == -1) { error = kyua_libc_error_new( errno, "Failed to set environment variable %s to %s", name, value); free(buffer); } else error = kyua_error_ok(); } #else # error "Don't know how to set an environment variable." #endif return error; }
/// 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(); }
/// Generates a string from a format string and its replacements. /// /// \param [out] output Pointer to the dynamically-allocated string with the /// result of the operation. The caller must release this with free(). /// \param format The formatting string. /// \param ap List of to apply to the formatting string. /// /// \return OK if the string could be formatted; an error otherwise. kyua_error_t kyua_text_vprintf(char** output, const char* format, va_list ap) { va_list ap2; va_copy(ap2, ap); const int length = calculate_length(format, ap2); va_end(ap2); if (length < 0) return kyua_libc_error_new(errno, "Could not calculate length of " "string with format '%s'", format); char* buffer = (char*)malloc(length + 1); if (buffer == NULL) return kyua_oom_error_new(); va_copy(ap2, ap); const int printed_length = vsnprintf(buffer, length + 1, format, ap2); va_end(ap2); assert(printed_length == length); if (printed_length < 0) { free(buffer); return kyua_libc_error_new(errno, "Could generate string with format " "'%s'", format); } *output = buffer; return kyua_error_ok(); }
ATF_TC_BODY(oom_error_format, tc) { kyua_error_t error = kyua_oom_error_new(); char buffer[1024]; kyua_error_format(error, buffer, sizeof(buffer)); ATF_REQUIRE_STREQ("Not enough memory", buffer); kyua_error_free(error); }
ATF_TC_BODY(oom_error_data, tc) { kyua_error_t error = kyua_oom_error_new(); ATF_REQUIRE(kyua_error_data(error) == NULL); kyua_error_free(error); }
ATF_TC_BODY(oom_error_type, tc) { kyua_error_t error = kyua_oom_error_new(); ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); kyua_error_free(error); }