123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- // Copyright 2021 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 <cstdint>
- #include <string>
- #include "gmock/gmock.h"
- #include "gtest/gtest.h"
- #include "absl/base/config.h"
- #include "absl/base/internal/raw_logging.h"
- #include "absl/base/macros.h"
- #include "absl/strings/cord.h"
- #include "absl/strings/cord_test_helpers.h"
- #include "absl/strings/cordz_test_helpers.h"
- #include "absl/strings/internal/cordz_functions.h"
- #include "absl/strings/internal/cordz_info.h"
- #include "absl/strings/internal/cordz_sample_token.h"
- #include "absl/strings/internal/cordz_statistics.h"
- #include "absl/strings/internal/cordz_update_tracker.h"
- #include "absl/strings/str_cat.h"
- #include "absl/strings/string_view.h"
- #ifdef ABSL_INTERNAL_CORDZ_ENABLED
- using testing::Eq;
- using testing::AnyOf;
- namespace absl {
- ABSL_NAMESPACE_BEGIN
- using cord_internal::CordzInfo;
- using cord_internal::CordzSampleToken;
- using cord_internal::CordzStatistics;
- using cord_internal::CordzUpdateTracker;
- using Method = CordzUpdateTracker::MethodIdentifier;
- // Do not print cord contents, we only care about 'size' perhaps.
- // Note that this method must be inside the named namespace.
- inline void PrintTo(const Cord& cord, std::ostream* s) {
- if (s) *s << "Cord[" << cord.size() << "]";
- }
- namespace {
- auto constexpr kMaxInline = cord_internal::kMaxInline;
- // Returns a string_view value of the specified length
- // We do this to avoid 'consuming' large strings in Cord by default.
- absl::string_view MakeString(size_t size) {
- thread_local std::string str;
- str = std::string(size, '.');
- return str;
- }
- absl::string_view MakeString(TestCordSize size) {
- return MakeString(Length(size));
- }
- // Returns a cord with a sampled method of kAppendString.
- absl::Cord MakeAppendStringCord(TestCordSize size) {
- CordzSamplingIntervalHelper always(1);
- absl::Cord cord;
- cord.Append(MakeString(size));
- return cord;
- }
- std::string TestParamToString(::testing::TestParamInfo<TestCordSize> size) {
- return absl::StrCat("On", ToString(size.param), "Cord");
- }
- class CordzUpdateTest : public testing::TestWithParam<TestCordSize> {
- public:
- Cord& cord() { return cord_; }
- Method InitialOr(Method method) const {
- return (GetParam() > TestCordSize::kInlined) ? Method::kConstructorString
- : method;
- }
- private:
- CordzSamplingIntervalHelper sample_every_{1};
- Cord cord_{MakeString(GetParam())};
- };
- template <typename T>
- std::string ParamToString(::testing::TestParamInfo<T> param) {
- return std::string(ToString(param.param));
- }
- INSTANTIATE_TEST_SUITE_P(WithParam, CordzUpdateTest,
- testing::Values(TestCordSize::kEmpty,
- TestCordSize::kInlined,
- TestCordSize::kLarge),
- TestParamToString);
- class CordzStringTest : public testing::TestWithParam<TestCordSize> {
- private:
- CordzSamplingIntervalHelper sample_every_{1};
- };
- INSTANTIATE_TEST_SUITE_P(WithParam, CordzStringTest,
- testing::Values(TestCordSize::kInlined,
- TestCordSize::kStringSso1,
- TestCordSize::kStringSso2,
- TestCordSize::kSmall,
- TestCordSize::kLarge),
- ParamToString<TestCordSize>);
- TEST(CordzTest, ConstructSmallArray) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(MakeString(TestCordSize::kSmall));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- }
- TEST(CordzTest, ConstructLargeArray) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(MakeString(TestCordSize::kLarge));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- }
- TEST_P(CordzStringTest, ConstructString) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(std::string(Length(GetParam()), '.'));
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- }
- }
- TEST(CordzTest, CopyConstructFromUnsampled) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- Cord cord(src);
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- }
- TEST(CordzTest, CopyConstructFromSampled) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord(src);
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- }
- TEST(CordzTest, MoveConstruct) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src(MakeString(TestCordSize::kLarge));
- Cord cord(std::move(src));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- }
- TEST_P(CordzUpdateTest, AssignUnsampledCord) {
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- const CordzInfo* info = GetCordzInfoForTesting(cord());
- cord() = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
- }
- TEST_P(CordzUpdateTest, AssignSampledCord) {
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- cord() = src;
- ASSERT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord())->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
- }
- TEST(CordzUpdateTest, AssignSampledCordToInlined) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord cord;
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
- }
- TEST(CordzUpdateTest, AssignSampledCordToUnsampledCord) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord cord = UnsampledCord(MakeString(TestCordSize::kLarge));
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
- }
- TEST(CordzUpdateTest, AssignUnsampledCordToSampledCordWithoutSampling) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord cord = MakeAppendStringCord(TestCordSize::kLarge);
- const CordzInfo* info = GetCordzInfoForTesting(cord);
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
- }
- TEST(CordzUpdateTest, AssignUnsampledCordToSampledCordWithSampling) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord = MakeAppendStringCord(TestCordSize::kLarge);
- const CordzInfo* info = GetCordzInfoForTesting(cord);
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
- }
- TEST(CordzUpdateTest, AssignSampledCordToSampledCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord(MakeString(TestCordSize::kLarge));
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
- }
- TEST(CordzUpdateTest, AssignUnsampledCordToSampledCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord(MakeString(TestCordSize::kLarge));
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
- }
- TEST(CordzTest, AssignInlinedCordToSampledCord) {
- CordzSampleToken token;
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(MakeString(TestCordSize::kLarge));
- const CordzInfo* info = GetCordzInfoForTesting(cord);
- Cord src = UnsampledCord(MakeString(TestCordSize::kInlined));
- cord = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
- }
- TEST(CordzUpdateTest, MoveAssignCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord;
- Cord src(MakeString(TestCordSize::kLarge));
- cord = std::move(src);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- }
- TEST_P(CordzUpdateTest, AssignLargeArray) {
- cord() = MakeString(TestCordSize::kSmall);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignString));
- }
- TEST_P(CordzUpdateTest, AssignSmallArray) {
- cord() = MakeString(TestCordSize::kSmall);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignString));
- }
- TEST_P(CordzUpdateTest, AssignInlinedArray) {
- cord() = MakeString(TestCordSize::kInlined);
- EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));
- }
- TEST_P(CordzStringTest, AssignStringToInlined) {
- Cord cord;
- cord = std::string(Length(GetParam()), '.');
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAssignString));
- }
- }
- TEST_P(CordzStringTest, AssignStringToCord) {
- Cord cord(MakeString(TestCordSize::kLarge));
- cord = std::string(Length(GetParam()), '.');
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kAssignString, 1));
- }
- }
- TEST_P(CordzUpdateTest, AssignInlinedString) {
- cord() = std::string(Length(TestCordSize::kInlined), '.');
- EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));
- }
- TEST_P(CordzUpdateTest, AppendCord) {
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord().Append(src);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendCord)));
- }
- TEST_P(CordzUpdateTest, MoveAppendCord) {
- cord().Append(UnsampledCord(MakeString(TestCordSize::kLarge)));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendCord)));
- }
- TEST_P(CordzUpdateTest, AppendSmallArray) {
- cord().Append(MakeString(TestCordSize::kSmall));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendString)));
- }
- TEST_P(CordzUpdateTest, AppendLargeArray) {
- cord().Append(MakeString(TestCordSize::kLarge));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendString)));
- }
- TEST_P(CordzStringTest, AppendStringToEmpty) {
- Cord cord;
- cord.Append(std::string(Length(GetParam()), '.'));
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendString));
- }
- }
- TEST_P(CordzStringTest, AppendStringToInlined) {
- Cord cord(MakeString(TestCordSize::kInlined));
- cord.Append(std::string(Length(GetParam()), '.'));
- if (Length(TestCordSize::kInlined) + Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendString));
- }
- }
- TEST_P(CordzStringTest, AppendStringToCord) {
- Cord cord(MakeString(TestCordSize::kLarge));
- cord.Append(std::string(Length(GetParam()), '.'));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kAppendString, 1));
- }
- TEST(CordzTest, MakeCordFromExternal) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord = MakeCordFromExternal("Hello world", [](absl::string_view) {});
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kMakeCordFromExternal));
- }
- TEST(CordzTest, MakeCordFromEmptyExternal) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord = MakeCordFromExternal({}, [](absl::string_view) {});
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- }
- TEST_P(CordzUpdateTest, PrependCord) {
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord().Prepend(src);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependCord)));
- }
- TEST_P(CordzUpdateTest, PrependSmallArray) {
- cord().Prepend(MakeString(TestCordSize::kSmall));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependString)));
- }
- TEST_P(CordzUpdateTest, PrependLargeArray) {
- cord().Prepend(MakeString(TestCordSize::kLarge));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependString)));
- }
- TEST_P(CordzStringTest, PrependStringToEmpty) {
- Cord cord;
- cord.Prepend(std::string(Length(GetParam()), '.'));
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kPrependString));
- }
- }
- TEST_P(CordzStringTest, PrependStringToInlined) {
- Cord cord(MakeString(TestCordSize::kInlined));
- cord.Prepend(std::string(Length(GetParam()), '.'));
- if (Length(TestCordSize::kInlined) + Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kPrependString));
- }
- }
- TEST_P(CordzStringTest, PrependStringToCord) {
- Cord cord(MakeString(TestCordSize::kLarge));
- cord.Prepend(std::string(Length(GetParam()), '.'));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kPrependString, 1));
- }
- TEST(CordzTest, RemovePrefix) {
- CordzSamplingIntervalHelper sample_every(1);
- Cord cord(MakeString(TestCordSize::kLarge));
- // Half the cord
- cord.RemovePrefix(cord.size() / 2);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemovePrefix, 1));
- // TODO(mvels): RemovePrefix does not reset to inlined, except if empty?
- cord.RemovePrefix(cord.size() - kMaxInline);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemovePrefix, 2));
- cord.RemovePrefix(cord.size());
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- }
- TEST(CordzTest, RemoveSuffix) {
- CordzSamplingIntervalHelper sample_every(1);
- Cord cord(MakeString(TestCordSize::kLarge));
- // Half the cord
- cord.RemoveSuffix(cord.size() / 2);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemoveSuffix, 1));
- // TODO(mvels): RemoveSuffix does not reset to inlined, except if empty?
- cord.RemoveSuffix(cord.size() - kMaxInline);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemoveSuffix, 2));
- cord.RemoveSuffix(cord.size());
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- }
- TEST(CordzTest, SubCordFromUnsampledCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- Cord cord = src.Subcord(10, src.size() / 2);
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- }
- TEST(CordzTest, SubCordFromSampledCord) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord = src.Subcord(10, src.size() / 2);
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kSubCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- }
- TEST(CordzTest, SmallSubCord) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord = src.Subcord(10, kMaxInline + 1);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kSubCord));
- }
- } // namespace
- ABSL_NAMESPACE_END
- } // namespace absl
- #endif // ABSL_INTERNAL_CORDZ_ENABLED
|