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 SmallVector<StringRef> Argv(ArrayRef(argv, argc));
61 std::string ErrMsg;
62 int Result =
63 sys::ExecuteAndWait(Program: *Program, Args: Argv, Env: std::nullopt, Redirects: {}, SecondsToWait: 0, MemoryLimit: 0, ErrMsg: &ErrMsg);
64#ifdef _WIN32
65 // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka
66 // unreachable, should be recognized as a crash. However, some binaries use
67 // exit code 3 on non-crash failure paths, so only do this if we expect a
68 // crash.
69 if (ExpectCrash && Result == 3)
70 Result = -3;
71#endif
72 if (Result < 0) {
73 WithColor::error() << ErrMsg << "\n";
74 if (ExpectCrash)
75 return 0;
76 return 1;
77 }
78
79 if (ExpectCrash)
80 return 1;
81
82 return Result == 0;
83}
84