1//===- not.cpp - The 'not' testing tool -----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// Usage:
9// not cmd
10// Will return true if cmd doesn't crash and returns false.
11// not --crash cmd
12// Will return true if cmd crashes (e.g. for testing crash reporting).
13
14#include "llvm/Support/Process.h"
15#include "llvm/Support/Program.h"
16#include "llvm/Support/WithColor.h"
17#include "llvm/Support/raw_ostream.h"
18
19#ifdef _WIN32
20#include <windows.h>
21#endif
22
23using namespace llvm;
24
25int main(int argc, const char **argv) {
26 bool ExpectCrash = false;
27
28 ++argv;
29 --argc;
30
31 if (argc > 0 && StringRef(argv[0]) == "--crash") {
32 ++argv;
33 --argc;
34 ExpectCrash = true;
35
36 // Crash is expected, so disable crash report and symbolization to reduce
37 // output and avoid potentially slow symbolization.
38#ifdef _WIN32
39 SetEnvironmentVariableA("LLVM_DISABLE_CRASH_REPORT", "1");
40 SetEnvironmentVariableA("LLVM_DISABLE_SYMBOLIZATION", "1");
41#else
42 setenv(name: "LLVM_DISABLE_CRASH_REPORT", value: "1", replace: 0);
43 setenv(name: "LLVM_DISABLE_SYMBOLIZATION", value: "1", replace: 0);
44#endif
45 // Try to disable coredumps for expected crashes as well since this can
46 // noticeably slow down running the test suite.
47 sys::Process::PreventCoreFiles();
48 }
49
50 if (argc == 0)
51 return 1;
52
53 auto Program = sys::findProgramByName(Name: argv[0]);
54 if (!Program) {
55 WithColor::error() << "unable to find `" << argv[0]
56 << "' in PATH: " << Program.getError().message() << "\n";
57 return 1;
58 }
59
60 std::vector<StringRef> Argv;
61 Argv.reserve(n: argc);
62 for (int i = 0; i < argc; ++i)
63 Argv.push_back(x: argv[i]);
64 std::string ErrMsg;
65 int Result =
66 sys::ExecuteAndWait(Program: *Program, Args: Argv, Env: std::nullopt, Redirects: {}, SecondsToWait: 0, MemoryLimit: 0, ErrMsg: &ErrMsg);
67#ifdef _WIN32
68 // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka
69 // unreachable, should be recognized as a crash. However, some binaries use
70 // exit code 3 on non-crash failure paths, so only do this if we expect a
71 // crash.
72 if (ExpectCrash && Result == 3)
73 Result = -3;
74#endif
75 if (Result < 0) {
76 WithColor::error() << ErrMsg << "\n";
77 if (ExpectCrash)
78 return 0;
79 return 1;
80 }
81
82 if (ExpectCrash)
83 return 1;
84
85 return Result == 0;
86}
87