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 
114cfccd51SMichael Jones #include "utils/testutils/ExecuteFunction.h"
124cfccd51SMichael Jones #include <cassert>
134cfccd51SMichael Jones #include <iostream>
144cfccd51SMichael Jones #include <string>
154cfccd51SMichael Jones 
164cfccd51SMichael Jones namespace __llvm_libc {
174cfccd51SMichael Jones namespace testing {
184cfccd51SMichael Jones 
194cfccd51SMichael Jones // This need not be a class as all it has is a single read-write state variable.
204cfccd51SMichael Jones // But, we make it class as then its implementation can be hidden from the
214cfccd51SMichael Jones // header file.
224cfccd51SMichael Jones class RunContext {
234cfccd51SMichael Jones public:
244cfccd51SMichael Jones   enum RunResult { Result_Pass = 1, Result_Fail = 2 };
254cfccd51SMichael Jones 
264cfccd51SMichael Jones   RunResult status() const { return Status; }
274cfccd51SMichael Jones 
284cfccd51SMichael Jones   void markFail() { Status = Result_Fail; }
294cfccd51SMichael Jones 
304cfccd51SMichael Jones private:
314cfccd51SMichael Jones   RunResult Status = Result_Pass;
324cfccd51SMichael Jones };
334cfccd51SMichael Jones 
344cfccd51SMichael Jones namespace internal {
354cfccd51SMichael Jones 
364cfccd51SMichael Jones // When the value is of integral type, just display it as normal.
374cfccd51SMichael Jones template <typename ValType>
384cfccd51SMichael Jones cpp::EnableIfType<cpp::IsIntegral<ValType>::Value, std::string>
394cfccd51SMichael Jones describeValue(ValType Value) {
404cfccd51SMichael Jones   return std::to_string(Value);
414cfccd51SMichael Jones }
424cfccd51SMichael Jones 
434cfccd51SMichael Jones std::string describeValue(std::string Value) { return std::string(Value); }
444cfccd51SMichael Jones 
454cfccd51SMichael Jones // When the value is __uint128_t, also show its hexadecimal digits.
464cfccd51SMichael Jones // Using template to force exact match, prevent ambiguous promotion.
47b62d72f3SMichael Jones std::string describeValue128(__uint128_t Value) {
484cfccd51SMichael Jones   std::string S(sizeof(__uint128_t) * 2, '0');
494cfccd51SMichael Jones 
504cfccd51SMichael Jones   for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value >>= 4) {
514cfccd51SMichael Jones     unsigned char Mod = static_cast<unsigned char>(Value) & 15;
524cfccd51SMichael Jones     *I = Mod < 10 ? '0' + Mod : 'a' + Mod - 10;
534cfccd51SMichael Jones   }
544cfccd51SMichael Jones 
554cfccd51SMichael Jones   return "0x" + S;
564cfccd51SMichael Jones }
574cfccd51SMichael Jones 
58b62d72f3SMichael Jones template <> std::string describeValue<__int128_t>(__int128_t Value) {
59b62d72f3SMichael Jones   return describeValue128(Value);
60b62d72f3SMichael Jones }
61b62d72f3SMichael Jones template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
62b62d72f3SMichael Jones   return describeValue128(Value);
63b62d72f3SMichael Jones }
64b62d72f3SMichael Jones 
654cfccd51SMichael Jones template <typename ValType>
664cfccd51SMichael Jones void explainDifference(ValType LHS, ValType RHS, const char *LHSStr,
674cfccd51SMichael Jones                        const char *RHSStr, const char *File, unsigned long Line,
684cfccd51SMichael Jones                        std::string OpString) {
694cfccd51SMichael Jones   size_t OffsetLength = OpString.size() > 2 ? OpString.size() - 2 : 0;
704cfccd51SMichael Jones   std::string Offset(OffsetLength, ' ');
714cfccd51SMichael Jones 
724cfccd51SMichael Jones   std::cout << File << ":" << Line << ": FAILURE\n"
734cfccd51SMichael Jones             << Offset << "Expected: " << LHSStr << '\n'
744cfccd51SMichael Jones             << Offset << "Which is: " << describeValue(LHS) << '\n'
754cfccd51SMichael Jones             << "To be " << OpString << ": " << RHSStr << '\n'
764cfccd51SMichael Jones             << Offset << "Which is: " << describeValue(RHS) << '\n';
774cfccd51SMichael Jones }
784cfccd51SMichael Jones 
794cfccd51SMichael Jones template <typename ValType>
804cfccd51SMichael Jones bool test(RunContext *Ctx, TestCondition Cond, ValType LHS, ValType RHS,
814cfccd51SMichael Jones           const char *LHSStr, const char *RHSStr, const char *File,
824cfccd51SMichael Jones           unsigned long Line) {
834cfccd51SMichael Jones   auto ExplainDifference = [=](std::string OpString) {
844cfccd51SMichael Jones     explainDifference(LHS, RHS, LHSStr, RHSStr, File, Line, OpString);
854cfccd51SMichael Jones   };
864cfccd51SMichael Jones 
874cfccd51SMichael Jones   switch (Cond) {
884cfccd51SMichael Jones   case Cond_EQ:
894cfccd51SMichael Jones     if (LHS == RHS)
904cfccd51SMichael Jones       return true;
914cfccd51SMichael Jones 
924cfccd51SMichael Jones     Ctx->markFail();
934cfccd51SMichael Jones     ExplainDifference("equal to");
944cfccd51SMichael Jones     return false;
954cfccd51SMichael Jones   case Cond_NE:
964cfccd51SMichael Jones     if (LHS != RHS)
974cfccd51SMichael Jones       return true;
984cfccd51SMichael Jones 
994cfccd51SMichael Jones     Ctx->markFail();
1004cfccd51SMichael Jones     ExplainDifference("not equal to");
1014cfccd51SMichael Jones     return false;
1024cfccd51SMichael Jones   case Cond_LT:
1034cfccd51SMichael Jones     if (LHS < RHS)
1044cfccd51SMichael Jones       return true;
1054cfccd51SMichael Jones 
1064cfccd51SMichael Jones     Ctx->markFail();
1074cfccd51SMichael Jones     ExplainDifference("less than");
1084cfccd51SMichael Jones     return false;
1094cfccd51SMichael Jones   case Cond_LE:
1104cfccd51SMichael Jones     if (LHS <= RHS)
1114cfccd51SMichael Jones       return true;
1124cfccd51SMichael Jones 
1134cfccd51SMichael Jones     Ctx->markFail();
1144cfccd51SMichael Jones     ExplainDifference("less than or equal to");
1154cfccd51SMichael Jones     return false;
1164cfccd51SMichael Jones   case Cond_GT:
1174cfccd51SMichael Jones     if (LHS > RHS)
1184cfccd51SMichael Jones       return true;
1194cfccd51SMichael Jones 
1204cfccd51SMichael Jones     Ctx->markFail();
1214cfccd51SMichael Jones     ExplainDifference("greater than");
1224cfccd51SMichael Jones     return false;
1234cfccd51SMichael Jones   case Cond_GE:
1244cfccd51SMichael Jones     if (LHS >= RHS)
1254cfccd51SMichael Jones       return true;
1264cfccd51SMichael Jones 
1274cfccd51SMichael Jones     Ctx->markFail();
1284cfccd51SMichael Jones     ExplainDifference("greater than or equal to");
1294cfccd51SMichael Jones     return false;
1304cfccd51SMichael Jones   default:
1314cfccd51SMichael Jones     Ctx->markFail();
1324cfccd51SMichael Jones     std::cout << "Unexpected test condition.\n";
1334cfccd51SMichael Jones     return false;
1344cfccd51SMichael Jones   }
1354cfccd51SMichael Jones }
1364cfccd51SMichael Jones 
1374cfccd51SMichael Jones } // namespace internal
1384cfccd51SMichael Jones 
1394cfccd51SMichael Jones Test *Test::Start = nullptr;
1404cfccd51SMichael Jones Test *Test::End = nullptr;
1414cfccd51SMichael Jones 
1424cfccd51SMichael Jones void Test::addTest(Test *T) {
1434cfccd51SMichael Jones   if (End == nullptr) {
1444cfccd51SMichael Jones     Start = T;
1454cfccd51SMichael Jones     End = T;
1464cfccd51SMichael Jones     return;
1474cfccd51SMichael Jones   }
1484cfccd51SMichael Jones 
1494cfccd51SMichael Jones   End->Next = T;
1504cfccd51SMichael Jones   End = T;
1514cfccd51SMichael Jones }
1524cfccd51SMichael Jones 
153fa7a9ef1SCaitlyn Cano int Test::runTests(const char *TestFilter) {
1544cfccd51SMichael Jones   int TestCount = 0;
1554cfccd51SMichael Jones   int FailCount = 0;
156fa7a9ef1SCaitlyn Cano   for (Test *T = Start; T != nullptr; T = T->Next) {
1574cfccd51SMichael Jones     const char *TestName = T->getName();
158fa7a9ef1SCaitlyn Cano     std::string StrTestName(TestName);
1594cfccd51SMichael Jones     constexpr auto GREEN = "\033[32m";
1604cfccd51SMichael Jones     constexpr auto RED = "\033[31m";
1614cfccd51SMichael Jones     constexpr auto RESET = "\033[0m";
162fa7a9ef1SCaitlyn Cano     if ((TestFilter != nullptr) && (StrTestName != TestFilter)) {
163fa7a9ef1SCaitlyn Cano       continue;
164fa7a9ef1SCaitlyn Cano     }
1654cfccd51SMichael Jones     std::cout << GREEN << "[ RUN      ] " << RESET << TestName << '\n';
1664cfccd51SMichael Jones     RunContext Ctx;
1674cfccd51SMichael Jones     T->SetUp();
1684cfccd51SMichael Jones     T->setContext(&Ctx);
1694cfccd51SMichael Jones     T->Run();
1704cfccd51SMichael Jones     T->TearDown();
1714cfccd51SMichael Jones     auto Result = Ctx.status();
1724cfccd51SMichael Jones     switch (Result) {
1734cfccd51SMichael Jones     case RunContext::Result_Fail:
1744cfccd51SMichael Jones       std::cout << RED << "[  FAILED  ] " << RESET << TestName << '\n';
1754cfccd51SMichael Jones       ++FailCount;
1764cfccd51SMichael Jones       break;
1774cfccd51SMichael Jones     case RunContext::Result_Pass:
1784cfccd51SMichael Jones       std::cout << GREEN << "[       OK ] " << RESET << TestName << '\n';
1794cfccd51SMichael Jones       break;
1804cfccd51SMichael Jones     }
181fa7a9ef1SCaitlyn Cano     ++TestCount;
1824cfccd51SMichael Jones   }
1834cfccd51SMichael Jones 
184fa7a9ef1SCaitlyn Cano   if (TestCount > 0) {
1854cfccd51SMichael Jones     std::cout << "Ran " << TestCount << " tests. "
1864cfccd51SMichael Jones               << " PASS: " << TestCount - FailCount << ' '
1874cfccd51SMichael Jones               << " FAIL: " << FailCount << '\n';
188fa7a9ef1SCaitlyn Cano   } else {
189fa7a9ef1SCaitlyn Cano     std::cout << "No tests run.\n";
190fa7a9ef1SCaitlyn Cano     if (TestFilter) {
191fa7a9ef1SCaitlyn Cano       std::cout << "No matching test for " << TestFilter << '\n';
192fa7a9ef1SCaitlyn Cano     }
193fa7a9ef1SCaitlyn Cano   }
1944cfccd51SMichael Jones 
195fa7a9ef1SCaitlyn Cano   return FailCount > 0 || TestCount == 0 ? 1 : 0;
1964cfccd51SMichael Jones }
1974cfccd51SMichael Jones 
198*d2c59546SGuillaume Chatelet namespace internal {
199*d2c59546SGuillaume Chatelet 
200*d2c59546SGuillaume Chatelet template bool test<char>(RunContext *Ctx, TestCondition Cond, char LHS,
201*d2c59546SGuillaume Chatelet                          char RHS, const char *LHSStr, const char *RHSStr,
202*d2c59546SGuillaume Chatelet                          const char *File, unsigned long Line);
203*d2c59546SGuillaume Chatelet 
204*d2c59546SGuillaume Chatelet template bool test<short>(RunContext *Ctx, TestCondition Cond, short LHS,
205*d2c59546SGuillaume Chatelet                           short RHS, const char *LHSStr, const char *RHSStr,
206*d2c59546SGuillaume Chatelet                           const char *File, unsigned long Line);
207*d2c59546SGuillaume Chatelet 
208*d2c59546SGuillaume Chatelet template bool test<int>(RunContext *Ctx, TestCondition Cond, int LHS, int RHS,
2094cfccd51SMichael Jones                         const char *LHSStr, const char *RHSStr,
2104cfccd51SMichael Jones                         const char *File, unsigned long Line);
2114cfccd51SMichael Jones 
212*d2c59546SGuillaume Chatelet template bool test<long>(RunContext *Ctx, TestCondition Cond, long LHS,
213*d2c59546SGuillaume Chatelet                          long RHS, const char *LHSStr, const char *RHSStr,
2144cfccd51SMichael Jones                          const char *File, unsigned long Line);
2154cfccd51SMichael Jones 
216*d2c59546SGuillaume Chatelet template bool test<long long>(RunContext *Ctx, TestCondition Cond,
217*d2c59546SGuillaume Chatelet                               long long LHS, long long RHS, const char *LHSStr,
2184cfccd51SMichael Jones                               const char *RHSStr, const char *File,
2194cfccd51SMichael Jones                               unsigned long Line);
2204cfccd51SMichael Jones 
221*d2c59546SGuillaume Chatelet template bool test<__int128_t>(RunContext *Ctx, TestCondition Cond,
222*d2c59546SGuillaume Chatelet                                __int128_t LHS, __int128_t RHS,
223*d2c59546SGuillaume Chatelet                                const char *LHSStr, const char *RHSStr,
224*d2c59546SGuillaume Chatelet                                const char *File, unsigned long Line);
225b62d72f3SMichael Jones 
226*d2c59546SGuillaume Chatelet template bool test<unsigned char>(RunContext *Ctx, TestCondition Cond,
2274cfccd51SMichael Jones                                   unsigned char LHS, unsigned char RHS,
2284cfccd51SMichael Jones                                   const char *LHSStr, const char *RHSStr,
2294cfccd51SMichael Jones                                   const char *File, unsigned long Line);
2304cfccd51SMichael Jones 
231*d2c59546SGuillaume Chatelet template bool test<unsigned short>(RunContext *Ctx, TestCondition Cond,
232*d2c59546SGuillaume Chatelet                                    unsigned short LHS, unsigned short RHS,
233*d2c59546SGuillaume Chatelet                                    const char *LHSStr, const char *RHSStr,
234*d2c59546SGuillaume Chatelet                                    const char *File, unsigned long Line);
2354cfccd51SMichael Jones 
236*d2c59546SGuillaume Chatelet template bool test<unsigned int>(RunContext *Ctx, TestCondition Cond,
237*d2c59546SGuillaume Chatelet                                  unsigned int LHS, unsigned int RHS,
238*d2c59546SGuillaume Chatelet                                  const char *LHSStr, const char *RHSStr,
239*d2c59546SGuillaume Chatelet                                  const char *File, unsigned long Line);
240*d2c59546SGuillaume Chatelet 
241*d2c59546SGuillaume Chatelet template bool test<unsigned long>(RunContext *Ctx, TestCondition Cond,
242*d2c59546SGuillaume Chatelet                                   unsigned long LHS, unsigned long RHS,
243*d2c59546SGuillaume Chatelet                                   const char *LHSStr, const char *RHSStr,
244*d2c59546SGuillaume Chatelet                                   const char *File, unsigned long Line);
245*d2c59546SGuillaume Chatelet 
246*d2c59546SGuillaume Chatelet template bool test<bool>(RunContext *Ctx, TestCondition Cond, bool LHS,
247*d2c59546SGuillaume Chatelet                          bool RHS, const char *LHSStr, const char *RHSStr,
248*d2c59546SGuillaume Chatelet                          const char *File, unsigned long Line);
249*d2c59546SGuillaume Chatelet 
250*d2c59546SGuillaume Chatelet template bool test<unsigned long long>(RunContext *Ctx, TestCondition Cond,
251*d2c59546SGuillaume Chatelet                                        unsigned long long LHS,
252*d2c59546SGuillaume Chatelet                                        unsigned long long RHS,
253*d2c59546SGuillaume Chatelet                                        const char *LHSStr, const char *RHSStr,
254*d2c59546SGuillaume Chatelet                                        const char *File, unsigned long Line);
255*d2c59546SGuillaume Chatelet 
256*d2c59546SGuillaume Chatelet template bool test<__uint128_t>(RunContext *Ctx, TestCondition Cond,
257*d2c59546SGuillaume Chatelet                                 __uint128_t LHS, __uint128_t RHS,
258*d2c59546SGuillaume Chatelet                                 const char *LHSStr, const char *RHSStr,
259*d2c59546SGuillaume Chatelet                                 const char *File, unsigned long Line);
260*d2c59546SGuillaume Chatelet 
261*d2c59546SGuillaume Chatelet } // namespace internal
2624cfccd51SMichael Jones 
2634cfccd51SMichael Jones bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr,
2644cfccd51SMichael Jones                      const char *RHSStr, const char *File, unsigned long Line) {
2654cfccd51SMichael Jones   return internal::test(Ctx, Cond_EQ, LHS ? std::string(LHS) : std::string(),
2664cfccd51SMichael Jones                         RHS ? std::string(RHS) : std::string(), LHSStr, RHSStr,
2674cfccd51SMichael Jones                         File, Line);
2684cfccd51SMichael Jones }
2694cfccd51SMichael Jones 
2704cfccd51SMichael Jones bool Test::testStrNe(const char *LHS, const char *RHS, const char *LHSStr,
2714cfccd51SMichael Jones                      const char *RHSStr, const char *File, unsigned long Line) {
2724cfccd51SMichael Jones   return internal::test(Ctx, Cond_NE, LHS ? std::string(LHS) : std::string(),
2734cfccd51SMichael Jones                         RHS ? std::string(RHS) : std::string(), LHSStr, RHSStr,
2744cfccd51SMichael Jones                         File, Line);
2754cfccd51SMichael Jones }
2764cfccd51SMichael Jones 
2774cfccd51SMichael Jones bool Test::testMatch(bool MatchResult, MatcherBase &Matcher, const char *LHSStr,
2784cfccd51SMichael Jones                      const char *RHSStr, const char *File, unsigned long Line) {
2794cfccd51SMichael Jones   if (MatchResult)
2804cfccd51SMichael Jones     return true;
2814cfccd51SMichael Jones 
2824cfccd51SMichael Jones   Ctx->markFail();
2834cfccd51SMichael Jones   std::cout << File << ":" << Line << ": FAILURE\n"
2844cfccd51SMichael Jones             << "Failed to match " << LHSStr << " against " << RHSStr << ".\n";
2854cfccd51SMichael Jones   testutils::StreamWrapper OutsWrapper = testutils::outs();
2864cfccd51SMichael Jones   Matcher.explainError(OutsWrapper);
2874cfccd51SMichael Jones   return false;
2884cfccd51SMichael Jones }
2894cfccd51SMichael Jones 
2906344a583SSiva Chandra Reddy #ifdef ENABLE_SUBPROCESS_TESTS
2916344a583SSiva Chandra Reddy 
2924cfccd51SMichael Jones bool Test::testProcessKilled(testutils::FunctionCaller *Func, int Signal,
2934cfccd51SMichael Jones                              const char *LHSStr, const char *RHSStr,
2944cfccd51SMichael Jones                              const char *File, unsigned long Line) {
29525226f3eSMichael Jones   testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500);
2964cfccd51SMichael Jones 
29725226f3eSMichael Jones   if (const char *error = Result.get_error()) {
2984cfccd51SMichael Jones     Ctx->markFail();
2994cfccd51SMichael Jones     std::cout << File << ":" << Line << ": FAILURE\n" << error << '\n';
3004cfccd51SMichael Jones     return false;
3014cfccd51SMichael Jones   }
3024cfccd51SMichael Jones 
30325226f3eSMichael Jones   if (Result.timed_out()) {
3044cfccd51SMichael Jones     Ctx->markFail();
3054cfccd51SMichael Jones     std::cout << File << ":" << Line << ": FAILURE\n"
3064cfccd51SMichael Jones               << "Process timed out after " << 500 << " milliseconds.\n";
3074cfccd51SMichael Jones     return false;
3084cfccd51SMichael Jones   }
3094cfccd51SMichael Jones 
31025226f3eSMichael Jones   if (Result.exited_normally()) {
3114cfccd51SMichael Jones     Ctx->markFail();
3124cfccd51SMichael Jones     std::cout << File << ":" << Line << ": FAILURE\n"
3134cfccd51SMichael Jones               << "Expected " << LHSStr
3144cfccd51SMichael Jones               << " to be killed by a signal\nBut it exited normally!\n";
3154cfccd51SMichael Jones     return false;
3164cfccd51SMichael Jones   }
3174cfccd51SMichael Jones 
31825226f3eSMichael Jones   int KilledBy = Result.get_fatal_signal();
3194cfccd51SMichael Jones   assert(KilledBy != 0 && "Not killed by any signal");
3204cfccd51SMichael Jones   if (Signal == -1 || KilledBy == Signal)
3214cfccd51SMichael Jones     return true;
3224cfccd51SMichael Jones 
32325226f3eSMichael Jones   using testutils::signal_as_string;
3244cfccd51SMichael Jones   Ctx->markFail();
3254cfccd51SMichael Jones   std::cout << File << ":" << Line << ": FAILURE\n"
3264cfccd51SMichael Jones             << "              Expected: " << LHSStr << '\n'
3274cfccd51SMichael Jones             << "To be killed by signal: " << Signal << '\n'
32825226f3eSMichael Jones             << "              Which is: " << signal_as_string(Signal) << '\n'
3294cfccd51SMichael Jones             << "  But it was killed by: " << KilledBy << '\n'
33025226f3eSMichael Jones             << "              Which is: " << signal_as_string(KilledBy) << '\n';
3314cfccd51SMichael Jones   return false;
3324cfccd51SMichael Jones }
3334cfccd51SMichael Jones 
3344cfccd51SMichael Jones bool Test::testProcessExits(testutils::FunctionCaller *Func, int ExitCode,
3354cfccd51SMichael Jones                             const char *LHSStr, const char *RHSStr,
3364cfccd51SMichael Jones                             const char *File, unsigned long Line) {
33725226f3eSMichael Jones   testutils::ProcessStatus Result = testutils::invoke_in_subprocess(Func, 500);
3384cfccd51SMichael Jones 
33925226f3eSMichael Jones   if (const char *error = Result.get_error()) {
3404cfccd51SMichael Jones     Ctx->markFail();
3414cfccd51SMichael Jones     std::cout << File << ":" << Line << ": FAILURE\n" << error << '\n';
3424cfccd51SMichael Jones     return false;
3434cfccd51SMichael Jones   }
3444cfccd51SMichael Jones 
34525226f3eSMichael Jones   if (Result.timed_out()) {
3464cfccd51SMichael Jones     Ctx->markFail();
3474cfccd51SMichael Jones     std::cout << File << ":" << Line << ": FAILURE\n"
3484cfccd51SMichael Jones               << "Process timed out after " << 500 << " milliseconds.\n";
3494cfccd51SMichael Jones     return false;
3504cfccd51SMichael Jones   }
3514cfccd51SMichael Jones 
35225226f3eSMichael Jones   if (!Result.exited_normally()) {
3534cfccd51SMichael Jones     Ctx->markFail();
3544cfccd51SMichael Jones     std::cout << File << ":" << Line << ": FAILURE\n"
3554cfccd51SMichael Jones               << "Expected " << LHSStr << '\n'
3564cfccd51SMichael Jones               << "to exit with exit code " << ExitCode << '\n'
3574cfccd51SMichael Jones               << "But it exited abnormally!\n";
3584cfccd51SMichael Jones     return false;
3594cfccd51SMichael Jones   }
3604cfccd51SMichael Jones 
36125226f3eSMichael Jones   int ActualExit = Result.get_exit_code();
3624cfccd51SMichael Jones   if (ActualExit == ExitCode)
3634cfccd51SMichael Jones     return true;
3644cfccd51SMichael Jones 
3654cfccd51SMichael Jones   Ctx->markFail();
3664cfccd51SMichael Jones   std::cout << File << ":" << Line << ": FAILURE\n"
3674cfccd51SMichael Jones             << "Expected exit code of: " << LHSStr << '\n'
3684cfccd51SMichael Jones             << "             Which is: " << ActualExit << '\n'
3694cfccd51SMichael Jones             << "       To be equal to: " << RHSStr << '\n'
3704cfccd51SMichael Jones             << "             Which is: " << ExitCode << '\n';
3714cfccd51SMichael Jones   return false;
3724cfccd51SMichael Jones }
3734cfccd51SMichael Jones 
3746344a583SSiva Chandra Reddy #endif // ENABLE_SUBPROCESS_TESTS
3754cfccd51SMichael Jones } // namespace testing
3764cfccd51SMichael Jones } // namespace __llvm_libc
377