1*c243e490SMarcel Moolenaar /* 2*c243e490SMarcel Moolenaar * Automated Testing Framework (atf) 3*c243e490SMarcel Moolenaar * 4*c243e490SMarcel Moolenaar * Copyright (c) 2008 The NetBSD Foundation, Inc. 5*c243e490SMarcel Moolenaar * All rights reserved. 6*c243e490SMarcel Moolenaar * 7*c243e490SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 8*c243e490SMarcel Moolenaar * modification, are permitted provided that the following conditions 9*c243e490SMarcel Moolenaar * are met: 10*c243e490SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 11*c243e490SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 12*c243e490SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 13*c243e490SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 14*c243e490SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 15*c243e490SMarcel Moolenaar * 16*c243e490SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17*c243e490SMarcel Moolenaar * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18*c243e490SMarcel Moolenaar * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19*c243e490SMarcel Moolenaar * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*c243e490SMarcel Moolenaar * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21*c243e490SMarcel Moolenaar * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*c243e490SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23*c243e490SMarcel Moolenaar * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*c243e490SMarcel Moolenaar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*c243e490SMarcel Moolenaar * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26*c243e490SMarcel Moolenaar * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27*c243e490SMarcel Moolenaar * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*c243e490SMarcel Moolenaar */ 29*c243e490SMarcel Moolenaar 30*c243e490SMarcel Moolenaar #include <fcntl.h> 31*c243e490SMarcel Moolenaar #include <stdio.h> 32*c243e490SMarcel Moolenaar #include <stdlib.h> 33*c243e490SMarcel Moolenaar #include <regex.h> 34*c243e490SMarcel Moolenaar #include <unistd.h> 35*c243e490SMarcel Moolenaar 36*c243e490SMarcel Moolenaar #include "atf-c/build.h" 37*c243e490SMarcel Moolenaar #include "atf-c/check.h" 38*c243e490SMarcel Moolenaar #include "atf-c/config.h" 39*c243e490SMarcel Moolenaar #include "atf-c/error.h" 40*c243e490SMarcel Moolenaar #include "atf-c/macros.h" 41*c243e490SMarcel Moolenaar 42*c243e490SMarcel Moolenaar #include "dynstr.h" 43*c243e490SMarcel Moolenaar #include "fs.h" 44*c243e490SMarcel Moolenaar #include "process.h" 45*c243e490SMarcel Moolenaar #include "test_helpers.h" 46*c243e490SMarcel Moolenaar 47*c243e490SMarcel Moolenaar static 48*c243e490SMarcel Moolenaar void 49*c243e490SMarcel Moolenaar build_check_c_o_aux(const char *path, const char *failmsg, 50*c243e490SMarcel Moolenaar const bool expect_pass) 51*c243e490SMarcel Moolenaar { 52*c243e490SMarcel Moolenaar bool success; 53*c243e490SMarcel Moolenaar atf_dynstr_t iflag; 54*c243e490SMarcel Moolenaar const char *optargs[4]; 55*c243e490SMarcel Moolenaar 56*c243e490SMarcel Moolenaar RE(atf_dynstr_init_fmt(&iflag, "-I%s", atf_config_get("atf_includedir"))); 57*c243e490SMarcel Moolenaar 58*c243e490SMarcel Moolenaar optargs[0] = atf_dynstr_cstring(&iflag); 59*c243e490SMarcel Moolenaar optargs[1] = "-Wall"; 60*c243e490SMarcel Moolenaar optargs[2] = "-Werror"; 61*c243e490SMarcel Moolenaar optargs[3] = NULL; 62*c243e490SMarcel Moolenaar 63*c243e490SMarcel Moolenaar RE(atf_check_build_c_o(path, "test.o", optargs, &success)); 64*c243e490SMarcel Moolenaar 65*c243e490SMarcel Moolenaar atf_dynstr_fini(&iflag); 66*c243e490SMarcel Moolenaar 67*c243e490SMarcel Moolenaar if ((expect_pass && !success) || (!expect_pass && success)) 68*c243e490SMarcel Moolenaar atf_tc_fail("%s", failmsg); 69*c243e490SMarcel Moolenaar } 70*c243e490SMarcel Moolenaar 71*c243e490SMarcel Moolenaar void 72*c243e490SMarcel Moolenaar build_check_c_o(const atf_tc_t *tc, const char *sfile, const char *failmsg, 73*c243e490SMarcel Moolenaar const bool expect_pass) 74*c243e490SMarcel Moolenaar { 75*c243e490SMarcel Moolenaar atf_fs_path_t path; 76*c243e490SMarcel Moolenaar 77*c243e490SMarcel Moolenaar RE(atf_fs_path_init_fmt(&path, "%s/%s", 78*c243e490SMarcel Moolenaar atf_tc_get_config_var(tc, "srcdir"), sfile)); 79*c243e490SMarcel Moolenaar build_check_c_o_aux(atf_fs_path_cstring(&path), failmsg, expect_pass); 80*c243e490SMarcel Moolenaar atf_fs_path_fini(&path); 81*c243e490SMarcel Moolenaar } 82*c243e490SMarcel Moolenaar 83*c243e490SMarcel Moolenaar void 84*c243e490SMarcel Moolenaar header_check(const char *hdrname) 85*c243e490SMarcel Moolenaar { 86*c243e490SMarcel Moolenaar FILE *srcfile; 87*c243e490SMarcel Moolenaar char failmsg[128]; 88*c243e490SMarcel Moolenaar 89*c243e490SMarcel Moolenaar srcfile = fopen("test.c", "w"); 90*c243e490SMarcel Moolenaar ATF_REQUIRE(srcfile != NULL); 91*c243e490SMarcel Moolenaar fprintf(srcfile, "#include <%s>\n", hdrname); 92*c243e490SMarcel Moolenaar fclose(srcfile); 93*c243e490SMarcel Moolenaar 94*c243e490SMarcel Moolenaar snprintf(failmsg, sizeof(failmsg), 95*c243e490SMarcel Moolenaar "Header check failed; %s is not self-contained", hdrname); 96*c243e490SMarcel Moolenaar 97*c243e490SMarcel Moolenaar build_check_c_o_aux("test.c", failmsg, true); 98*c243e490SMarcel Moolenaar } 99*c243e490SMarcel Moolenaar 100*c243e490SMarcel Moolenaar void 101*c243e490SMarcel Moolenaar get_process_helpers_path(const atf_tc_t *tc, const bool is_detail, 102*c243e490SMarcel Moolenaar atf_fs_path_t *path) 103*c243e490SMarcel Moolenaar { 104*c243e490SMarcel Moolenaar RE(atf_fs_path_init_fmt(path, "%s/%sprocess_helpers", 105*c243e490SMarcel Moolenaar atf_tc_get_config_var(tc, "srcdir"), 106*c243e490SMarcel Moolenaar is_detail ? "" : "detail/")); 107*c243e490SMarcel Moolenaar } 108*c243e490SMarcel Moolenaar 109*c243e490SMarcel Moolenaar bool 110*c243e490SMarcel Moolenaar grep_string(const atf_dynstr_t *str, const char *regex) 111*c243e490SMarcel Moolenaar { 112*c243e490SMarcel Moolenaar int res; 113*c243e490SMarcel Moolenaar regex_t preg; 114*c243e490SMarcel Moolenaar 115*c243e490SMarcel Moolenaar printf("Looking for '%s' in '%s'\n", regex, atf_dynstr_cstring(str)); 116*c243e490SMarcel Moolenaar ATF_REQUIRE(regcomp(&preg, regex, REG_EXTENDED) == 0); 117*c243e490SMarcel Moolenaar 118*c243e490SMarcel Moolenaar res = regexec(&preg, atf_dynstr_cstring(str), 0, NULL, 0); 119*c243e490SMarcel Moolenaar ATF_REQUIRE(res == 0 || res == REG_NOMATCH); 120*c243e490SMarcel Moolenaar 121*c243e490SMarcel Moolenaar regfree(&preg); 122*c243e490SMarcel Moolenaar 123*c243e490SMarcel Moolenaar return res == 0; 124*c243e490SMarcel Moolenaar } 125*c243e490SMarcel Moolenaar 126*c243e490SMarcel Moolenaar bool 127*c243e490SMarcel Moolenaar grep_file(const char *file, const char *regex, ...) 128*c243e490SMarcel Moolenaar { 129*c243e490SMarcel Moolenaar bool done, found; 130*c243e490SMarcel Moolenaar int fd; 131*c243e490SMarcel Moolenaar va_list ap; 132*c243e490SMarcel Moolenaar atf_dynstr_t formatted; 133*c243e490SMarcel Moolenaar 134*c243e490SMarcel Moolenaar va_start(ap, regex); 135*c243e490SMarcel Moolenaar RE(atf_dynstr_init_ap(&formatted, regex, ap)); 136*c243e490SMarcel Moolenaar va_end(ap); 137*c243e490SMarcel Moolenaar 138*c243e490SMarcel Moolenaar done = false; 139*c243e490SMarcel Moolenaar found = false; 140*c243e490SMarcel Moolenaar ATF_REQUIRE((fd = open(file, O_RDONLY)) != -1); 141*c243e490SMarcel Moolenaar do { 142*c243e490SMarcel Moolenaar atf_dynstr_t line; 143*c243e490SMarcel Moolenaar 144*c243e490SMarcel Moolenaar RE(atf_dynstr_init(&line)); 145*c243e490SMarcel Moolenaar 146*c243e490SMarcel Moolenaar done = read_line(fd, &line); 147*c243e490SMarcel Moolenaar if (!done) 148*c243e490SMarcel Moolenaar found = grep_string(&line, atf_dynstr_cstring(&formatted)); 149*c243e490SMarcel Moolenaar 150*c243e490SMarcel Moolenaar atf_dynstr_fini(&line); 151*c243e490SMarcel Moolenaar } while (!found && !done); 152*c243e490SMarcel Moolenaar close(fd); 153*c243e490SMarcel Moolenaar 154*c243e490SMarcel Moolenaar atf_dynstr_fini(&formatted); 155*c243e490SMarcel Moolenaar 156*c243e490SMarcel Moolenaar return found; 157*c243e490SMarcel Moolenaar } 158*c243e490SMarcel Moolenaar 159*c243e490SMarcel Moolenaar bool 160*c243e490SMarcel Moolenaar read_line(int fd, atf_dynstr_t *dest) 161*c243e490SMarcel Moolenaar { 162*c243e490SMarcel Moolenaar char ch; 163*c243e490SMarcel Moolenaar ssize_t cnt; 164*c243e490SMarcel Moolenaar 165*c243e490SMarcel Moolenaar while ((cnt = read(fd, &ch, sizeof(ch))) == sizeof(ch) && 166*c243e490SMarcel Moolenaar ch != '\n') { 167*c243e490SMarcel Moolenaar const atf_error_t err = atf_dynstr_append_fmt(dest, "%c", ch); 168*c243e490SMarcel Moolenaar ATF_REQUIRE(!atf_is_error(err)); 169*c243e490SMarcel Moolenaar } 170*c243e490SMarcel Moolenaar ATF_REQUIRE(cnt != -1); 171*c243e490SMarcel Moolenaar 172*c243e490SMarcel Moolenaar return cnt == 0; 173*c243e490SMarcel Moolenaar } 174*c243e490SMarcel Moolenaar 175*c243e490SMarcel Moolenaar struct run_h_tc_data { 176*c243e490SMarcel Moolenaar atf_tc_t *m_tc; 177*c243e490SMarcel Moolenaar const char *m_resname; 178*c243e490SMarcel Moolenaar }; 179*c243e490SMarcel Moolenaar 180*c243e490SMarcel Moolenaar static 181*c243e490SMarcel Moolenaar void 182*c243e490SMarcel Moolenaar run_h_tc_child(void *v) 183*c243e490SMarcel Moolenaar { 184*c243e490SMarcel Moolenaar struct run_h_tc_data *data = (struct run_h_tc_data *)v; 185*c243e490SMarcel Moolenaar 186*c243e490SMarcel Moolenaar RE(atf_tc_run(data->m_tc, data->m_resname)); 187*c243e490SMarcel Moolenaar } 188*c243e490SMarcel Moolenaar 189*c243e490SMarcel Moolenaar /* TODO: Investigate if it's worth to add this functionality as part of 190*c243e490SMarcel Moolenaar * the public API. I.e. a function to easily run a test case body in a 191*c243e490SMarcel Moolenaar * subprocess. */ 192*c243e490SMarcel Moolenaar void 193*c243e490SMarcel Moolenaar run_h_tc(atf_tc_t *tc, const char *outname, const char *errname, 194*c243e490SMarcel Moolenaar const char *resname) 195*c243e490SMarcel Moolenaar { 196*c243e490SMarcel Moolenaar atf_fs_path_t outpath, errpath; 197*c243e490SMarcel Moolenaar atf_process_stream_t outb, errb; 198*c243e490SMarcel Moolenaar atf_process_child_t child; 199*c243e490SMarcel Moolenaar atf_process_status_t status; 200*c243e490SMarcel Moolenaar 201*c243e490SMarcel Moolenaar RE(atf_fs_path_init_fmt(&outpath, outname)); 202*c243e490SMarcel Moolenaar RE(atf_fs_path_init_fmt(&errpath, errname)); 203*c243e490SMarcel Moolenaar 204*c243e490SMarcel Moolenaar struct run_h_tc_data data = { tc, resname }; 205*c243e490SMarcel Moolenaar 206*c243e490SMarcel Moolenaar RE(atf_process_stream_init_redirect_path(&outb, &outpath)); 207*c243e490SMarcel Moolenaar RE(atf_process_stream_init_redirect_path(&errb, &errpath)); 208*c243e490SMarcel Moolenaar RE(atf_process_fork(&child, run_h_tc_child, &outb, &errb, &data)); 209*c243e490SMarcel Moolenaar atf_process_stream_fini(&errb); 210*c243e490SMarcel Moolenaar atf_process_stream_fini(&outb); 211*c243e490SMarcel Moolenaar 212*c243e490SMarcel Moolenaar RE(atf_process_child_wait(&child, &status)); 213*c243e490SMarcel Moolenaar ATF_CHECK(atf_process_status_exited(&status)); 214*c243e490SMarcel Moolenaar atf_process_status_fini(&status); 215*c243e490SMarcel Moolenaar 216*c243e490SMarcel Moolenaar atf_fs_path_fini(&errpath); 217*c243e490SMarcel Moolenaar atf_fs_path_fini(&outpath); 218*c243e490SMarcel Moolenaar } 219