1 // Copyright 2010 Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #include "utils/sanity.hpp" 30 31 extern "C" { 32 #include <signal.h> 33 #include <unistd.h> 34 } 35 36 #include <cstdlib> 37 #include <iostream> 38 39 #include <atf-c++.hpp> 40 41 #include "utils/format/macros.hpp" 42 #include "utils/fs/path.hpp" 43 #include "utils/process/child.ipp" 44 #include "utils/process/status.hpp" 45 46 namespace fs = utils::fs; 47 namespace process = utils::process; 48 49 50 #define FILE_REGEXP __FILE__ ":[0-9]+: " 51 52 53 static const fs::path Stdout_File("stdout.txt"); 54 static const fs::path Stderr_File("stderr.txt"); 55 56 57 #if NDEBUG 58 static bool NDebug = true; 59 #else 60 static bool NDebug = false; 61 #endif 62 63 64 template< typename Function > 65 static process::status 66 run_test(Function function) 67 { 68 const process::status status = process::child::fork_files( 69 function, Stdout_File, Stderr_File)->wait(); 70 atf::utils::cat_file(Stdout_File.str(), "Helper stdout: "); 71 atf::utils::cat_file(Stderr_File.str(), "Helper stderr: "); 72 return status; 73 } 74 75 76 static void 77 verify_success(const process::status& status) 78 { 79 ATF_REQUIRE(status.exited()); 80 ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus()); 81 ATF_REQUIRE(atf::utils::grep_file("Before test", Stdout_File.str())); 82 ATF_REQUIRE(atf::utils::grep_file("After test", Stdout_File.str())); 83 } 84 85 86 static void 87 verify_failed(const process::status& status, const char* type, 88 const char* exp_message, const bool check_ndebug) 89 { 90 if (check_ndebug && NDebug) { 91 std::cout << "Built with NDEBUG; skipping verification\n"; 92 verify_success(status); 93 } else { 94 ATF_REQUIRE(status.signaled()); 95 ATF_REQUIRE_EQ(SIGABRT, status.termsig()); 96 ATF_REQUIRE(atf::utils::grep_file("Before test", Stdout_File.str())); 97 ATF_REQUIRE(!atf::utils::grep_file("After test", Stdout_File.str())); 98 if (exp_message != NULL) 99 ATF_REQUIRE(atf::utils::grep_file(F(FILE_REGEXP "%s: %s") % 100 type % exp_message, 101 Stderr_File.str())); 102 else 103 ATF_REQUIRE(atf::utils::grep_file(F(FILE_REGEXP "%s") % type, 104 Stderr_File.str())); 105 } 106 } 107 108 109 template< bool Expression, bool WithMessage > 110 static void 111 do_inv_test(void) 112 { 113 std::cout << "Before test\n"; 114 if (WithMessage) 115 INV_MSG(Expression, "Custom message"); 116 else 117 INV(Expression); 118 std::cout << "After test\n"; 119 std::exit(EXIT_SUCCESS); 120 } 121 122 123 ATF_TEST_CASE_WITHOUT_HEAD(inv__holds); 124 ATF_TEST_CASE_BODY(inv__holds) 125 { 126 const process::status status = run_test(do_inv_test< true, false >); 127 verify_success(status); 128 } 129 130 131 ATF_TEST_CASE_WITHOUT_HEAD(inv__triggers_default_message); 132 ATF_TEST_CASE_BODY(inv__triggers_default_message) 133 { 134 const process::status status = run_test(do_inv_test< false, false >); 135 verify_failed(status, "Invariant check failed", "Expression", true); 136 } 137 138 139 ATF_TEST_CASE_WITHOUT_HEAD(inv__triggers_custom_message); 140 ATF_TEST_CASE_BODY(inv__triggers_custom_message) 141 { 142 const process::status status = run_test(do_inv_test< false, true >); 143 verify_failed(status, "Invariant check failed", "Custom", true); 144 } 145 146 147 template< bool Expression, bool WithMessage > 148 static void 149 do_pre_test(void) 150 { 151 std::cout << "Before test\n"; 152 if (WithMessage) 153 PRE_MSG(Expression, "Custom message"); 154 else 155 PRE(Expression); 156 std::cout << "After test\n"; 157 std::exit(EXIT_SUCCESS); 158 } 159 160 161 ATF_TEST_CASE_WITHOUT_HEAD(pre__holds); 162 ATF_TEST_CASE_BODY(pre__holds) 163 { 164 const process::status status = run_test(do_pre_test< true, false >); 165 verify_success(status); 166 } 167 168 169 ATF_TEST_CASE_WITHOUT_HEAD(pre__triggers_default_message); 170 ATF_TEST_CASE_BODY(pre__triggers_default_message) 171 { 172 const process::status status = run_test(do_pre_test< false, false >); 173 verify_failed(status, "Precondition check failed", "Expression", true); 174 } 175 176 177 ATF_TEST_CASE_WITHOUT_HEAD(pre__triggers_custom_message); 178 ATF_TEST_CASE_BODY(pre__triggers_custom_message) 179 { 180 const process::status status = run_test(do_pre_test< false, true >); 181 verify_failed(status, "Precondition check failed", "Custom", true); 182 } 183 184 185 template< bool Expression, bool WithMessage > 186 static void 187 do_post_test(void) 188 { 189 std::cout << "Before test\n"; 190 if (WithMessage) 191 POST_MSG(Expression, "Custom message"); 192 else 193 POST(Expression); 194 std::cout << "After test\n"; 195 std::exit(EXIT_SUCCESS); 196 } 197 198 199 ATF_TEST_CASE_WITHOUT_HEAD(post__holds); 200 ATF_TEST_CASE_BODY(post__holds) 201 { 202 const process::status status = run_test(do_post_test< true, false >); 203 verify_success(status); 204 } 205 206 207 ATF_TEST_CASE_WITHOUT_HEAD(post__triggers_default_message); 208 ATF_TEST_CASE_BODY(post__triggers_default_message) 209 { 210 const process::status status = run_test(do_post_test< false, false >); 211 verify_failed(status, "Postcondition check failed", "Expression", true); 212 } 213 214 215 ATF_TEST_CASE_WITHOUT_HEAD(post__triggers_custom_message); 216 ATF_TEST_CASE_BODY(post__triggers_custom_message) 217 { 218 const process::status status = run_test(do_post_test< false, true >); 219 verify_failed(status, "Postcondition check failed", "Custom", true); 220 } 221 222 223 template< bool WithMessage > 224 static void 225 do_unreachable_test(void) 226 { 227 std::cout << "Before test\n"; 228 if (WithMessage) 229 UNREACHABLE_MSG("Custom message"); 230 else 231 UNREACHABLE; 232 std::cout << "After test\n"; 233 std::exit(EXIT_SUCCESS); 234 } 235 236 237 ATF_TEST_CASE_WITHOUT_HEAD(unreachable__default_message); 238 ATF_TEST_CASE_BODY(unreachable__default_message) 239 { 240 const process::status status = run_test(do_unreachable_test< false >); 241 verify_failed(status, "Unreachable point reached", NULL, false); 242 } 243 244 245 ATF_TEST_CASE_WITHOUT_HEAD(unreachable__custom_message); 246 ATF_TEST_CASE_BODY(unreachable__custom_message) 247 { 248 const process::status status = run_test(do_unreachable_test< true >); 249 verify_failed(status, "Unreachable point reached", "Custom", false); 250 } 251 252 253 template< int Signo > 254 static void 255 do_crash_handler_test(void) 256 { 257 utils::install_crash_handlers("test-log.txt"); 258 ::kill(::getpid(), Signo); 259 std::cout << "After signal\n"; 260 std::exit(EXIT_FAILURE); 261 } 262 263 264 template< int Signo > 265 static void 266 crash_handler_test(void) 267 { 268 const process::status status = run_test(do_crash_handler_test< Signo >); 269 ATF_REQUIRE(status.signaled()); 270 ATF_REQUIRE_EQ(Signo, status.termsig()); 271 ATF_REQUIRE(atf::utils::grep_file(F("Fatal signal %s") % Signo, 272 Stderr_File.str())); 273 ATF_REQUIRE(atf::utils::grep_file("Log file is test-log.txt", 274 Stderr_File.str())); 275 ATF_REQUIRE(!atf::utils::grep_file("After signal", Stdout_File.str())); 276 } 277 278 279 ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigabrt); 280 ATF_TEST_CASE_BODY(install_crash_handlers__sigabrt) 281 { 282 crash_handler_test< SIGABRT >(); 283 } 284 285 286 ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigbus); 287 ATF_TEST_CASE_BODY(install_crash_handlers__sigbus) 288 { 289 crash_handler_test< SIGBUS >(); 290 } 291 292 293 ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigsegv); 294 ATF_TEST_CASE_BODY(install_crash_handlers__sigsegv) 295 { 296 crash_handler_test< SIGSEGV >(); 297 } 298 299 300 ATF_INIT_TEST_CASES(tcs) 301 { 302 ATF_ADD_TEST_CASE(tcs, inv__holds); 303 ATF_ADD_TEST_CASE(tcs, inv__triggers_default_message); 304 ATF_ADD_TEST_CASE(tcs, inv__triggers_custom_message); 305 ATF_ADD_TEST_CASE(tcs, pre__holds); 306 ATF_ADD_TEST_CASE(tcs, pre__triggers_default_message); 307 ATF_ADD_TEST_CASE(tcs, pre__triggers_custom_message); 308 ATF_ADD_TEST_CASE(tcs, post__holds); 309 ATF_ADD_TEST_CASE(tcs, post__triggers_default_message); 310 ATF_ADD_TEST_CASE(tcs, post__triggers_custom_message); 311 ATF_ADD_TEST_CASE(tcs, unreachable__default_message); 312 ATF_ADD_TEST_CASE(tcs, unreachable__custom_message); 313 314 ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigabrt); 315 ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigbus); 316 ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigsegv); 317 } 318