1fa7a9ef1SCaitlyn Cano //===-- Implementation of the base class for libc unittests----------------===//
24cfccd51SMichael Jones //
34cfccd51SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44cfccd51SMichael Jones // See https://llvm.org/LICENSE.txt for license information.
54cfccd51SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64cfccd51SMichael Jones //
74cfccd51SMichael Jones //===----------------------------------------------------------------------===//
84cfccd51SMichael Jones
94cfccd51SMichael Jones #include "LibcTest.h"
104cfccd51SMichael Jones
11*300f8da8SSiva Chandra Reddy #include "src/__support/CPP/UInt128.h"
124cfccd51SMichael Jones #include "utils/testutils/ExecuteFunction.h"
134cfccd51SMichael Jones #include <cassert>
144cfccd51SMichael Jones #include <iostream>
154cfccd51SMichael Jones #include <string>
164cfccd51SMichael Jones
174cfccd51SMichael Jones namespace __llvm_libc {
184cfccd51SMichael Jones namespace testing {
194cfccd51SMichael Jones
204cfccd51SMichael Jones // This need not be a class as all it has is a single read-write state variable.
214cfccd51SMichael Jones // But, we make it class as then its implementation can be hidden from the
224cfccd51SMichael Jones // header file.
234cfccd51SMichael Jones class RunContext {
244cfccd51SMichael Jones public:
254cfccd51SMichael Jones enum RunResult { Result_Pass = 1, Result_Fail = 2 };
264cfccd51SMichael Jones
status() const274cfccd51SMichael Jones RunResult status() const { return Status; }
284cfccd51SMichael Jones
markFail()294cfccd51SMichael Jones void markFail() { Status = Result_Fail; }
304cfccd51SMichael Jones
314cfccd51SMichael Jones private:
324cfccd51SMichael Jones RunResult Status = Result_Pass;
334cfccd51SMichael Jones };
344cfccd51SMichael Jones
354cfccd51SMichael Jones namespace internal {
364cfccd51SMichael Jones
374cfccd51SMichael Jones // When the value is of integral type, just display it as normal.
384cfccd51SMichael Jones template <typename ValType>
394cfccd51SMichael Jones cpp::EnableIfType<cpp::IsIntegral<ValType>::Value, std::string>
describeValue(ValType Value)404cfccd51SMichael Jones describeValue(ValType Value) {
414cfccd51SMichael Jones return std::to_string(Value);
424cfccd51SMichael Jones }
434cfccd51SMichael Jones
describeValue(std::string Value)444cfccd51SMichael Jones std::string describeValue(std::string Value) { return std::string(Value); }
45*300f8da8SSiva Chandra Reddy
46*300f8da8SSiva Chandra Reddy // When the value is UInt128 or __uint128_t, show its hexadecimal digits.
47*300f8da8SSiva Chandra Reddy // We cannot just use a UInt128 specialization as that resolves to only
48*300f8da8SSiva Chandra Reddy // one type, UInt<128> or __uint128_t. We want both overloads as we want to
49*300f8da8SSiva Chandra Reddy // be able to unittest UInt<128> on platforms where UInt128 resolves to
50*300f8da8SSiva Chandra Reddy // UInt128.
51*300f8da8SSiva Chandra Reddy template <typename UInt128Type>
describeValue128(UInt128Type Value)52*300f8da8SSiva Chandra Reddy std::string describeValue128(UInt128Type Value) {
53*300f8da8SSiva Chandra Reddy std::string S(sizeof(UInt128) * 2, '0');
544cfccd51SMichael Jones
554cfccd51SMichael Jones for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value >>= 4) {
564cfccd51SMichael Jones unsigned char Mod = static_cast<unsigned char>(Value) & 15;
574cfccd51SMichael Jones *I = Mod < 10 ? '0' + Mod : 'a' + Mod - 10;
584cfccd51SMichael Jones }
594cfccd51SMichael Jones
604cfccd51SMichael Jones return "0x" + S;
614cfccd51SMichael Jones }
624cfccd51SMichael Jones
63*300f8da8SSiva Chandra Reddy #ifdef __SIZEOF_INT128__
describeValue(__uint128_t Value)64b62d72f3SMichael Jones template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
65b62d72f3SMichael Jones return describeValue128(Value);
66b62d72f3SMichael Jones }
67ce6bfd10SDominic Chen #endif
68b62d72f3SMichael Jones
691170951cSMichael Jones template <>
701170951cSMichael Jones std::string
describeValue(__llvm_libc::cpp::UInt<128> Value)711170951cSMichael Jones describeValue<__llvm_libc::cpp::UInt<128>>(__llvm_libc::cpp::UInt<128> Value) {
72*300f8da8SSiva Chandra Reddy return describeValue128(Value);
731170951cSMichael Jones }
741170951cSMichael Jones
754cfccd51SMichael Jones template <typename ValType>
explainDifference(ValType LHS,ValType RHS,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line,std::string OpString)764cfccd51SMichael Jones void explainDifference(ValType LHS, ValType RHS, const char *LHSStr,
774cfccd51SMichael Jones const char *RHSStr, const char *File, unsigned long Line,
784cfccd51SMichael Jones std::string OpString) {
794cfccd51SMichael Jones size_t OffsetLength = OpString.size() > 2 ? OpString.size() - 2 : 0;
804cfccd51SMichael Jones std::string Offset(OffsetLength, ' ');
814cfccd51SMichael Jones
824cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
834cfccd51SMichael Jones << Offset << "Expected: " << LHSStr << '\n'
844cfccd51SMichael Jones << Offset << "Which is: " << describeValue(LHS) << '\n'
854cfccd51SMichael Jones << "To be " << OpString << ": " << RHSStr << '\n'
864cfccd51SMichael Jones << Offset << "Which is: " << describeValue(RHS) << '\n';
874cfccd51SMichael Jones }
884cfccd51SMichael Jones
894cfccd51SMichael Jones template <typename ValType>
test(RunContext * Ctx,TestCondition Cond,ValType LHS,ValType RHS,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line)904cfccd51SMichael Jones bool test(RunContext *Ctx, TestCondition Cond, ValType LHS, ValType RHS,
914cfccd51SMichael Jones const char *LHSStr, const char *RHSStr, const char *File,
924cfccd51SMichael Jones unsigned long Line) {
934cfccd51SMichael Jones auto ExplainDifference = [=](std::string OpString) {
944cfccd51SMichael Jones explainDifference(LHS, RHS, LHSStr, RHSStr, File, Line, OpString);
954cfccd51SMichael Jones };
964cfccd51SMichael Jones
974cfccd51SMichael Jones switch (Cond) {
984cfccd51SMichael Jones case Cond_EQ:
994cfccd51SMichael Jones if (LHS == RHS)
1004cfccd51SMichael Jones return true;
1014cfccd51SMichael Jones
1024cfccd51SMichael Jones Ctx->markFail();
1034cfccd51SMichael Jones ExplainDifference("equal to");
1044cfccd51SMichael Jones return false;
1054cfccd51SMichael Jones case Cond_NE:
1064cfccd51SMichael Jones if (LHS != RHS)
1074cfccd51SMichael Jones return true;
1084cfccd51SMichael Jones
1094cfccd51SMichael Jones Ctx->markFail();
1104cfccd51SMichael Jones ExplainDifference("not equal to");
1114cfccd51SMichael Jones return false;
1124cfccd51SMichael Jones case Cond_LT:
1134cfccd51SMichael Jones if (LHS < RHS)
1144cfccd51SMichael Jones return true;
1154cfccd51SMichael Jones
1164cfccd51SMichael Jones Ctx->markFail();
1174cfccd51SMichael Jones ExplainDifference("less than");
1184cfccd51SMichael Jones return false;
1194cfccd51SMichael Jones case Cond_LE:
1204cfccd51SMichael Jones if (LHS <= RHS)
1214cfccd51SMichael Jones return true;
1224cfccd51SMichael Jones
1234cfccd51SMichael Jones Ctx->markFail();
1244cfccd51SMichael Jones ExplainDifference("less than or equal to");
1254cfccd51SMichael Jones return false;
1264cfccd51SMichael Jones case Cond_GT:
1274cfccd51SMichael Jones if (LHS > RHS)
1284cfccd51SMichael Jones return true;
1294cfccd51SMichael Jones
1304cfccd51SMichael Jones Ctx->markFail();
1314cfccd51SMichael Jones ExplainDifference("greater than");
1324cfccd51SMichael Jones return false;
1334cfccd51SMichael Jones case Cond_GE:
1344cfccd51SMichael Jones if (LHS >= RHS)
1354cfccd51SMichael Jones return true;
1364cfccd51SMichael Jones
1374cfccd51SMichael Jones Ctx->markFail();
1384cfccd51SMichael Jones ExplainDifference("greater than or equal to");
1394cfccd51SMichael Jones return false;
1404cfccd51SMichael Jones default:
1414cfccd51SMichael Jones Ctx->markFail();
1424cfccd51SMichael Jones std::cout << "Unexpected test condition.\n";
1434cfccd51SMichael Jones return false;
1444cfccd51SMichael Jones }
1454cfccd51SMichael Jones }
1464cfccd51SMichael Jones
1474cfccd51SMichael Jones } // namespace internal
1484cfccd51SMichael Jones
1494cfccd51SMichael Jones Test *Test::Start = nullptr;
1504cfccd51SMichael Jones Test *Test::End = nullptr;
1514cfccd51SMichael Jones
addTest(Test * T)1524cfccd51SMichael Jones void Test::addTest(Test *T) {
1534cfccd51SMichael Jones if (End == nullptr) {
1544cfccd51SMichael Jones Start = T;
1554cfccd51SMichael Jones End = T;
1564cfccd51SMichael Jones return;
1574cfccd51SMichael Jones }
1584cfccd51SMichael Jones
1594cfccd51SMichael Jones End->Next = T;
1604cfccd51SMichael Jones End = T;
1614cfccd51SMichael Jones }
1624cfccd51SMichael Jones
runTests(const char * TestFilter)163fa7a9ef1SCaitlyn Cano int Test::runTests(const char *TestFilter) {
1644cfccd51SMichael Jones int TestCount = 0;
1654cfccd51SMichael Jones int FailCount = 0;
166fa7a9ef1SCaitlyn Cano for (Test *T = Start; T != nullptr; T = T->Next) {
1674cfccd51SMichael Jones const char *TestName = T->getName();
168fa7a9ef1SCaitlyn Cano std::string StrTestName(TestName);
1694cfccd51SMichael Jones constexpr auto GREEN = "\033[32m";
1704cfccd51SMichael Jones constexpr auto RED = "\033[31m";
1714cfccd51SMichael Jones constexpr auto RESET = "\033[0m";
172fa7a9ef1SCaitlyn Cano if ((TestFilter != nullptr) && (StrTestName != TestFilter)) {
173fa7a9ef1SCaitlyn Cano continue;
174fa7a9ef1SCaitlyn Cano }
1754cfccd51SMichael Jones std::cout << GREEN << "[ RUN ] " << RESET << TestName << '\n';
1764cfccd51SMichael Jones RunContext Ctx;
1774cfccd51SMichael Jones T->SetUp();
1784cfccd51SMichael Jones T->setContext(&Ctx);
1794cfccd51SMichael Jones T->Run();
1804cfccd51SMichael Jones T->TearDown();
1814cfccd51SMichael Jones auto Result = Ctx.status();
1824cfccd51SMichael Jones switch (Result) {
1834cfccd51SMichael Jones case RunContext::Result_Fail:
1844cfccd51SMichael Jones std::cout << RED << "[ FAILED ] " << RESET << TestName << '\n';
1854cfccd51SMichael Jones ++FailCount;
1864cfccd51SMichael Jones break;
1874cfccd51SMichael Jones case RunContext::Result_Pass:
1884cfccd51SMichael Jones std::cout << GREEN << "[ OK ] " << RESET << TestName << '\n';
1894cfccd51SMichael Jones break;
1904cfccd51SMichael Jones }
191fa7a9ef1SCaitlyn Cano ++TestCount;
1924cfccd51SMichael Jones }
1934cfccd51SMichael Jones
194fa7a9ef1SCaitlyn Cano if (TestCount > 0) {
1954cfccd51SMichael Jones std::cout << "Ran " << TestCount << " tests. "
1964cfccd51SMichael Jones << " PASS: " << TestCount - FailCount << ' '
1974cfccd51SMichael Jones << " FAIL: " << FailCount << '\n';
198fa7a9ef1SCaitlyn Cano } else {
199fa7a9ef1SCaitlyn Cano std::cout << "No tests run.\n";
200fa7a9ef1SCaitlyn Cano if (TestFilter) {
201fa7a9ef1SCaitlyn Cano std::cout << "No matching test for " << TestFilter << '\n';
202fa7a9ef1SCaitlyn Cano }
203fa7a9ef1SCaitlyn Cano }
2044cfccd51SMichael Jones
205fa7a9ef1SCaitlyn Cano return FailCount > 0 || TestCount == 0 ? 1 : 0;
2064cfccd51SMichael Jones }
2074cfccd51SMichael Jones
208d2c59546SGuillaume Chatelet namespace internal {
209d2c59546SGuillaume Chatelet
210d2c59546SGuillaume Chatelet template bool test<char>(RunContext *Ctx, TestCondition Cond, char LHS,
211d2c59546SGuillaume Chatelet char RHS, const char *LHSStr, const char *RHSStr,
212d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
213d2c59546SGuillaume Chatelet
214d2c59546SGuillaume Chatelet template bool test<short>(RunContext *Ctx, TestCondition Cond, short LHS,
215d2c59546SGuillaume Chatelet short RHS, const char *LHSStr, const char *RHSStr,
216d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
217d2c59546SGuillaume Chatelet
218d2c59546SGuillaume Chatelet template bool test<int>(RunContext *Ctx, TestCondition Cond, int LHS, int RHS,
2194cfccd51SMichael Jones const char *LHSStr, const char *RHSStr,
2204cfccd51SMichael Jones const char *File, unsigned long Line);
2214cfccd51SMichael Jones
222d2c59546SGuillaume Chatelet template bool test<long>(RunContext *Ctx, TestCondition Cond, long LHS,
223d2c59546SGuillaume Chatelet long RHS, const char *LHSStr, const char *RHSStr,
2244cfccd51SMichael Jones const char *File, unsigned long Line);
2254cfccd51SMichael Jones
226d2c59546SGuillaume Chatelet template bool test<long long>(RunContext *Ctx, TestCondition Cond,
227d2c59546SGuillaume Chatelet long long LHS, long long RHS, const char *LHSStr,
2284cfccd51SMichael Jones const char *RHSStr, const char *File,
2294cfccd51SMichael Jones unsigned long Line);
2304cfccd51SMichael Jones
231d2c59546SGuillaume Chatelet template bool test<unsigned char>(RunContext *Ctx, TestCondition Cond,
2324cfccd51SMichael Jones unsigned char LHS, unsigned char RHS,
2334cfccd51SMichael Jones const char *LHSStr, const char *RHSStr,
2344cfccd51SMichael Jones const char *File, unsigned long Line);
2354cfccd51SMichael Jones
236d2c59546SGuillaume Chatelet template bool test<unsigned short>(RunContext *Ctx, TestCondition Cond,
237d2c59546SGuillaume Chatelet unsigned short LHS, unsigned short RHS,
238d2c59546SGuillaume Chatelet const char *LHSStr, const char *RHSStr,
239d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
2404cfccd51SMichael Jones
241d2c59546SGuillaume Chatelet template bool test<unsigned int>(RunContext *Ctx, TestCondition Cond,
242d2c59546SGuillaume Chatelet unsigned int LHS, unsigned int RHS,
243d2c59546SGuillaume Chatelet const char *LHSStr, const char *RHSStr,
244d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
245d2c59546SGuillaume Chatelet
246d2c59546SGuillaume Chatelet template bool test<unsigned long>(RunContext *Ctx, TestCondition Cond,
247d2c59546SGuillaume Chatelet unsigned long LHS, unsigned long RHS,
248d2c59546SGuillaume Chatelet const char *LHSStr, const char *RHSStr,
249d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
250d2c59546SGuillaume Chatelet
251d2c59546SGuillaume Chatelet template bool test<bool>(RunContext *Ctx, TestCondition Cond, bool LHS,
252d2c59546SGuillaume Chatelet bool RHS, const char *LHSStr, const char *RHSStr,
253d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
254d2c59546SGuillaume Chatelet
255d2c59546SGuillaume Chatelet template bool test<unsigned long long>(RunContext *Ctx, TestCondition Cond,
256d2c59546SGuillaume Chatelet unsigned long long LHS,
257d2c59546SGuillaume Chatelet unsigned long long RHS,
258d2c59546SGuillaume Chatelet const char *LHSStr, const char *RHSStr,
259d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
260d2c59546SGuillaume Chatelet
261*300f8da8SSiva Chandra Reddy // We cannot just use a single UInt128 specialization as that resolves to only
262*300f8da8SSiva Chandra Reddy // one type, UInt<128> or __uint128_t. We want both overloads as we want to
263*300f8da8SSiva Chandra Reddy // be able to unittest UInt<128> on platforms where UInt128 resolves to
264*300f8da8SSiva Chandra Reddy // UInt128.
265ce6bfd10SDominic Chen #ifdef __SIZEOF_INT128__
266*300f8da8SSiva Chandra Reddy // When builtin __uint128_t type is available, include its specialization
267*300f8da8SSiva Chandra Reddy // also.
268d2c59546SGuillaume Chatelet template bool test<__uint128_t>(RunContext *Ctx, TestCondition Cond,
269d2c59546SGuillaume Chatelet __uint128_t LHS, __uint128_t RHS,
270d2c59546SGuillaume Chatelet const char *LHSStr, const char *RHSStr,
271d2c59546SGuillaume Chatelet const char *File, unsigned long Line);
272ce6bfd10SDominic Chen #endif
273d2c59546SGuillaume Chatelet
274*300f8da8SSiva Chandra Reddy template bool test<__llvm_libc::cpp::UInt<128>>(
275*300f8da8SSiva Chandra Reddy RunContext *Ctx, TestCondition Cond, __llvm_libc::cpp::UInt<128> LHS,
276*300f8da8SSiva Chandra Reddy __llvm_libc::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr,
277*300f8da8SSiva Chandra Reddy const char *File, unsigned long Line);
278*300f8da8SSiva Chandra Reddy
279d2c59546SGuillaume Chatelet } // namespace internal
2804cfccd51SMichael Jones
testStrEq(const char * LHS,const char * RHS,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line)2814cfccd51SMichael Jones bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr,
2824cfccd51SMichael Jones const char *RHSStr, const char *File, unsigned long Line) {
2834cfccd51SMichael Jones return internal::test(Ctx, Cond_EQ, LHS ? std::string(LHS) : std::string(),
2844cfccd51SMichael Jones RHS ? std::string(RHS) : std::string(), LHSStr, RHSStr,
2854cfccd51SMichael Jones File, Line);
2864cfccd51SMichael Jones }
2874cfccd51SMichael Jones
testStrNe(const char * LHS,const char * RHS,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line)2884cfccd51SMichael Jones bool Test::testStrNe(const char *LHS, const char *RHS, const char *LHSStr,
2894cfccd51SMichael Jones const char *RHSStr, const char *File, unsigned long Line) {
2904cfccd51SMichael Jones return internal::test(Ctx, Cond_NE, LHS ? std::string(LHS) : std::string(),
2914cfccd51SMichael Jones RHS ? std::string(RHS) : std::string(), LHSStr, RHSStr,
2924cfccd51SMichael Jones File, Line);
2934cfccd51SMichael Jones }
2944cfccd51SMichael Jones
testMatch(bool MatchResult,MatcherBase & Matcher,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line)2954cfccd51SMichael Jones bool Test::testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr,
2964cfccd51SMichael Jones const char *RHSStr, const char *File, unsigned long Line) {
2974cfccd51SMichael Jones if (MatchResult)
2984cfccd51SMichael Jones return true;
2994cfccd51SMichael Jones
3004cfccd51SMichael Jones Ctx->markFail();
3014cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3024cfccd51SMichael Jones << "Failed to match " << LHSStr << " against " << RHSStr << ".\n";
3034cfccd51SMichael Jones testutils::StreamWrapper OutsWrapper = testutils::outs();
3044cfccd51SMichael Jones Matcher.explainError(OutsWrapper);
3054cfccd51SMichael Jones return false;
3064cfccd51SMichael Jones }
3074cfccd51SMichael Jones
3086344a583SSiva Chandra Reddy #ifdef ENABLE_SUBPROCESS_TESTS
3096344a583SSiva Chandra Reddy
testProcessKilled(testutils::FunctionCaller * Func,int Signal,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line)3104cfccd51SMichael Jones bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
3114cfccd51SMichael Jones const char *LHSStr, const char *RHSStr,
3124cfccd51SMichael Jones const char *File, unsigned long Line) {
31325226f3eSMichael Jones testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500);
3144cfccd51SMichael Jones
31525226f3eSMichael Jones if (const char *error = Result.get_error()) {
3164cfccd51SMichael Jones Ctx->markFail();
3174cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n" << error << '\n';
3184cfccd51SMichael Jones return false;
3194cfccd51SMichael Jones }
3204cfccd51SMichael Jones
32125226f3eSMichael Jones if (Result.timed_out()) {
3224cfccd51SMichael Jones Ctx->markFail();
3234cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3244cfccd51SMichael Jones << "Process timed out after " << 500 << " milliseconds.\n";
3254cfccd51SMichael Jones return false;
3264cfccd51SMichael Jones }
3274cfccd51SMichael Jones
32825226f3eSMichael Jones if (Result.exited_normally()) {
3294cfccd51SMichael Jones Ctx->markFail();
3304cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3314cfccd51SMichael Jones << "Expected " << LHSStr
3324cfccd51SMichael Jones << " to be killed by a signal\nBut it exited normally!\n";
3334cfccd51SMichael Jones return false;
3344cfccd51SMichael Jones }
3354cfccd51SMichael Jones
33625226f3eSMichael Jones int KilledBy = Result.get_fatal_signal();
3374cfccd51SMichael Jones assert(KilledBy != 0 && "Not killed by any signal");
3384cfccd51SMichael Jones if (Signal == -1 || KilledBy == Signal)
3394cfccd51SMichael Jones return true;
3404cfccd51SMichael Jones
34125226f3eSMichael Jones using testutils::signal_as_string;
3424cfccd51SMichael Jones Ctx->markFail();
3434cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3444cfccd51SMichael Jones << " Expected: " << LHSStr << '\n'
3454cfccd51SMichael Jones << "To be killed by signal: " << Signal << '\n'
34625226f3eSMichael Jones << " Which is: " << signal_as_string(Signal) << '\n'
3474cfccd51SMichael Jones << " But it was killed by: " << KilledBy << '\n'
34825226f3eSMichael Jones << " Which is: " << signal_as_string(KilledBy) << '\n';
3494cfccd51SMichael Jones return false;
3504cfccd51SMichael Jones }
3514cfccd51SMichael Jones
testProcessExits(testutils::FunctionCaller * Func,int ExitCode,const char * LHSStr,const char * RHSStr,const char * File,unsigned long Line)3524cfccd51SMichael Jones bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode,
3534cfccd51SMichael Jones const char *LHSStr, const char *RHSStr,
3544cfccd51SMichael Jones const char *File, unsigned long Line) {
35525226f3eSMichael Jones testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500);
3564cfccd51SMichael Jones
35725226f3eSMichael Jones if (const char *error = Result.get_error()) {
3584cfccd51SMichael Jones Ctx->markFail();
3594cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n" << error << '\n';
3604cfccd51SMichael Jones return false;
3614cfccd51SMichael Jones }
3624cfccd51SMichael Jones
36325226f3eSMichael Jones if (Result.timed_out()) {
3644cfccd51SMichael Jones Ctx->markFail();
3654cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3664cfccd51SMichael Jones << "Process timed out after " << 500 << " milliseconds.\n";
3674cfccd51SMichael Jones return false;
3684cfccd51SMichael Jones }
3694cfccd51SMichael Jones
37025226f3eSMichael Jones if (!Result.exited_normally()) {
3714cfccd51SMichael Jones Ctx->markFail();
3724cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3734cfccd51SMichael Jones << "Expected " << LHSStr << '\n'
3744cfccd51SMichael Jones << "to exit with exit code " << ExitCode << '\n'
3754cfccd51SMichael Jones << "But it exited abnormally!\n";
3764cfccd51SMichael Jones return false;
3774cfccd51SMichael Jones }
3784cfccd51SMichael Jones
37925226f3eSMichael Jones int ActualExit = Result.get_exit_code();
3804cfccd51SMichael Jones if (ActualExit == ExitCode)
3814cfccd51SMichael Jones return true;
3824cfccd51SMichael Jones
3834cfccd51SMichael Jones Ctx->markFail();
3844cfccd51SMichael Jones std::cout << File << ":" << Line << ": FAILURE\n"
3854cfccd51SMichael Jones << "Expected exit code of: " << LHSStr << '\n'
3864cfccd51SMichael Jones << " Which is: " << ActualExit << '\n'
3874cfccd51SMichael Jones << " To be equal to: " << RHSStr << '\n'
3884cfccd51SMichael Jones << " Which is: " << ExitCode << '\n';
3894cfccd51SMichael Jones return false;
3904cfccd51SMichael Jones }
3914cfccd51SMichael Jones
3926344a583SSiva Chandra Reddy #endif // ENABLE_SUBPROCESS_TESTS
3934cfccd51SMichael Jones } // namespace testing
3944cfccd51SMichael Jones } // namespace __llvm_libc
395