LCOV - code coverage report
Current view: top level - test/unittests/base - logging-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 63 72 87.5 %
Date: 2019-03-21 Functions: 27 53 50.9 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include <cstdint>
       6             : 
       7             : #include "src/base/logging.h"
       8             : #include "src/objects.h"
       9             : #include "src/objects/smi.h"
      10             : #include "testing/gtest-support.h"
      11             : 
      12             : namespace v8 {
      13             : namespace base {
      14             : namespace logging_unittest {
      15             : 
      16             : namespace {
      17             : 
      18             : #define CHECK_SUCCEED(NAME, lhs, rhs)                                      \
      19             :   {                                                                        \
      20             :     std::string* error_message =                                           \
      21             :         Check##NAME##Impl<decltype(lhs), decltype(rhs)>((lhs), (rhs), ""); \
      22             :     EXPECT_EQ(nullptr, error_message);                                     \
      23             :   }
      24             : 
      25             : #define CHECK_FAIL(NAME, lhs, rhs)                                         \
      26             :   {                                                                        \
      27             :     std::string* error_message =                                           \
      28             :         Check##NAME##Impl<decltype(lhs), decltype(rhs)>((lhs), (rhs), ""); \
      29             :     EXPECT_NE(nullptr, error_message);                                     \
      30             :     delete error_message;                                                  \
      31             :   }
      32             : 
      33             : }  // namespace
      34             : 
      35       15373 : TEST(LoggingTest, CheckEQImpl) {
      36           1 :   CHECK_SUCCEED(EQ, 0.0, 0.0);
      37           1 :   CHECK_SUCCEED(EQ, 0.0, -0.0);
      38           1 :   CHECK_SUCCEED(EQ, -0.0, 0.0);
      39           1 :   CHECK_SUCCEED(EQ, -0.0, -0.0);
      40           1 : }
      41             : 
      42       15373 : TEST(LoggingTest, CompareSignedMismatch) {
      43           1 :   CHECK_SUCCEED(EQ, static_cast<int32_t>(14), static_cast<uint32_t>(14));
      44           3 :   CHECK_FAIL(EQ, static_cast<int32_t>(14), static_cast<uint32_t>(15));
      45           3 :   CHECK_FAIL(EQ, static_cast<int32_t>(-1), static_cast<uint32_t>(-1));
      46           1 :   CHECK_SUCCEED(LT, static_cast<int32_t>(-1), static_cast<uint32_t>(0));
      47           1 :   CHECK_SUCCEED(LT, static_cast<int32_t>(-1), static_cast<uint32_t>(-1));
      48           1 :   CHECK_SUCCEED(LE, static_cast<int32_t>(-1), static_cast<uint32_t>(0));
      49           1 :   CHECK_SUCCEED(LE, static_cast<int32_t>(55), static_cast<uint32_t>(55));
      50           1 :   CHECK_SUCCEED(LT, static_cast<int32_t>(55),
      51             :                 static_cast<uint32_t>(0x7FFFFF00));
      52           1 :   CHECK_SUCCEED(LE, static_cast<int32_t>(55),
      53             :                 static_cast<uint32_t>(0x7FFFFF00));
      54           1 :   CHECK_SUCCEED(GE, static_cast<uint32_t>(0x7FFFFF00),
      55             :                 static_cast<int32_t>(55));
      56           1 :   CHECK_SUCCEED(GT, static_cast<uint32_t>(0x7FFFFF00),
      57             :                 static_cast<int32_t>(55));
      58           1 :   CHECK_SUCCEED(GT, static_cast<uint32_t>(-1), static_cast<int32_t>(-1));
      59           1 :   CHECK_SUCCEED(GE, static_cast<uint32_t>(0), static_cast<int32_t>(-1));
      60           1 :   CHECK_SUCCEED(LT, static_cast<int8_t>(-1), static_cast<uint32_t>(0));
      61           1 :   CHECK_SUCCEED(GT, static_cast<uint64_t>(0x7F01010101010101), 0);
      62           1 :   CHECK_SUCCEED(LE, static_cast<int64_t>(0xFF01010101010101),
      63             :                 static_cast<uint8_t>(13));
      64           1 : }
      65             : 
      66       15373 : TEST(LoggingTest, CompareAgainstStaticConstPointer) {
      67             :   // These used to produce link errors before http://crrev.com/2524093002.
      68           3 :   CHECK_FAIL(EQ, v8::internal::Smi::zero(), v8::internal::Smi::FromInt(17));
      69           1 :   CHECK_SUCCEED(GT, 0, v8::internal::Smi::kMinValue);
      70           1 : }
      71             : 
      72             : #define CHECK_BOTH(name, lhs, rhs) \
      73             :   CHECK_##name(lhs, rhs);          \
      74             :   DCHECK_##name(lhs, rhs)
      75             : 
      76             : namespace {
      77          10 : std::string FailureMessage(const char* msg, const char* debug_msg) {
      78          10 :   std::string regexp(msg);
      79             : #ifdef DEBUG
      80             :   regexp.append(" (").append(debug_msg).append(")");
      81             : #endif
      82             :   size_t last_pos = 0;
      83             :   do {
      84             :     size_t pos = regexp.find_first_of("(){}+*", last_pos);
      85          20 :     if (pos == std::string::npos) break;
      86          10 :     regexp.insert(pos, "\\");
      87          10 :     last_pos = pos + 2;
      88             :   } while (true);
      89          10 :   return regexp;
      90             : }
      91             : }  // namespace
      92             : 
      93       15373 : TEST(LoggingTest, CompareWithDifferentSignedness) {
      94           1 :   int32_t i32 = 10;
      95             :   uint32_t u32 = 20;
      96             :   int64_t i64 = 30;
      97           1 :   uint64_t u64 = 40;
      98             : 
      99             :   // All these checks should compile (!) and succeed.
     100             :   CHECK_BOTH(EQ, i32 + 10, u32);
     101             :   CHECK_BOTH(LT, i32, u64);
     102             :   CHECK_BOTH(LE, u32, i64);
     103             :   CHECK_BOTH(IMPLIES, i32, i64);
     104             :   CHECK_BOTH(IMPLIES, u32, i64);
     105             :   CHECK_BOTH(IMPLIES, !u32, !i64);
     106             : 
     107             :   // Check that the values are output correctly on error.
     108           3 :   ASSERT_DEATH_IF_SUPPORTED(
     109             :       ([&] { CHECK_GT(i32, u64); })(),
     110             :       FailureMessage("Check failed: i32 > u64", "10 vs. 40"));
     111             : }
     112             : 
     113       15373 : TEST(LoggingTest, CompareWithReferenceType) {
     114           1 :   int32_t i32 = 10;
     115             :   uint32_t u32 = 20;
     116             :   int64_t i64 = 30;
     117           1 :   uint64_t u64 = 40;
     118             : 
     119             :   // All these checks should compile (!) and succeed.
     120             :   CHECK_BOTH(EQ, i32 + 10, *&u32);
     121             :   CHECK_BOTH(LT, *&i32, u64);
     122             :   CHECK_BOTH(IMPLIES, *&i32, i64);
     123             :   CHECK_BOTH(IMPLIES, *&i32, u64);
     124             : 
     125             :   // Check that the values are output correctly on error.
     126           3 :   ASSERT_DEATH_IF_SUPPORTED(
     127             :       ([&] { CHECK_GT(*&i32, u64); })(),
     128             :       FailureMessage("Check failed: *&i32 > u64", "10 vs. 40"));
     129             : }
     130             : 
     131             : enum TestEnum1 { ONE, TWO };
     132             : enum TestEnum2 : uint16_t { FOO = 14, BAR = 5 };
     133             : enum class TestEnum3 { A, B };
     134             : enum class TestEnum4 : uint8_t { FIRST, SECOND };
     135             : 
     136       15373 : TEST(LoggingTest, CompareEnumTypes) {
     137             :   // All these checks should compile (!) and succeed.
     138             :   CHECK_BOTH(EQ, ONE, ONE);
     139             :   CHECK_BOTH(LT, ONE, TWO);
     140             :   CHECK_BOTH(EQ, BAR, 5);
     141             :   CHECK_BOTH(LT, BAR, FOO);
     142             :   CHECK_BOTH(EQ, TestEnum3::A, TestEnum3::A);
     143             :   CHECK_BOTH(LT, TestEnum3::A, TestEnum3::B);
     144             :   CHECK_BOTH(EQ, TestEnum4::FIRST, TestEnum4::FIRST);
     145             :   CHECK_BOTH(LT, TestEnum4::FIRST, TestEnum4::SECOND);
     146           1 : }
     147             : 
     148             : class TestClass1 {
     149             :  public:
     150             :   bool operator==(const TestClass1&) const { return true; }
     151             :   bool operator!=(const TestClass1&) const { return false; }
     152             : };
     153             : class TestClass2 {
     154             :  public:
     155             :   explicit TestClass2(int val) : val_(val) {}
     156             :   bool operator<(const TestClass2& other) const { return val_ < other.val_; }
     157           0 :   int val() const { return val_; }
     158             : 
     159             :  private:
     160             :   int val_;
     161             : };
     162           0 : std::ostream& operator<<(std::ostream& str, const TestClass2& val) {
     163           0 :   return str << "TestClass2(" << val.val() << ")";
     164             : }
     165             : 
     166       15373 : TEST(LoggingTest, CompareClassTypes) {
     167             :   // All these checks should compile (!) and succeed.
     168             :   CHECK_BOTH(EQ, TestClass1{}, TestClass1{});
     169             :   CHECK_BOTH(LT, TestClass2{2}, TestClass2{7});
     170             : 
     171             :   // Check that the values are output correctly on error.
     172           3 :   ASSERT_DEATH_IF_SUPPORTED(
     173             :       ([&] { CHECK_NE(TestClass1{}, TestClass1{}); })(),
     174             :       FailureMessage("Check failed: TestClass1{} != TestClass1{}",
     175             :                      "<unprintable> vs. <unprintable>"));
     176           4 :   ASSERT_DEATH_IF_SUPPORTED(
     177             :       ([&] { CHECK_LT(TestClass2{4}, TestClass2{3}); })(),
     178             :       FailureMessage("Check failed: TestClass2{4} < TestClass2{3}",
     179             :                      "TestClass2(4) vs. TestClass2(3)"));
     180             : }
     181             : 
     182       15373 : TEST(LoggingDeathTest, OutputEnumValues) {
     183           3 :   ASSERT_DEATH_IF_SUPPORTED(
     184             :       ([&] { CHECK_EQ(ONE, TWO); })(),
     185             :       FailureMessage("Check failed: ONE == TWO", "0 vs. 1"));
     186           4 :   ASSERT_DEATH_IF_SUPPORTED(
     187             :       ([&] { CHECK_NE(BAR, 2 + 3); })(),
     188             :       FailureMessage("Check failed: BAR != 2 + 3", "5 vs. 5"));
     189           4 :   ASSERT_DEATH_IF_SUPPORTED(
     190             :       ([&] { CHECK_EQ(TestEnum3::A, TestEnum3::B); })(),
     191             :       FailureMessage("Check failed: TestEnum3::A == TestEnum3::B", "0 vs. 1"));
     192           4 :   ASSERT_DEATH_IF_SUPPORTED(
     193             :       ([&] { CHECK_GE(TestEnum4::FIRST, TestEnum4::SECOND); })(),
     194             :       FailureMessage("Check failed: TestEnum4::FIRST >= TestEnum4::SECOND",
     195             :                      "0 vs. 1"));
     196             : }
     197             : 
     198             : enum TestEnum5 { TEST_A, TEST_B };
     199             : enum class TestEnum6 { TEST_C, TEST_D };
     200           0 : std::ostream& operator<<(std::ostream& str, TestEnum5 val) {
     201           0 :   return str << (val == TEST_A ? "A" : "B");
     202             : }
     203           0 : void operator<<(std::ostream& str, TestEnum6 val) {
     204           0 :   str << (val == TestEnum6::TEST_C ? "C" : "D");
     205           0 : }
     206             : 
     207       15373 : TEST(LoggingDeathTest, OutputEnumWithOutputOperator) {
     208           3 :   ASSERT_DEATH_IF_SUPPORTED(
     209             :       ([&] { CHECK_EQ(TEST_A, TEST_B); })(),
     210             :       FailureMessage("Check failed: TEST_A == TEST_B", "A vs. B"));
     211           4 :   ASSERT_DEATH_IF_SUPPORTED(
     212             :       ([&] { CHECK_GE(TestEnum6::TEST_C, TestEnum6::TEST_D); })(),
     213             :       FailureMessage("Check failed: TestEnum6::TEST_C >= TestEnum6::TEST_D",
     214             :                      "C vs. D"));
     215             : }
     216             : 
     217       15373 : TEST(LoggingDeathTest, FatalKills) {
     218           2 :   ASSERT_DEATH_IF_SUPPORTED(FATAL("Dread pirate"), "Dread pirate");
     219             : }
     220             : 
     221       15373 : TEST(LoggingDeathTest, DcheckIsOnlyFatalInDebug) {
     222             : #ifdef DEBUG
     223             :   ASSERT_DEATH_IF_SUPPORTED(DCHECK(false && "Dread pirate"), "Dread pirate");
     224             : #else
     225             :   // DCHECK should be non-fatal if DEBUG is undefined.
     226             :   DCHECK(false && "I'm a benign teapot");
     227             : #endif
     228           1 : }
     229             : 
     230             : namespace {
     231           0 : void DcheckOverrideFunction(const char*, int, const char*) {}
     232             : }  // namespace
     233             : 
     234       15373 : TEST(LoggingDeathTest, V8_DcheckCanBeOverridden) {
     235             :   // Default DCHECK state should be fatal.
     236           2 :   ASSERT_DEATH_IF_SUPPORTED(V8_Dcheck(__FILE__, __LINE__, "Dread pirate"),
     237             :                             "Dread pirate");
     238             : 
     239           3 :   ASSERT_DEATH_IF_SUPPORTED(
     240             :       {
     241             :         v8::base::SetDcheckFunction(&DcheckOverrideFunction);
     242             :         // This should be non-fatal.
     243             :         V8_Dcheck(__FILE__, __LINE__, "I'm a benign teapot.");
     244             : 
     245             :         // Restore default behavior, and assert on lethality.
     246             :         v8::base::SetDcheckFunction(nullptr);
     247             :         V8_Dcheck(__FILE__, __LINE__, "Dread pirate");
     248             :       },
     249             :       "Dread pirate");
     250             : }
     251             : 
     252             : #if defined(DEBUG)
     253             : namespace {
     254             : int g_log_sink_call_count = 0;
     255             : void DcheckCountFunction(const char* file, int line, const char* message) {
     256             :   ++g_log_sink_call_count;
     257             : }
     258             : 
     259             : void DcheckEmptyFunction1() {
     260             :   // Provide a body so that Release builds do not cause the compiler to
     261             :   // optimize DcheckEmptyFunction1 and DcheckEmptyFunction2 as a single
     262             :   // function, which breaks the Dcheck tests below.
     263             :   // Note that this function is never actually called.
     264             :   g_log_sink_call_count += 42;
     265             : }
     266             : void DcheckEmptyFunction2() {}
     267             : 
     268             : }  // namespace
     269             : 
     270             : TEST(LoggingTest, LogFunctionPointers) {
     271             :   v8::base::SetDcheckFunction(&DcheckCountFunction);
     272             :   g_log_sink_call_count = 0;
     273             :   void (*fp1)() = DcheckEmptyFunction1;
     274             :   void (*fp2)() = DcheckEmptyFunction2;
     275             :   void (*fp3)() = DcheckEmptyFunction1;
     276             :   DCHECK_EQ(fp1, DcheckEmptyFunction1);
     277             :   DCHECK_EQ(fp1, fp3);
     278             :   EXPECT_EQ(0, g_log_sink_call_count);
     279             :   DCHECK_EQ(fp1, fp2);
     280             :   EXPECT_EQ(1, g_log_sink_call_count);
     281             :   std::string* error_message =
     282             :       CheckEQImpl<decltype(fp1), decltype(fp2)>(fp1, fp2, "");
     283             :   EXPECT_NE(*error_message, "(1 vs 1)");
     284             :   delete error_message;
     285             : }
     286             : #endif  // defined(DEBUG)
     287             : 
     288             : }  // namespace logging_unittest
     289             : }  // namespace base
     290        9222 : }  // namespace v8

Generated by: LCOV version 1.10