atf_error_t atf_fs_mkstemp(atf_fs_path_t *p, int *fdout) { atf_error_t err; char *buf; int fd; if (!check_umask(S_IRWXU, S_IRWXU)) { err = invalid_umask_error(p, atf_fs_stat_reg_type, current_umask()); goto out; } err = copy_contents(p, &buf); if (atf_is_error(err)) goto out; err = do_mkstemp(buf, &fd); if (atf_is_error(err)) goto out_buf; replace_contents(p, buf); *fdout = fd; INV(!atf_is_error(err)); out_buf: free(buf); out: return err; }
atf_error_t atf_fs_mkdtemp(atf_fs_path_t *p) { atf_error_t err; char *buf = NULL; if (!check_umask(S_IRWXU, S_IRWXU)) { err = invalid_umask_error(p, atf_fs_stat_dir_type, current_umask()); goto out; } err = copy_contents(p, &buf); if (atf_is_error(err)) goto out; err = do_mkdtemp(buf); if (atf_is_error(err)) goto out_buf; replace_contents(p, buf); INV(!atf_is_error(err)); out_buf: free(buf); out: return err; }
static atf_error_t params_init(struct params *p, const char *argv0) { atf_error_t err; p->m_do_list = false; p->m_tcname = NULL; p->m_tcpart = BODY; err = argv0_to_dir(argv0, &p->m_srcdir); if (atf_is_error(err)) return err; err = atf_fs_path_init_fmt(&p->m_resfile, "/dev/stdout"); if (atf_is_error(err)) { atf_fs_path_fini(&p->m_srcdir); return err; } err = atf_map_init(&p->m_config); if (atf_is_error(err)) { atf_fs_path_fini(&p->m_resfile); atf_fs_path_fini(&p->m_srcdir); return err; } return err; }
atf_error_t atf_process_fork(atf_process_child_t *c, void (*start)(void *), const atf_process_stream_t *outsb, const atf_process_stream_t *errsb, void *v) { atf_error_t err; atf_process_stream_t inherit_outsb, inherit_errsb; const atf_process_stream_t *real_outsb, *real_errsb; real_outsb = NULL; /* Shut up GCC warning. */ err = init_stream_w_default(outsb, &inherit_outsb, &real_outsb); if (atf_is_error(err)) goto out; real_errsb = NULL; /* Shut up GCC warning. */ err = init_stream_w_default(errsb, &inherit_errsb, &real_errsb); if (atf_is_error(err)) goto out_out; err = fork_with_streams(c, start, real_outsb, real_errsb, v); if (errsb == NULL) atf_process_stream_fini(&inherit_errsb); out_out: if (outsb == NULL) atf_process_stream_fini(&inherit_outsb); out: return err; }
static void cleanup_tmpdir(const atf_fs_path_t *dir, const atf_fs_path_t *outfile, const atf_fs_path_t *errfile) { { atf_error_t err = atf_fs_unlink(outfile); if (atf_is_error(err)) { INV(atf_error_is(err, "libc") && atf_libc_error_code(err) == ENOENT); atf_error_free(err); } else INV(!atf_is_error(err)); } { atf_error_t err = atf_fs_unlink(errfile); if (atf_is_error(err)) { INV(atf_error_is(err, "libc") && atf_libc_error_code(err) == ENOENT); atf_error_free(err); } else INV(!atf_is_error(err)); } { atf_error_t err = atf_fs_rmdir(dir); INV(!atf_is_error(err)); } }
static atf_error_t normalize_ap(atf_dynstr_t *d, const char *p, va_list ap) { char *str; atf_error_t err; va_list ap2; err = atf_dynstr_init(d); if (atf_is_error(err)) goto out; va_copy(ap2, ap); err = atf_text_format_ap(&str, p, ap2); va_end(ap2); if (atf_is_error(err)) atf_dynstr_fini(d); else { err = normalize(d, str); free(str); } out: return err; }
static void do_child(void (*start)(void *), void *v, const stream_prepare_t *outsp, const stream_prepare_t *errsp) { atf_error_t err; err = child_connect(outsp, STDOUT_FILENO); if (atf_is_error(err)) goto out; err = child_connect(errsp, STDERR_FILENO); if (atf_is_error(err)) goto out; start(v); UNREACHABLE; out: if (atf_is_error(err)) { char buf[1024]; atf_error_format(err, buf, sizeof(buf)); fprintf(stderr, "Unhandled error: %s\n", buf); atf_error_free(err); exit(EXIT_FAILURE); } else exit(EXIT_SUCCESS); }
static atf_error_t run_tc(const atf_tp_t *tp, struct params *p, int *exitcode) { atf_error_t err; err = atf_no_error(); if (!atf_tp_has_tc(tp, p->m_tcname)) { err = usage_error("Unknown test case `%s'", p->m_tcname); goto out; } if (!atf_env_has("__RUNNING_INSIDE_ATF_RUN") || strcmp(atf_env_get( "__RUNNING_INSIDE_ATF_RUN"), "internal-yes-value") != 0) { print_warning("Running test cases outside of kyua(1) is unsupported"); print_warning("No isolation nor timeout control is being applied; you " "may get unexpected failures; see atf-test-case(4)"); } switch (p->m_tcpart) { case BODY: err = atf_tp_run(tp, p->m_tcname, atf_fs_path_cstring(&p->m_resfile)); if (atf_is_error(err)) { /* TODO: Handle error */ *exitcode = EXIT_FAILURE; atf_error_free(err); } else { *exitcode = EXIT_SUCCESS; } break; case CLEANUP: err = atf_tp_cleanup(tp, p->m_tcname); if (atf_is_error(err)) { /* TODO: Handle error */ *exitcode = EXIT_FAILURE; atf_error_free(err); } else { *exitcode = EXIT_SUCCESS; } break; default: UNREACHABLE; } INV(!atf_is_error(err)); out: return err; }
ATF_TC_BODY(is_error, tc) { atf_error_t err; err = atf_no_error(); ATF_REQUIRE(!atf_is_error(err)); err = atf_error_new("test_error", NULL, 0, NULL); ATF_REQUIRE(atf_is_error(err)); atf_error_free(err); }
static atf_error_t fork_with_streams(atf_process_child_t *c, void (*start)(void *), const atf_process_stream_t *outsb, const atf_process_stream_t *errsb, void *v) { atf_error_t err; stream_prepare_t outsp; stream_prepare_t errsp; pid_t pid; err = stream_prepare_init(&outsp, outsb); if (atf_is_error(err)) goto out; err = stream_prepare_init(&errsp, errsb); if (atf_is_error(err)) goto err_outpipe; pid = fork(); if (pid == -1) { err = atf_libc_error(errno, "Failed to fork"); goto err_errpipe; } if (pid == 0) { do_child(start, v, &outsp, &errsp); UNREACHABLE; abort(); err = atf_no_error(); } else { err = do_parent(c, pid, &outsp, &errsp); if (atf_is_error(err)) goto err_errpipe; } goto out; err_errpipe: stream_prepare_fini(&errsp); err_outpipe: stream_prepare_fini(&outsp); out: return err; }
static atf_error_t controlled_main(int argc, char **argv, atf_error_t (*add_tcs_hook)(atf_tp_t *), int *exitcode) { atf_error_t err; struct params p; atf_tp_t tp; char **raw_config; err = process_params(argc, argv, &p); if (atf_is_error(err)) goto out; err = handle_srcdir(&p); if (atf_is_error(err)) goto out_p; raw_config = atf_map_to_charpp(&p.m_config); if (raw_config == NULL) { err = atf_no_memory_error(); goto out_p; } err = atf_tp_init(&tp, (const char* const*)raw_config); atf_utils_free_charpp(raw_config); if (atf_is_error(err)) goto out_p; err = add_tcs_hook(&tp); if (atf_is_error(err)) goto out_tp; if (p.m_do_list) { list_tcs(&tp); INV(!atf_is_error(err)); *exitcode = EXIT_SUCCESS; } else { err = run_tc(&tp, &p, exitcode); } out_tp: atf_tp_fini(&tp); out_p: params_fini(&p); out: return err; }
impl::stream_redirect_path::stream_redirect_path(const fs::path& p) { atf_error_t err = atf_process_stream_init_redirect_path(&m_sb, p.c_path()); if (atf_is_error(err)) throw_atf_error(err); m_inited = true; }
impl::stream_capture::stream_capture(void) { atf_error_t err = atf_process_stream_init_capture(&m_sb); if (atf_is_error(err)) throw_atf_error(err); m_inited = true; }
impl::stream_redirect_fd::stream_redirect_fd(const int fd) { atf_error_t err = atf_process_stream_init_redirect_fd(&m_sb, fd); if (atf_is_error(err)) throw_atf_error(err); m_inited = true; }
ATF_TC_BODY(no_error, tc) { atf_error_t err; err = atf_no_error(); ATF_REQUIRE(!atf_is_error(err)); }
impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) { atf_error_t err = atf_process_stream_init_connect(&m_sb, src_fd, tgt_fd); if (atf_is_error(err)) throw_atf_error(err); m_inited = true; }
void impl::set(const std::string& name, const std::string& val) { atf_error_t err = atf_env_set(name.c_str(), val.c_str()); if (atf_is_error(err)) throw_atf_error(err); }
atf_error_t atf_env_set(const char *name, const char *val) { atf_error_t err; #if defined(HAVE_SETENV) if (setenv(name, val, 1) == -1) err = atf_libc_error(errno, "Cannot set environment variable " "'%s' to '%s'", name, val); else err = atf_no_error(); #elif defined(HAVE_PUTENV) char *buf; err = atf_text_format(&buf, "%s=%s", name, val); if (!atf_is_error(err)) { if (putenv(buf) == -1) err = atf_libc_error(errno, "Cannot set environment variable " "'%s' to '%s'", name, val); free(buf); } #else # error "Don't know how to set an environment variable." #endif return err; }
static atf_error_t normalize(atf_dynstr_t *d, char *p) { const char *ptr; char *last; atf_error_t err; bool first; PRE(strlen(p) > 0); PRE(atf_dynstr_length(d) == 0); if (p[0] == '/') err = atf_dynstr_append_fmt(d, "/"); else err = atf_no_error(); first = true; last = NULL; /* Silence GCC warning. */ ptr = strtok_r(p, "/", &last); while (!atf_is_error(err) && ptr != NULL) { if (strlen(ptr) > 0) { err = atf_dynstr_append_fmt(d, "%s%s", first ? "" : "/", ptr); first = false; } ptr = strtok_r(NULL, "/", &last); } return err; }
int atf_tp_main(int argc, char **argv, atf_error_t (*add_tcs_hook)(atf_tp_t *)) { atf_error_t err; int exitcode; progname = strrchr(argv[0], '/'); if (progname == NULL) progname = argv[0]; else progname++; /* Libtool workaround: if running from within the source tree (binaries * that are not installed yet), skip the "lt-" prefix added to files in * the ".libs" directory to show the real (not temporary) name. */ if (strncmp(progname, "lt-", 3) == 0) progname += 3; exitcode = EXIT_FAILURE; /* Silence GCC warning. */ err = controlled_main(argc, argv, add_tcs_hook, &exitcode); if (atf_is_error(err)) { print_error(err); atf_error_free(err); exitcode = EXIT_FAILURE; } return exitcode; }
ATF_TC_BODY(init_raw, tc) { const char *src = "String 1, String 2"; atf_dynstr_t str; RE(atf_dynstr_init_raw(&str, src, 0)); ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); atf_dynstr_fini(&str); RE(atf_dynstr_init_raw(&str, src, 8)); ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); atf_dynstr_fini(&str); RE(atf_dynstr_init_raw(&str, src + 10, 8)); ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); atf_dynstr_fini(&str); RE(atf_dynstr_init_raw(&str, "String\0Lost", 11)); ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String") == 0); atf_dynstr_fini(&str); { atf_error_t err = atf_dynstr_init_raw(&str, "NULL", SIZE_MAX - 1); ATF_REQUIRE(atf_is_error(err)); ATF_REQUIRE(atf_error_is(err, "no_memory")); atf_error_free(err); } }
void impl::unset(const std::string& name) { atf_error_t err = atf_env_unset(name.c_str()); if (atf_is_error(err)) throw_atf_error(err); }
impl::stream_inherit::stream_inherit(void) { atf_error_t err = atf_process_stream_init_inherit(&m_sb); if (atf_is_error(err)) throw_atf_error(err); m_inited = true; }
atf_error_t atf_text_for_each_word(const char *instr, const char *sep, atf_error_t (*func)(const char *, void *), void *data) { atf_error_t err; char *str, *str2, *last; str = strdup(instr); if (str == NULL) { err = atf_no_memory_error(); goto out; } err = atf_no_error(); str2 = strtok_r(str, sep, &last); while (str2 != NULL && !atf_is_error(err)) { err = func(str2, data); str2 = strtok_r(NULL, sep, &last); } free(str); out: return err; }
/** Searches for a regexp in a file. * * \param regex The regexp to look for. * \param file The file in which to look for the expression. * \param ... Positional parameters to the regex. * * \return True if there is a match; false otherwise. */ bool atf_utils_grep_file(const char *regex, const char *file, ...) { int fd; va_list ap; atf_dynstr_t formatted; atf_error_t error; va_start(ap, file); error = atf_dynstr_init_ap(&formatted, regex, ap); va_end(ap); ATF_REQUIRE(!atf_is_error(error)); ATF_REQUIRE((fd = open(file, O_RDONLY)) != -1); bool found = false; char *line = NULL; while (!found && (line = atf_utils_readline(fd)) != NULL) { found = grep_string(atf_dynstr_cstring(&formatted), line); free(line); } close(fd); atf_dynstr_fini(&formatted); return found; }
static atf_error_t run_tc(const atf_tp_t *tp, struct params *p, int *exitcode) { atf_error_t err; err = atf_no_error(); if (!atf_tp_has_tc(tp, p->m_tcname)) { err = usage_error("Unknown test case `%s'", p->m_tcname); goto out; } switch (p->m_tcpart) { case BODY: err = atf_tp_run(tp, p->m_tcname, atf_fs_path_cstring(&p->m_resfile)); if (atf_is_error(err)) { /* TODO: Handle error */ *exitcode = EXIT_FAILURE; atf_error_free(err); } else { *exitcode = EXIT_SUCCESS; } break; case CLEANUP: err = atf_tp_cleanup(tp, p->m_tcname); if (atf_is_error(err)) { /* TODO: Handle error */ *exitcode = EXIT_FAILURE; atf_error_free(err); } else { *exitcode = EXIT_SUCCESS; } break; default: UNREACHABLE; } INV(!atf_is_error(err)); out: return err; }
atf_error_t atf_text_split(const char *str, const char *delim, atf_list_t *words) { atf_error_t err; const char *end; const char *iter; err = atf_list_init(words); if (atf_is_error(err)) goto err; end = str + strlen(str); INV(*end == '\0'); iter = str; while (iter < end) { const char *ptr; INV(iter != NULL); ptr = strstr(iter, delim); if (ptr == NULL) ptr = end; INV(ptr >= iter); if (ptr > iter) { atf_dynstr_t word; err = atf_dynstr_init_raw(&word, iter, ptr - iter); if (atf_is_error(err)) goto err_list; err = atf_list_append(words, atf_dynstr_fini_disown(&word), true); if (atf_is_error(err)) goto err_list; } iter = ptr + strlen(delim); } INV(!atf_is_error(err)); return err; err_list: atf_list_fini(words); err: return err; }
static atf_error_t srcdir_strip_libtool(atf_fs_path_t *srcdir) { atf_error_t err; atf_fs_path_t parent; err = atf_fs_path_branch_path(srcdir, &parent); if (atf_is_error(err)) goto out; atf_fs_path_fini(srcdir); *srcdir = parent; INV(!atf_is_error(err)); out: return err; }
atf_error_t atf_fs_path_to_absolute(const atf_fs_path_t *p, atf_fs_path_t *pa) { atf_error_t err; PRE(!atf_fs_path_is_absolute(p)); err = atf_fs_getcwd(pa); if (atf_is_error(err)) goto out; err = atf_fs_path_append_path(pa, p); if (atf_is_error(err)) atf_fs_path_fini(pa); out: return err; }
static atf_error_t mkstemp_discard_fd(atf_fs_path_t *p) { int fd; atf_error_t err = atf_fs_mkstemp(p, &fd); if (!atf_is_error(err)) close(fd); return err; }