Abseil Common Libraries (C++) (grcp 依赖)
https://abseil.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
10 KiB
433 lines
10 KiB
// |
|
// Copyright 2022 The Abseil Authors. |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// https://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
|
|
#include "absl/log/check.h" |
|
|
|
#include <ostream> |
|
#include <string> |
|
|
|
#include "gmock/gmock.h" |
|
#include "gtest/gtest.h" |
|
#include "absl/base/attributes.h" |
|
#include "absl/base/config.h" |
|
#include "absl/log/internal/test_helpers.h" |
|
|
|
namespace { |
|
using ::testing::AllOf; |
|
using ::testing::HasSubstr; |
|
using ::testing::Not; |
|
|
|
auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment( |
|
new absl::log_internal::LogTestEnvironment); |
|
|
|
#if GTEST_HAS_DEATH_TEST |
|
|
|
TEST(CHECKDeathTest, TestBasicValues) { |
|
CHECK(true); |
|
|
|
EXPECT_DEATH(CHECK(false), "Check failed: false"); |
|
|
|
int i = 2; |
|
CHECK(i != 3); // NOLINT |
|
} |
|
|
|
#endif // GTEST_HAS_DEATH_TEST |
|
|
|
TEST(CHECKTest, TestLogicExpressions) { |
|
int i = 5; |
|
CHECK(i > 0 && i < 10); |
|
CHECK(i < 0 || i > 3); |
|
} |
|
|
|
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L |
|
ABSL_CONST_INIT const auto global_var_check = [](int i) { |
|
CHECK(i > 0); // NOLINT |
|
return i + 1; |
|
}(3); |
|
|
|
ABSL_CONST_INIT const auto global_var = [](int i) { |
|
CHECK_GE(i, 0); // NOLINT |
|
return i + 1; |
|
}(global_var_check); |
|
#endif // ABSL_INTERNAL_CPLUSPLUS_LANG |
|
|
|
TEST(CHECKTest, TestPlacementsInCompoundStatements) { |
|
// check placement inside if/else clauses |
|
if (true) CHECK(true); |
|
|
|
if (false) |
|
; // NOLINT |
|
else |
|
CHECK(true); |
|
|
|
switch (0) |
|
case 0: |
|
CHECK(true); // NOLINT |
|
|
|
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L |
|
constexpr auto var = [](int i) { |
|
CHECK(i > 0); // NOLINT |
|
return i + 1; |
|
}(global_var); |
|
(void)var; |
|
#endif // ABSL_INTERNAL_CPLUSPLUS_LANG |
|
} |
|
|
|
TEST(CHECKTest, TestBoolConvertible) { |
|
struct Tester { |
|
} tester; |
|
CHECK([&]() { return &tester; }()); |
|
} |
|
|
|
#if GTEST_HAS_DEATH_TEST |
|
|
|
TEST(CHECKDeathTest, TestChecksWithSideeffects) { |
|
int var = 0; |
|
CHECK([&var]() { |
|
++var; |
|
return true; |
|
}()); |
|
EXPECT_EQ(var, 1); |
|
|
|
EXPECT_DEATH(CHECK([&var]() { |
|
++var; |
|
return false; |
|
}()) << var, |
|
"Check failed: .* 2"); |
|
} |
|
|
|
#endif // GTEST_HAS_DEATH_TEST |
|
|
|
#if GTEST_HAS_DEATH_TEST |
|
|
|
TEST(CHECKDeachTest, TestOrderOfInvocationsBetweenCheckAndMessage) { |
|
int counter = 0; |
|
|
|
auto GetStr = [&counter]() -> std::string { |
|
return counter++ == 0 ? "" : "non-empty"; |
|
}; |
|
|
|
EXPECT_DEATH(CHECK(!GetStr().empty()) << GetStr(), HasSubstr("non-empty")); |
|
} |
|
|
|
TEST(CHECKTest, TestSecondaryFailure) { |
|
auto FailingRoutine = []() { |
|
CHECK(false) << "Secondary"; |
|
return false; |
|
}; |
|
EXPECT_DEATH(CHECK(FailingRoutine()) << "Primary", |
|
AllOf(HasSubstr("Secondary"), Not(HasSubstr("Primary")))); |
|
} |
|
|
|
TEST(CHECKTest, TestSecondaryFailureInMessage) { |
|
auto MessageGen = []() { |
|
CHECK(false) << "Secondary"; |
|
return "Primary"; |
|
}; |
|
EXPECT_DEATH(CHECK(false) << MessageGen(), |
|
AllOf(HasSubstr("Secondary"), Not(HasSubstr("Primary")))); |
|
} |
|
|
|
#endif // GTEST_HAS_DEATH_TEST |
|
|
|
TEST(CHECKTest, TestBinaryChecksWithPrimitives) { |
|
CHECK_EQ(1, 1); |
|
CHECK_NE(1, 2); |
|
CHECK_GE(1, 1); |
|
CHECK_GE(2, 1); |
|
CHECK_LE(1, 1); |
|
CHECK_LE(1, 2); |
|
CHECK_GT(2, 1); |
|
CHECK_LT(1, 2); |
|
} |
|
|
|
// For testing using CHECK*() on anonymous enums. |
|
enum { CASE_A, CASE_B }; |
|
|
|
TEST(CHECKTest, TestBinaryChecksWithEnumValues) { |
|
// Tests using CHECK*() on anonymous enums. |
|
CHECK_EQ(CASE_A, CASE_A); |
|
CHECK_NE(CASE_A, CASE_B); |
|
CHECK_GE(CASE_A, CASE_A); |
|
CHECK_GE(CASE_B, CASE_A); |
|
CHECK_LE(CASE_A, CASE_A); |
|
CHECK_LE(CASE_A, CASE_B); |
|
CHECK_GT(CASE_B, CASE_A); |
|
CHECK_LT(CASE_A, CASE_B); |
|
} |
|
|
|
TEST(CHECKTest, TestBinaryChecksWithNullptr) { |
|
const void* p_null = nullptr; |
|
const void* p_not_null = &p_null; |
|
CHECK_EQ(p_null, nullptr); |
|
CHECK_EQ(nullptr, p_null); |
|
CHECK_NE(p_not_null, nullptr); |
|
CHECK_NE(nullptr, p_not_null); |
|
} |
|
|
|
#if GTEST_HAS_DEATH_TEST |
|
|
|
// Test logging of various char-typed values by failing CHECK*(). |
|
TEST(CHECKDeathTest, TestComparingCharsValues) { |
|
{ |
|
char a = ';'; |
|
char b = 'b'; |
|
EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(';' vs. 'b'\\)"); |
|
b = 1; |
|
EXPECT_DEATH(CHECK_EQ(a, b), |
|
"Check failed: a == b \\(';' vs. char value 1\\)"); |
|
} |
|
{ |
|
signed char a = ';'; |
|
signed char b = 'b'; |
|
EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(';' vs. 'b'\\)"); |
|
b = -128; |
|
EXPECT_DEATH(CHECK_EQ(a, b), |
|
"Check failed: a == b \\(';' vs. signed char value -128\\)"); |
|
} |
|
{ |
|
unsigned char a = ';'; |
|
unsigned char b = 'b'; |
|
EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(';' vs. 'b'\\)"); |
|
b = 128; |
|
EXPECT_DEATH(CHECK_EQ(a, b), |
|
"Check failed: a == b \\(';' vs. unsigned char value 128\\)"); |
|
} |
|
} |
|
|
|
TEST(CHECKDeathTest, TestNullValuesAreReportedCleanly) { |
|
const char* a = nullptr; |
|
const char* b = nullptr; |
|
EXPECT_DEATH(CHECK_NE(a, b), |
|
"Check failed: a != b \\(\\(null\\) vs. \\(null\\)\\)"); |
|
|
|
a = "xx"; |
|
EXPECT_DEATH(CHECK_EQ(a, b), "Check failed: a == b \\(xx vs. \\(null\\)\\)"); |
|
EXPECT_DEATH(CHECK_EQ(b, a), "Check failed: b == a \\(\\(null\\) vs. xx\\)"); |
|
|
|
std::nullptr_t n{}; |
|
EXPECT_DEATH(CHECK_NE(n, nullptr), |
|
"Check failed: n != nullptr \\(\\(null\\) vs. \\(null\\)\\)"); |
|
} |
|
|
|
#endif // GTEST_HAS_DEATH_TEST |
|
|
|
TEST(CHECKTest, TestSTREQ) { |
|
CHECK_STREQ("this", "this"); |
|
CHECK_STREQ(nullptr, nullptr); |
|
CHECK_STRCASEEQ("this", "tHiS"); |
|
CHECK_STRCASEEQ(nullptr, nullptr); |
|
CHECK_STRNE("this", "tHiS"); |
|
CHECK_STRNE("this", nullptr); |
|
CHECK_STRCASENE("this", "that"); |
|
CHECK_STRCASENE(nullptr, "that"); |
|
CHECK_STREQ((std::string("a") + "b").c_str(), "ab"); |
|
CHECK_STREQ(std::string("test").c_str(), |
|
(std::string("te") + std::string("st")).c_str()); |
|
} |
|
|
|
TEST(CHECKTest, TestComparisonPlacementsInCompoundStatements) { |
|
// check placement inside if/else clauses |
|
if (true) CHECK_EQ(1, 1); |
|
if (true) CHECK_STREQ("c", "c"); |
|
|
|
if (false) |
|
; // NOLINT |
|
else |
|
CHECK_LE(0, 1); |
|
|
|
if (false) |
|
; // NOLINT |
|
else |
|
CHECK_STRNE("a", "b"); |
|
|
|
switch (0) |
|
case 0: |
|
CHECK_NE(1, 0); |
|
|
|
switch (0) |
|
case 0: |
|
CHECK_STRCASEEQ("A", "a"); |
|
|
|
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L |
|
constexpr auto var = [](int i) { |
|
CHECK_GT(i, 0); |
|
return i + 1; |
|
}(global_var); |
|
(void)var; |
|
|
|
// CHECK_STR... checks are not supported in constexpr routines. |
|
// constexpr auto var2 = [](int i) { |
|
// CHECK_STRNE("c", "d"); |
|
// return i + 1; |
|
// }(global_var); |
|
|
|
#if defined(__GNUC__) |
|
int var3 = (({ CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0; |
|
(void)var3; |
|
|
|
int var4 = (({ CHECK_STREQ("a", "a"); }), global_var < 10) ? 1 : 0; |
|
(void)var4; |
|
#endif // __GNUC__ |
|
#endif // ABSL_INTERNAL_CPLUSPLUS_LANG |
|
} |
|
|
|
TEST(CHECKTest, TestDCHECK) { |
|
#ifdef NDEBUG |
|
DCHECK(1 == 2) << " DCHECK's shouldn't be compiled in normal mode"; |
|
#endif |
|
DCHECK(1 == 1); // NOLINT(readability/check) |
|
DCHECK_EQ(1, 1); |
|
DCHECK_NE(1, 2); |
|
DCHECK_GE(1, 1); |
|
DCHECK_GE(2, 1); |
|
DCHECK_LE(1, 1); |
|
DCHECK_LE(1, 2); |
|
DCHECK_GT(2, 1); |
|
DCHECK_LT(1, 2); |
|
|
|
// Test DCHECK on std::nullptr_t |
|
const void* p_null = nullptr; |
|
const void* p_not_null = &p_null; |
|
DCHECK_EQ(p_null, nullptr); |
|
DCHECK_EQ(nullptr, p_null); |
|
DCHECK_NE(p_not_null, nullptr); |
|
DCHECK_NE(nullptr, p_not_null); |
|
} |
|
|
|
TEST(CHECKTest, TestQCHECK) { |
|
// The tests that QCHECK does the same as CHECK |
|
QCHECK(1 == 1); // NOLINT(readability/check) |
|
QCHECK_EQ(1, 1); |
|
QCHECK_NE(1, 2); |
|
QCHECK_GE(1, 1); |
|
QCHECK_GE(2, 1); |
|
QCHECK_LE(1, 1); |
|
QCHECK_LE(1, 2); |
|
QCHECK_GT(2, 1); |
|
QCHECK_LT(1, 2); |
|
|
|
// Tests using QCHECK*() on anonymous enums. |
|
QCHECK_EQ(CASE_A, CASE_A); |
|
QCHECK_NE(CASE_A, CASE_B); |
|
QCHECK_GE(CASE_A, CASE_A); |
|
QCHECK_GE(CASE_B, CASE_A); |
|
QCHECK_LE(CASE_A, CASE_A); |
|
QCHECK_LE(CASE_A, CASE_B); |
|
QCHECK_GT(CASE_B, CASE_A); |
|
QCHECK_LT(CASE_A, CASE_B); |
|
} |
|
|
|
TEST(CHECKTest, TestQCHECKPlacementsInCompoundStatements) { |
|
// check placement inside if/else clauses |
|
if (true) QCHECK(true); |
|
|
|
if (false) |
|
; // NOLINT |
|
else |
|
QCHECK(true); |
|
|
|
if (false) |
|
; // NOLINT |
|
else |
|
QCHECK(true); |
|
|
|
switch (0) |
|
case 0: |
|
QCHECK(true); |
|
|
|
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L |
|
constexpr auto var = [](int i) { |
|
QCHECK(i > 0); // NOLINT |
|
return i + 1; |
|
}(global_var); |
|
(void)var; |
|
|
|
#if defined(__GNUC__) |
|
int var2 = (({ CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0; |
|
(void)var2; |
|
#endif // __GNUC__ |
|
#endif // ABSL_INTERNAL_CPLUSPLUS_LANG |
|
} |
|
|
|
class ComparableType { |
|
public: |
|
explicit ComparableType(int v) : v_(v) {} |
|
|
|
void MethodWithCheck(int i) { |
|
CHECK_EQ(*this, i); |
|
CHECK_EQ(i, *this); |
|
} |
|
|
|
int Get() const { return v_; } |
|
|
|
private: |
|
friend bool operator==(const ComparableType& lhs, const ComparableType& rhs) { |
|
return lhs.v_ == rhs.v_; |
|
} |
|
friend bool operator!=(const ComparableType& lhs, const ComparableType& rhs) { |
|
return lhs.v_ != rhs.v_; |
|
} |
|
friend bool operator<(const ComparableType& lhs, const ComparableType& rhs) { |
|
return lhs.v_ < rhs.v_; |
|
} |
|
friend bool operator<=(const ComparableType& lhs, const ComparableType& rhs) { |
|
return lhs.v_ <= rhs.v_; |
|
} |
|
friend bool operator>(const ComparableType& lhs, const ComparableType& rhs) { |
|
return lhs.v_ > rhs.v_; |
|
} |
|
friend bool operator>=(const ComparableType& lhs, const ComparableType& rhs) { |
|
return lhs.v_ >= rhs.v_; |
|
} |
|
friend bool operator==(const ComparableType& lhs, int rhs) { |
|
return lhs.v_ == rhs; |
|
} |
|
friend bool operator==(int lhs, const ComparableType& rhs) { |
|
return lhs == rhs.v_; |
|
} |
|
|
|
friend std::ostream& operator<<(std::ostream& out, const ComparableType& v) { |
|
return out << "ComparableType{" << v.Get() << "}"; |
|
} |
|
|
|
int v_; |
|
}; |
|
|
|
TEST(CHECKTest, TestUserDefinedCompOp) { |
|
CHECK_EQ(ComparableType{0}, ComparableType{0}); |
|
CHECK_NE(ComparableType{1}, ComparableType{2}); |
|
CHECK_LT(ComparableType{1}, ComparableType{2}); |
|
CHECK_LE(ComparableType{1}, ComparableType{2}); |
|
CHECK_GT(ComparableType{2}, ComparableType{1}); |
|
CHECK_GE(ComparableType{2}, ComparableType{2}); |
|
} |
|
|
|
TEST(CHECKTest, TestCheckInMethod) { |
|
ComparableType v{1}; |
|
v.MethodWithCheck(1); |
|
} |
|
|
|
TEST(CHECKDeathTest, TestUserDefinedStreaming) { |
|
ComparableType v1{1}; |
|
ComparableType v2{2}; |
|
|
|
EXPECT_DEATH( |
|
CHECK_EQ(v1, v2), |
|
HasSubstr( |
|
"Check failed: v1 == v2 (ComparableType{1} vs. ComparableType{2})")); |
|
} |
|
|
|
} // namespace
|
|
|