1 1.1 jmmv // Copyright 2012 Google Inc. 2 1.1 jmmv // All rights reserved. 3 1.1 jmmv // 4 1.1 jmmv // Redistribution and use in source and binary forms, with or without 5 1.1 jmmv // modification, are permitted provided that the following conditions are 6 1.1 jmmv // met: 7 1.1 jmmv // 8 1.1 jmmv // * Redistributions of source code must retain the above copyright 9 1.1 jmmv // notice, this list of conditions and the following disclaimer. 10 1.1 jmmv // * Redistributions in binary form must reproduce the above copyright 11 1.1 jmmv // notice, this list of conditions and the following disclaimer in the 12 1.1 jmmv // documentation and/or other materials provided with the distribution. 13 1.1 jmmv // * Neither the name of Google Inc. nor the names of its contributors 14 1.1 jmmv // may be used to endorse or promote products derived from this software 15 1.1 jmmv // without specific prior written permission. 16 1.1 jmmv // 17 1.1 jmmv // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 1.1 jmmv // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 1.1 jmmv // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 1.1 jmmv // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 1.1 jmmv // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 1.1 jmmv // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 1.1 jmmv // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 1.1 jmmv // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 1.1 jmmv // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 1.1 jmmv // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 1.1 jmmv // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 jmmv 29 1.1 jmmv /// \file common_inttest.h 30 1.1 jmmv /// Common integration tests for the tester binaries. 31 1.1 jmmv 32 1.1 jmmv #if defined(KYUA_COMMON_INTTEST_H) 33 1.1 jmmv # error "common_inttest.h can only be defined once" 34 1.1 jmmv #endif 35 1.1 jmmv /// Include guard. 36 1.1 jmmv #define KYUA_COMMON_INTTEST_H 37 1.1 jmmv 38 1.1 jmmv #if !defined(INTERFACE) 39 1.1 jmmv # error "Must define INTERFACE to the name of the tester interface" 40 1.1 jmmv #endif 41 1.1 jmmv 42 1.1 jmmv #include <err.h> 43 1.1 jmmv #include <stdarg.h> 44 1.1 jmmv #include <stdbool.h> 45 1.1 jmmv #include <stdio.h> 46 1.1 jmmv #include <stdlib.h> 47 1.1 jmmv 48 1.1 jmmv #include <atf-c.h> 49 1.1 jmmv 50 1.1 jmmv #include "cli.h" // For the EXIT_* constants only. 51 1.1 jmmv #include "defs.h" 52 1.1 jmmv 53 1.1 jmmv 54 1.1 jmmv /// Path to the installed testers. 55 1.1 jmmv static const char* default_testersdir = TESTERSDIR; 56 1.1 jmmv 57 1.1 jmmv 58 1.1 jmmv /// Returns the name of the current tester. 59 1.1 jmmv #define TESTER_BIN "kyua-" INTERFACE "-tester" 60 1.1 jmmv 61 1.1 jmmv 62 1.1 jmmv /// Returns the path to the helpers. 63 1.1 jmmv /// 64 1.1 jmmv /// \param tc Pointer to the caller test case, to obtain the srcdir property. 65 1.1 jmmv /// 66 1.1 jmmv /// \return A dynamically-allocated string; must be released with free(3). 67 1.1 jmmv static char* 68 1.1 jmmv helpers_path(const atf_tc_t* tc) 69 1.1 jmmv { 70 1.1 jmmv const char* srcdir = atf_tc_get_config_var(tc, "srcdir"); 71 1.1 jmmv const char* name = INTERFACE "_helpers"; 72 1.1 jmmv 73 1.1 jmmv const size_t length = strlen(srcdir) + 1 + strlen(name) + 1; 74 1.1 jmmv char* buffer = (char*)malloc(length); 75 1.1 jmmv (void)snprintf(buffer, length, "%s/%s", srcdir, name); 76 1.1 jmmv return buffer; 77 1.1 jmmv } 78 1.1 jmmv 79 1.1 jmmv 80 1.1 jmmv /// Returns the path to the tester. 81 1.1 jmmv /// 82 1.1 jmmv /// \return A dynamically-allocated string; must be released with free(3). 83 1.1 jmmv static char* 84 1.1 jmmv tester_path(void) 85 1.1 jmmv { 86 1.1 jmmv const char* testersdir = getenv("TESTERSDIR"); 87 1.1 jmmv if (testersdir == NULL) 88 1.1 jmmv testersdir = default_testersdir; 89 1.1 jmmv const char* name = TESTER_BIN; 90 1.1 jmmv 91 1.1 jmmv const size_t length = strlen(testersdir) + 1 + strlen(name) + 1; 92 1.1 jmmv char* buffer = (char*)malloc(length); 93 1.1 jmmv ATF_REQUIRE(buffer != NULL); 94 1.1 jmmv (void)snprintf(buffer, length, "%s/%s", testersdir, name); 95 1.1 jmmv return buffer; 96 1.1 jmmv } 97 1.1 jmmv 98 1.1 jmmv 99 1.1 jmmv /// Initializes the test case metadata and the helpers. 100 1.1 jmmv /// 101 1.1 jmmv /// \param [in,out] tc The test case in which to set the property. 102 1.1 jmmv /// \param uses_helpers Whether the test uses the helpers or not. 103 1.1 jmmv static void 104 1.1 jmmv setup(atf_tc_t* tc, const bool uses_helpers) 105 1.1 jmmv { 106 1.1 jmmv char* tester = tester_path(); 107 1.1 jmmv if (uses_helpers) { 108 1.1 jmmv char* helpers = helpers_path(tc); 109 1.1 jmmv atf_tc_set_md_var(tc, "require.progs", "%s %s", tester, helpers); 110 1.1 jmmv free(helpers); 111 1.1 jmmv } else { 112 1.1 jmmv atf_tc_set_md_var(tc, "require.progs", "%s", tester); 113 1.1 jmmv } 114 1.1 jmmv free(tester); 115 1.1 jmmv } 116 1.1 jmmv 117 1.1 jmmv 118 1.1 jmmv static void execute(va_list ap) KYUA_DEFS_NORETURN; 119 1.1 jmmv 120 1.1 jmmv 121 1.1 jmmv /// Executes the tester with the given set of variable arguments. 122 1.1 jmmv /// 123 1.1 jmmv /// \param ap List of arguments to the tester. 124 1.1 jmmv static void 125 1.1 jmmv execute(va_list ap) 126 1.1 jmmv { 127 1.1 jmmv const char* args[16]; 128 1.1 jmmv 129 1.1 jmmv const char** current_arg = &args[0]; 130 1.1 jmmv *current_arg = TESTER_BIN; 131 1.1 jmmv ++current_arg; 132 1.1 jmmv while ((*current_arg = va_arg(ap, const char*)) != NULL) 133 1.1 jmmv ++current_arg; 134 1.1 jmmv 135 1.1 jmmv char* program = tester_path(); 136 1.1 jmmv (void)execv(program, KYUA_DEFS_UNCONST(args)); 137 1.1 jmmv free(program); 138 1.1 jmmv err(111, "Failed to execute %s", program); 139 1.1 jmmv } 140 1.1 jmmv 141 1.1 jmmv 142 1.1 jmmv /// Executes the tester and validates its output. 143 1.1 jmmv /// 144 1.1 jmmv /// \param expected_exit_status Expected exit status of the subprocess. 145 1.1 jmmv /// \param expected_stdout Expected contents of stdout. 146 1.1 jmmv /// \param expected_stderr Expected contents of stderr. 147 1.1 jmmv /// \param ... Arguments to the tester, not including the program name. 148 1.1 jmmv static void 149 1.1 jmmv check(const int expected_exit_status, const char* expected_stdout, 150 1.1 jmmv const char* expected_stderr, ...) 151 1.1 jmmv { 152 1.1 jmmv const pid_t pid = atf_utils_fork(); 153 1.1 jmmv if (pid == 0) { 154 1.1 jmmv va_list ap; 155 1.1 jmmv va_start(ap, expected_stderr); 156 1.1 jmmv execute(ap); 157 1.1 jmmv va_end(ap); 158 1.1 jmmv } else { 159 1.1 jmmv atf_utils_wait(pid, expected_exit_status, expected_stdout, 160 1.1 jmmv expected_stderr); 161 1.1 jmmv } 162 1.1 jmmv } 163 1.1 jmmv 164 1.1 jmmv 165 1.1 jmmv ATF_TC(top__missing_command); 166 1.1 jmmv ATF_TC_HEAD(top__missing_command, tc) { setup(tc, false); } 167 1.1 jmmv ATF_TC_BODY(top__missing_command, tc) 168 1.1 jmmv { 169 1.1 jmmv check(EXIT_USAGE_ERROR, "", TESTER_BIN": Must provide a command\n", 170 1.1 jmmv NULL); 171 1.1 jmmv } 172 1.1 jmmv 173 1.1 jmmv 174 1.1 jmmv ATF_TC(top__unknown_command); 175 1.1 jmmv ATF_TC_HEAD(top__unknown_command, tc) { setup(tc, false); } 176 1.1 jmmv ATF_TC_BODY(top__unknown_command, tc) 177 1.1 jmmv { 178 1.1 jmmv check(EXIT_USAGE_ERROR, "", TESTER_BIN": Unknown command 'foo'\n", 179 1.1 jmmv "foo", NULL); 180 1.1 jmmv } 181