mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
255 lines
7.6 KiB
C++
255 lines
7.6 KiB
C++
// Copyright 2025 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/internal/container.h"
|
|
|
|
#include <cstdint>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <ostream>
|
|
#include <set>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "absl/base/config.h"
|
|
#include "absl/strings/str_format.h"
|
|
#include "absl/strings/str_join.h"
|
|
#include "absl/types/span.h"
|
|
|
|
namespace absl {
|
|
ABSL_NAMESPACE_BEGIN
|
|
namespace log_internal {
|
|
namespace {
|
|
|
|
class ContainerLoggingTest : public ::testing::Test {
|
|
protected:
|
|
ContainerLoggingTest() : stream_(new std::stringstream) {}
|
|
std::ostream& stream() { return *stream_; }
|
|
std::string logged() {
|
|
std::string r = stream_->str();
|
|
stream_ = std::make_unique<std::stringstream>();
|
|
return r;
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<std::stringstream> stream_;
|
|
};
|
|
|
|
TEST_F(ContainerLoggingTest, ShortRange) {
|
|
std::vector<std::string> words = {"hi", "hello"};
|
|
LogRangeToStream(stream(), words.begin(), words.end(), LogMultiline());
|
|
EXPECT_EQ("[\nhi\nhello\n]", logged());
|
|
}
|
|
|
|
TEST_F(ContainerLoggingTest, LegacyRange) {
|
|
std::vector<int> lengths = {1, 2};
|
|
LogRangeToStream(stream(), lengths.begin(), lengths.end(),
|
|
LogLegacyUpTo100());
|
|
EXPECT_EQ("1 2", logged());
|
|
}
|
|
|
|
TEST_F(ContainerLoggingTest, ToString) {
|
|
std::vector<int> lengths = {1, 2, 3, 4, 5};
|
|
EXPECT_EQ(LogContainer(lengths).str(), "[1, 2, 3, 4, 5]");
|
|
}
|
|
|
|
class UserDefFriend {
|
|
public:
|
|
explicit UserDefFriend(int i) : i_(i) {}
|
|
|
|
private:
|
|
friend std::ostream& operator<<(std::ostream& str, const UserDefFriend& i) {
|
|
return str << i.i_;
|
|
}
|
|
int i_;
|
|
};
|
|
|
|
TEST_F(ContainerLoggingTest, RangeOfUserDefined) {
|
|
std::vector<UserDefFriend> ints = {UserDefFriend(1), UserDefFriend(2),
|
|
UserDefFriend(3)};
|
|
LogRangeToStream(stream(), ints.begin(), ints.begin() + 1, LogDefault());
|
|
LogRangeToStream(stream(), ints.begin() + 1, ints.begin() + 2,
|
|
LogMultiline());
|
|
LogRangeToStream(stream(), ints.begin() + 2, ints.begin() + 3, LogDefault());
|
|
LogRangeToStream(stream(), ints.begin(), ints.begin(), LogMultiline());
|
|
|
|
EXPECT_EQ("[1][\n2\n][3][\n]", logged());
|
|
}
|
|
|
|
TEST_F(ContainerLoggingTest, FullContainer) {
|
|
std::vector<int> ints;
|
|
std::vector<int> ints100;
|
|
std::vector<int> ints123;
|
|
int64_t max_elements = 123;
|
|
std::string expected1;
|
|
std::string expected2;
|
|
std::string expected3;
|
|
std::string expected4;
|
|
std::string expected5;
|
|
std::string expected6;
|
|
std::string expected7;
|
|
std::string expected8;
|
|
std::string expected9;
|
|
for (int i = 0; i < 1000; ++i) {
|
|
ints.push_back(i);
|
|
if (i < 100) {
|
|
ints100.push_back(i);
|
|
}
|
|
if (i < max_elements) {
|
|
ints123.push_back(i);
|
|
}
|
|
}
|
|
expected1 = "[\n" + absl::StrJoin(ints, "\n") + "\n]";
|
|
expected2 = "[" + absl::StrJoin(ints, ", ") + "]";
|
|
expected3 = "[\n" + absl::StrJoin(ints100, "\n") + "\n...\n]";
|
|
expected4 = "[" + absl::StrJoin(ints100, ", ") + ", ...]";
|
|
expected5 = absl::StrJoin(ints100, " ") + " ...";
|
|
expected6 = "[\n" + absl::StrJoin(ints, "\n") + "\n]";
|
|
expected7 = "[\n" + absl::StrJoin(ints123, "\n") + "\n...\n]";
|
|
expected8 = "[" + absl::StrJoin(ints, ", ") + "]";
|
|
expected9 = "[" + absl::StrJoin(ints123, ", ") + ", ...]";
|
|
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(), LogMultiline());
|
|
EXPECT_EQ(expected1, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(), LogShort());
|
|
EXPECT_EQ(expected2, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(), LogMultilineUpTo100());
|
|
EXPECT_EQ(expected3, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(), LogShortUpTo100());
|
|
EXPECT_EQ(expected4, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(), LogLegacyUpTo100());
|
|
EXPECT_EQ(expected5, logged());
|
|
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(),
|
|
LogMultilineUpToN(ints.size()));
|
|
EXPECT_EQ(expected6, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(),
|
|
LogMultilineUpToN(max_elements));
|
|
EXPECT_EQ(expected7, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(),
|
|
LogShortUpToN(ints.size()));
|
|
EXPECT_EQ(expected8, logged());
|
|
LogRangeToStream(stream(), ints.begin(), ints.end(),
|
|
LogShortUpToN(max_elements));
|
|
EXPECT_EQ(expected9, logged());
|
|
}
|
|
|
|
TEST_F(ContainerLoggingTest, LogContainer) {
|
|
std::set<int> ints = {1, 2, 3};
|
|
stream() << LogContainer(ints, LogMultiline());
|
|
EXPECT_EQ("[\n1\n2\n3\n]", logged());
|
|
|
|
stream() << LogContainer(ints);
|
|
EXPECT_EQ("[1, 2, 3]", logged());
|
|
|
|
stream() << LogContainer(std::vector<int>(ints.begin(), ints.end()),
|
|
LogLegacyUpTo100());
|
|
EXPECT_EQ("1 2 3", logged());
|
|
}
|
|
|
|
TEST_F(ContainerLoggingTest, LogMutableSpan) {
|
|
std::vector<int> ints = {1, 2, 3};
|
|
absl::Span<int> int_span(ints);
|
|
stream() << LogContainer(int_span);
|
|
EXPECT_EQ("[1, 2, 3]", logged());
|
|
}
|
|
|
|
TEST_F(ContainerLoggingTest, LogRange) {
|
|
std::set<int> ints = {1, 2, 3};
|
|
stream() << LogRange(ints.begin(), ints.end(), LogMultiline());
|
|
EXPECT_EQ("[\n1\n2\n3\n]", logged());
|
|
|
|
stream() << LogRange(ints.begin(), ints.end());
|
|
EXPECT_EQ("[1, 2, 3]", logged());
|
|
}
|
|
|
|
// Some class with a custom Stringify
|
|
class C {
|
|
public:
|
|
explicit C(int x) : x_(x) {}
|
|
|
|
private:
|
|
// This is intentionally made private for the purposes of the test;
|
|
//` AbslStringify` isn't meant to be called directly, and instead invoked
|
|
// via `StrCat` and friends.
|
|
template <typename Sink>
|
|
friend void AbslStringify(Sink& sink, const C& p) {
|
|
absl::Format(&sink, "C(%d)", p.x_);
|
|
}
|
|
|
|
int x_;
|
|
};
|
|
|
|
TEST_F(ContainerLoggingTest, LogContainerWithCustomStringify) {
|
|
std::vector<C> c = {C(1), C(2), C(3)};
|
|
stream() << LogContainer(c);
|
|
EXPECT_EQ("[C(1), C(2), C(3)]", logged());
|
|
}
|
|
|
|
class LogEnumTest : public ContainerLoggingTest {
|
|
protected:
|
|
enum Unscoped { kUnscoped0, kUnscoped1, kUnscoped2 };
|
|
|
|
enum StreamableUnscoped {
|
|
kStreamableUnscoped0,
|
|
kStreamableUnscoped1,
|
|
kStreamableUnscoped2
|
|
};
|
|
|
|
enum class Scoped { k0, k1, k2 };
|
|
|
|
enum class StreamableScoped { k0, k1, k2 };
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, StreamableUnscoped v) {
|
|
return os << LogEnum(v);
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, StreamableScoped v) {
|
|
return os << LogEnum(v);
|
|
}
|
|
};
|
|
|
|
TEST_F(LogEnumTest, Unscoped) {
|
|
stream() << LogEnum(kUnscoped0) << "," << LogEnum(kUnscoped1) << ","
|
|
<< LogEnum(kUnscoped2);
|
|
EXPECT_EQ("0,1,2", logged());
|
|
}
|
|
|
|
TEST_F(LogEnumTest, StreamableUnscoped) {
|
|
stream() << kStreamableUnscoped0 << "," << kStreamableUnscoped1 << ","
|
|
<< kStreamableUnscoped2;
|
|
EXPECT_EQ("0,1,2", logged());
|
|
}
|
|
|
|
TEST_F(LogEnumTest, Scoped) {
|
|
stream() << LogEnum(Scoped::k0) << "," << LogEnum(Scoped::k1) << ","
|
|
<< LogEnum(Scoped::k2);
|
|
EXPECT_EQ("0,1,2", logged());
|
|
}
|
|
|
|
TEST_F(LogEnumTest, StreamableScoped) {
|
|
// Test using LogEnum to implement an operator<<.
|
|
stream() << StreamableScoped::k0 << "," << StreamableScoped::k1 << ","
|
|
<< StreamableScoped::k2;
|
|
EXPECT_EQ("0,1,2", logged());
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace log_internal
|
|
ABSL_NAMESPACE_END
|
|
} // namespace absl
|