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.
434 lines
10 KiB
434 lines
10 KiB
2 years ago
|
//
|
||
|
// 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
|