Commit 73316fc3 by Abseil Team Committed by Andy Getz

Export of internal Abseil changes

--
262f6992ee0553782531ad58dd7d8bcd6d0b7bb7 by Martijn Vels <mvels@google.com>:

Remove CordRepConcat uses in tests and CONCAT constants.

This change removes the creation and uses of CordRepConcat in unit tests, and replaces some remaining CONCAT constants with IsConcat() to make subsequent teardown of CordrepConcat uses easier.

PiperOrigin-RevId: 426932694

--
fd590f7e849ba8c5395c589ed3f762cd00affdc8 by Abseil Team <absl-team@google.com>:

Replace NULL and 0 with nullptr.

PiperOrigin-RevId: 426912932

--
183e5babc478748023f732a1608745a2a544c996 by Abseil Team <absl-team@google.com>:

Replace "span of time" with "amount of time" in the first comment line, to make it clearer that we're not talking about a duration that starts at a specific time.

PiperOrigin-RevId: 426691794

--
e28ca760f21505f1be55c7af336eb61d2f1b7fea by Martijn Vels <mvels@google.com>:

Add extra assertions on CordRepSubstring child nodes

PiperOrigin-RevId: 426369104
GitOrigin-RevId: 262f6992ee0553782531ad58dd7d8bcd6d0b7bb7
Change-Id: I7ffdaa2dc999a2117944c9abdb1565b6b6f48b59
parent 36db0e4b
...@@ -86,7 +86,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) { ...@@ -86,7 +86,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
AllocMap::iterator it; AllocMap::iterator it;
BlockDesc block_desc; BlockDesc block_desc;
int rnd; int rnd;
LowLevelAlloc::Arena *arena = 0; LowLevelAlloc::Arena *arena = nullptr;
if (use_new_arena) { if (use_new_arena) {
int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0; int32_t flags = call_malloc_hook ? LowLevelAlloc::kCallMallocHook : 0;
arena = LowLevelAlloc::NewArena(flags); arena = LowLevelAlloc::NewArena(flags);
...@@ -101,11 +101,10 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) { ...@@ -101,11 +101,10 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
case 0: // coin came up heads: add a block case 0: // coin came up heads: add a block
using_low_level_alloc = true; using_low_level_alloc = true;
block_desc.len = rand() & 0x3fff; block_desc.len = rand() & 0x3fff;
block_desc.ptr = block_desc.ptr = reinterpret_cast<char *>(
reinterpret_cast<char *>( arena == nullptr
arena == 0 ? LowLevelAlloc::Alloc(block_desc.len)
? LowLevelAlloc::Alloc(block_desc.len) : LowLevelAlloc::AllocWithArena(block_desc.len, arena));
: LowLevelAlloc::AllocWithArena(block_desc.len, arena));
using_low_level_alloc = false; using_low_level_alloc = false;
RandomizeBlockDesc(&block_desc); RandomizeBlockDesc(&block_desc);
rnd = rand(); rnd = rand();
......
...@@ -309,20 +309,6 @@ cc_library( ...@@ -309,20 +309,6 @@ cc_library(
) )
cc_test( cc_test(
name = "cord_rep_concat_test",
size = "small",
srcs = ["internal/cord_rep_concat_test.cc"],
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
":cord_internal",
":cord_rep_test_util",
"//absl/base:config",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "cord_rep_btree_test", name = "cord_rep_btree_test",
size = "medium", size = "medium",
srcs = ["internal/cord_rep_btree_test.cc"], srcs = ["internal/cord_rep_btree_test.cc"],
...@@ -759,22 +745,6 @@ cc_test( ...@@ -759,22 +745,6 @@ cc_test(
) )
cc_test( cc_test(
name = "cord_rep_consume_test",
size = "medium",
srcs = ["internal/cord_rep_consume_test.cc"],
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
":cord_internal",
":strings",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/debugging:leak_check",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "cord_ring_test", name = "cord_ring_test",
size = "medium", size = "medium",
srcs = ["cord_ring_test.cc"], srcs = ["cord_ring_test.cc"],
......
...@@ -935,40 +935,6 @@ absl_cc_test( ...@@ -935,40 +935,6 @@ absl_cc_test(
absl_cc_test( absl_cc_test(
NAME NAME
cord_rep_consume_test
SRCS
"internal/cord_rep_consume_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::base
absl::config
absl::cord_internal
absl::core_headers
absl::function_ref
absl::raw_logging_internal
absl::strings
GTest::gmock_main
)
absl_cc_test(
NAME
cord_rep_concat_test
SRCS
"internal/cord_rep_concat_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::base
absl::config
absl::cord_internal
absl::cord_rep_test_util
absl::core_headers
GTest::gmock_main
)
absl_cc_test(
NAME
cord_rep_btree_test cord_rep_btree_test
SRCS SRCS
"internal/cord_rep_btree_test.cc" "internal/cord_rep_btree_test.cc"
......
...@@ -211,7 +211,7 @@ size_t GetEstimatedUsage(const CordRep* rep) { ...@@ -211,7 +211,7 @@ size_t GetEstimatedUsage(const CordRep* rep) {
AnalyzeDataEdge(repref, raw_usage); AnalyzeDataEdge(repref, raw_usage);
} else if (repref.rep->tag == BTREE) { } else if (repref.rep->tag == BTREE) {
AnalyzeBtree(repref, raw_usage); AnalyzeBtree(repref, raw_usage);
} else if (repref.rep->tag == CONCAT) { } else if (repref.rep->IsConcat()) {
AnalyzeConcat(repref, raw_usage); AnalyzeConcat(repref, raw_usage);
} else if (repref.rep->tag == RING) { } else if (repref.rep->tag == RING) {
AnalyzeRing(repref, raw_usage); AnalyzeRing(repref, raw_usage);
......
...@@ -44,7 +44,6 @@ using ::absl::cord_internal::CordRepFlat; ...@@ -44,7 +44,6 @@ using ::absl::cord_internal::CordRepFlat;
using ::absl::cord_internal::CordRepRing; using ::absl::cord_internal::CordRepRing;
using ::absl::cord_internal::CordRepSubstring; using ::absl::cord_internal::CordRepSubstring;
using ::absl::cord_internal::CONCAT;
using ::absl::cord_internal::EXTERNAL; using ::absl::cord_internal::EXTERNAL;
using ::absl::cord_internal::SUBSTRING; using ::absl::cord_internal::SUBSTRING;
...@@ -262,16 +261,6 @@ CordRepSubstring* RemoveSuffix(size_t length, CordRep* rep) { ...@@ -262,16 +261,6 @@ CordRepSubstring* RemoveSuffix(size_t length, CordRep* rep) {
return MakeSubstring(0, rep->length - length, rep); return MakeSubstring(0, rep->length - length, rep);
} }
CordRepConcat* MakeConcat(CordRep* left, CordRep* right, int depth = 0) {
auto* concat = new CordRepConcat;
concat->tag = CONCAT;
concat->length = left->length + right->length;
concat->left = left;
concat->right = right;
concat->set_depth(depth);
return concat;
}
enum Composition { kMix, kAppend, kPrepend }; enum Composition { kMix, kAppend, kPrepend };
Composition RandomComposition() { Composition RandomComposition() {
...@@ -296,7 +285,6 @@ constexpr const char* kFox = "The quick brown fox jumps over the lazy dog"; ...@@ -296,7 +285,6 @@ constexpr const char* kFox = "The quick brown fox jumps over the lazy dog";
constexpr const char* kFoxFlats[] = {"The ", "quick ", "brown ", constexpr const char* kFoxFlats[] = {"The ", "quick ", "brown ",
"fox ", "jumps ", "over ", "fox ", "jumps ", "over ",
"the ", "lazy ", "dog"}; "the ", "lazy ", "dog"};
constexpr const char* kAlphabet = "abcdefghijklmnopqrstuvwxyz";
CordRepRing* FromFlats(Span<const char* const> flats, CordRepRing* FromFlats(Span<const char* const> flats,
Composition composition = kAppend) { Composition composition = kAppend) {
...@@ -594,35 +582,6 @@ TEST_P(CordRingCreateFromTreeTest, CreateFromSubstringOfLargeExternal) { ...@@ -594,35 +582,6 @@ TEST_P(CordRingCreateFromTreeTest, CreateFromSubstringOfLargeExternal) {
EXPECT_THAT(ToRawFlats(result), ElementsAre(str)); EXPECT_THAT(ToRawFlats(result), ElementsAre(str));
} }
TEST_P(CordRingBuildInputTest, CreateFromConcat) {
CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
auto* left = MakeConcat(RefIfInputSharedIndirect(flats[0]), flats[1]);
auto* right = MakeConcat(flats[2], RefIfInputSharedIndirect(flats[3]));
auto* concat = RefIfInputShared(MakeConcat(left, right));
CordRepRing* result = NeedsUnref(CordRepRing::Create(concat));
ASSERT_THAT(result, IsValidRingBuffer());
EXPECT_THAT(result->length, Eq(26));
EXPECT_THAT(ToString(result), Eq(kAlphabet));
}
TEST_P(CordRingBuildInputTest, CreateFromSubstringConcat) {
for (size_t off = 0; off < 26; ++off) {
for (size_t len = 1; len < 26 - off; ++len) {
CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
auto* left = MakeConcat(RefIfInputSharedIndirect(flats[0]), flats[1]);
auto* right = MakeConcat(flats[2], RefIfInputSharedIndirect(flats[3]));
auto* concat = MakeConcat(left, right);
auto* child = RefIfInputShared(MakeSubstring(off, len, concat));
CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
ASSERT_THAT(result, IsValidRingBuffer());
ASSERT_THAT(result->length, Eq(len));
ASSERT_THAT(ToString(result), string_view(kAlphabet).substr(off, len));
}
}
}
TEST_P(CordRingCreateTest, Properties) { TEST_P(CordRingCreateTest, Properties) {
absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz"; absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
CordRepRing* result = NeedsUnref(CordRepRing::Create(MakeFlat(str1), 120)); CordRepRing* result = NeedsUnref(CordRepRing::Create(MakeFlat(str1), 120));
......
...@@ -39,7 +39,7 @@ void CordRep::Destroy(CordRep* rep) { ...@@ -39,7 +39,7 @@ void CordRep::Destroy(CordRep* rep) {
absl::InlinedVector<CordRep*, Constants::kInlinedVectorSize> pending; absl::InlinedVector<CordRep*, Constants::kInlinedVectorSize> pending;
while (true) { while (true) {
assert(!rep->refcount.IsImmortal()); assert(!rep->refcount.IsImmortal());
if (rep->tag == CONCAT) { if (rep->IsConcat()) {
CordRepConcat* rep_concat = rep->concat(); CordRepConcat* rep_concat = rep->concat();
CordRep* right = rep_concat->right; CordRep* right = rep_concat->right;
if (!right->refcount.Decrement()) { if (!right->refcount.Decrement()) {
......
...@@ -119,6 +119,7 @@ CordRepSubstring* CreateSubstring(CordRep* rep, size_t offset, size_t n) { ...@@ -119,6 +119,7 @@ CordRepSubstring* CreateSubstring(CordRep* rep, size_t offset, size_t n) {
rep = CordRep::Ref(substring->child); rep = CordRep::Ref(substring->child);
CordRep::Unref(substring); CordRep::Unref(substring);
} }
assert(rep->IsExternal() || rep->IsFlat());
CordRepSubstring* substring = new CordRepSubstring(); CordRepSubstring* substring = new CordRepSubstring();
substring->length = n; substring->length = n;
substring->tag = SUBSTRING; substring->tag = SUBSTRING;
......
...@@ -49,6 +49,7 @@ inline CordRep* Substring(CordRep* rep, size_t offset, size_t n) { ...@@ -49,6 +49,7 @@ inline CordRep* Substring(CordRep* rep, size_t offset, size_t n) {
rep = rep->substring()->child; rep = rep->substring()->child;
} }
assert(rep->IsExternal() || rep->IsFlat());
CordRepSubstring* substring = new CordRepSubstring(); CordRepSubstring* substring = new CordRepSubstring();
substring->length = n; substring->length = n;
substring->tag = SUBSTRING; substring->tag = SUBSTRING;
......
...@@ -52,7 +52,6 @@ using ::absl::cordrep_testing::CordToString; ...@@ -52,7 +52,6 @@ using ::absl::cordrep_testing::CordToString;
using ::absl::cordrep_testing::CordVisitReps; using ::absl::cordrep_testing::CordVisitReps;
using ::absl::cordrep_testing::CreateFlatsFromString; using ::absl::cordrep_testing::CreateFlatsFromString;
using ::absl::cordrep_testing::CreateRandomString; using ::absl::cordrep_testing::CreateRandomString;
using ::absl::cordrep_testing::MakeConcat;
using ::absl::cordrep_testing::MakeExternal; using ::absl::cordrep_testing::MakeExternal;
using ::absl::cordrep_testing::MakeFlat; using ::absl::cordrep_testing::MakeFlat;
using ::absl::cordrep_testing::MakeSubstring; using ::absl::cordrep_testing::MakeSubstring;
...@@ -322,7 +321,6 @@ TEST(CordRepBtreeTest, EdgeData) { ...@@ -322,7 +321,6 @@ TEST(CordRepBtreeTest, EdgeData) {
CordRepExternal* external = MakeExternal("Hello external"); CordRepExternal* external = MakeExternal("Hello external");
CordRep* substr1 = MakeSubstring(1, 6, CordRep::Ref(flat)); CordRep* substr1 = MakeSubstring(1, 6, CordRep::Ref(flat));
CordRep* substr2 = MakeSubstring(1, 6, CordRep::Ref(external)); CordRep* substr2 = MakeSubstring(1, 6, CordRep::Ref(external));
CordRep* concat = MakeConcat(CordRep::Ref(flat), CordRep::Ref(external));
CordRep* bad_substr = MakeSubstring(1, 2, CordRep::Ref(substr1)); CordRep* bad_substr = MakeSubstring(1, 2, CordRep::Ref(substr1));
EXPECT_TRUE(CordRepBtree::IsDataEdge(flat)); EXPECT_TRUE(CordRepBtree::IsDataEdge(flat));
...@@ -345,17 +343,13 @@ TEST(CordRepBtreeTest, EdgeData) { ...@@ -345,17 +343,13 @@ TEST(CordRepBtreeTest, EdgeData) {
TypedEq<const void*>(external->base + 1)); TypedEq<const void*>(external->base + 1));
EXPECT_THAT(CordRepBtree::EdgeData(substr2), Eq("ello e")); EXPECT_THAT(CordRepBtree::EdgeData(substr2), Eq("ello e"));
EXPECT_FALSE(CordRepBtree::IsDataEdge(concat));
EXPECT_FALSE(CordRepBtree::IsDataEdge(bad_substr)); EXPECT_FALSE(CordRepBtree::IsDataEdge(bad_substr));
#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
EXPECT_DEATH(CordRepBtree::EdgeData(concat), ".*");
EXPECT_DEATH(CordRepBtree::EdgeDataPtr(concat), ".*");
EXPECT_DEATH(CordRepBtree::EdgeData(bad_substr), ".*"); EXPECT_DEATH(CordRepBtree::EdgeData(bad_substr), ".*");
EXPECT_DEATH(CordRepBtree::EdgeDataPtr(bad_substr), ".*"); EXPECT_DEATH(CordRepBtree::EdgeDataPtr(bad_substr), ".*");
#endif #endif
CordRep::Unref(bad_substr); CordRep::Unref(bad_substr);
CordRep::Unref(concat);
CordRep::Unref(substr2); CordRep::Unref(substr2);
CordRep::Unref(substr1); CordRep::Unref(substr1);
CordRep::Unref(external); CordRep::Unref(external);
...@@ -1006,50 +1000,6 @@ TEST_P(CordRepBtreeTest, AddLargeDataToLeaf) { ...@@ -1006,50 +1000,6 @@ TEST_P(CordRepBtreeTest, AddLargeDataToLeaf) {
} }
} }
TEST_P(CordRepBtreeDualTest, CreateFromConcat) {
AutoUnref refs;
CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
auto* left = MakeConcat(flats[0], flats[1]);
auto* right = MakeConcat(flats[2], refs.RefIf(first_shared(), flats[3]));
auto* concat = refs.RefIf(second_shared(), MakeConcat(left, right));
CordRepBtree* result = CordRepBtree::Create(concat);
ASSERT_TRUE(CordRepBtree::IsValid(result));
EXPECT_THAT(result->length, Eq(26));
EXPECT_THAT(CordToString(result), Eq("abcdefghijklmnopqrstuvwxyz"));
CordRep::Unref(result);
}
TEST_P(CordRepBtreeDualTest, AppendConcat) {
AutoUnref refs;
CordRep* flats[] = {MakeFlat("defgh"), MakeFlat("ijklm"),
MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
auto* left = MakeConcat(flats[0], flats[1]);
auto* right = MakeConcat(flats[2], refs.RefIf(first_shared(), flats[3]));
auto* concat = refs.RefIf(second_shared(), MakeConcat(left, right));
CordRepBtree* result = CordRepBtree::Create(MakeFlat("abc"));
result = CordRepBtree::Append(result, concat);
ASSERT_TRUE(CordRepBtree::IsValid(result));
EXPECT_THAT(result->length, Eq(26));
EXPECT_THAT(CordToString(result), Eq("abcdefghijklmnopqrstuvwxyz"));
CordRep::Unref(result);
}
TEST_P(CordRepBtreeDualTest, PrependConcat) {
AutoUnref refs;
CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
MakeFlat("nopqrstuv"), MakeFlat("wx")};
auto* left = MakeConcat(flats[0], flats[1]);
auto* right = MakeConcat(flats[2], refs.RefIf(first_shared(), flats[3]));
auto* concat = refs.RefIf(second_shared(), MakeConcat(left, right));
CordRepBtree* result = CordRepBtree::Create(MakeFlat("yz"));
result = CordRepBtree::Prepend(result, concat);
ASSERT_TRUE(CordRepBtree::IsValid(result));
EXPECT_THAT(result->length, Eq(26));
EXPECT_THAT(CordToString(result), Eq("abcdefghijklmnopqrstuvwxyz"));
CordRep::Unref(result);
}
TEST_P(CordRepBtreeTest, CreateFromTreeReturnsTree) { TEST_P(CordRepBtreeTest, CreateFromTreeReturnsTree) {
AutoUnref refs; AutoUnref refs;
CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("Hello world")); CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("Hello world"));
......
// 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 <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/config.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_test_util.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
namespace {
using ::absl::cordrep_testing::MakeFlat;
using ::absl::cordrep_testing::MakeSubstring;
using ::testing::Eq;
MATCHER_P2(EqExtractResult, tree, rep, "Equals ExtractResult") {
if (arg.tree != tree || arg.extracted != rep) {
*result_listener << "Expected {" << static_cast<const void*>(tree) << ", "
<< static_cast<const void*>(rep) << "}, got {" << arg.tree
<< ", " << arg.extracted << "}";
return false;
}
return true;
}
CordRepConcat* MakeConcat(CordRep* left, CordRep* right, int depth) {
CordRepConcat* concat = new CordRepConcat;
concat->tag = CONCAT;
concat->set_depth(depth);
concat->length = left->length + right->length;
concat->left = left;
concat->right = right;
return concat;
}
CordRepConcat::ExtractResult ExtractLast(CordRepConcat* concat,
size_t extra_capacity = 1) {
return CordRepConcat::ExtractAppendBuffer(concat, extra_capacity);
}
TEST(CordRepConcatTest, ExtractAppendBufferTwoFlats) {
CordRepFlat* flat1 = MakeFlat("abc");
CordRepFlat* flat2 = MakeFlat("defg");
CordRepConcat* concat = MakeConcat(flat1, flat2, 0);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(flat1, flat2));
CordRep::Unref(flat1);
CordRep::Unref(flat2);
}
TEST(CordRepConcatTest, ExtractAppendBufferThreeFlatsOne) {
CordRepFlat* flat1 = MakeFlat("abc");
CordRepFlat* flat2 = MakeFlat("defg");
CordRepFlat* flat3 = MakeFlat("hijkl");
CordRepConcat* lconcat = MakeConcat(flat1, flat2, 0);
CordRepConcat* concat = MakeConcat(lconcat, flat3, 1);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(lconcat, flat3));
ASSERT_THAT(lconcat->length, Eq(7));
CordRep::Unref(lconcat);
CordRep::Unref(flat3);
}
TEST(CordRepConcatTest, ExtractAppendBufferThreeFlatsTwo) {
CordRepFlat* flat1 = MakeFlat("hijkl");
CordRepFlat* flat2 = MakeFlat("abc");
CordRepFlat* flat3 = MakeFlat("defg");
CordRepConcat* rconcat = MakeConcat(flat2, flat3, 0);
CordRepConcat* concat = MakeConcat(flat1, rconcat, 1);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(concat, flat3));
ASSERT_THAT(concat->length, Eq(8));
CordRep::Unref(concat);
CordRep::Unref(flat3);
}
TEST(CordRepConcatTest, ExtractAppendBufferShared) {
CordRepFlat* flat1 = MakeFlat("hijkl");
CordRepFlat* flat2 = MakeFlat("abc");
CordRepFlat* flat3 = MakeFlat("defg");
CordRepConcat* rconcat = MakeConcat(flat2, flat3, 0);
CordRepConcat* concat = MakeConcat(flat1, rconcat, 1);
CordRep::Ref(concat);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(concat, nullptr));
CordRep::Unref(concat);
CordRep::Ref(rconcat);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(concat, nullptr));
CordRep::Unref(rconcat);
CordRep::Ref(flat3);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(concat, nullptr));
CordRep::Unref(flat3);
CordRep::Unref(concat);
}
TEST(CordRepConcatTest, ExtractAppendBufferNotFlat) {
CordRepFlat* flat1 = MakeFlat("hijkl");
CordRepFlat* flat2 = MakeFlat("abc");
CordRepFlat* flat3 = MakeFlat("defg");
auto substr = MakeSubstring(1, 2, flat3);
CordRepConcat* rconcat = MakeConcat(flat2, substr, 0);
CordRepConcat* concat = MakeConcat(flat1, rconcat, 1);
EXPECT_THAT(ExtractLast(concat), EqExtractResult(concat, nullptr));
CordRep::Unref(concat);
}
TEST(CordRepConcatTest, ExtractAppendBufferNoCapacity) {
CordRepFlat* flat1 = MakeFlat("hijkl");
CordRepFlat* flat2 = MakeFlat("abc");
CordRepFlat* flat3 = MakeFlat("defg");
size_t avail = flat3->Capacity() - flat3->length;
CordRepConcat* rconcat = MakeConcat(flat2, flat3, 0);
CordRepConcat* concat = MakeConcat(flat1, rconcat, 1);
// Should fail if 1 byte over, success if exactly matching
EXPECT_THAT(ExtractLast(concat, avail + 1), EqExtractResult(concat, nullptr));
EXPECT_THAT(ExtractLast(concat, avail), EqExtractResult(concat, flat3));
CordRep::Unref(concat);
CordRep::Unref(flat3);
}
} // namespace
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
...@@ -66,7 +66,7 @@ void Consume(bool forward, CordRep* rep, ConsumeFn consume_fn) { ...@@ -66,7 +66,7 @@ void Consume(bool forward, CordRep* rep, ConsumeFn consume_fn) {
absl::InlinedVector<Entry, 40> stack; absl::InlinedVector<Entry, 40> stack;
for (;;) { for (;;) {
if (rep->tag == CONCAT) { if (rep->IsConcat()) {
std::array<CordRep*, 2> res = ClipConcat(rep->concat()); std::array<CordRep*, 2> res = ClipConcat(rep->concat());
CordRep* left = res[0]; CordRep* left = res[0];
CordRep* right = res[1]; CordRep* right = res[1];
......
// 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 "absl/strings/internal/cord_rep_consume.h"
#include <functional>
#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_flat.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
namespace {
using testing::InSequence;
using testing::MockFunction;
// Returns the depth of a node
int Depth(const CordRep* rep) {
return (rep->tag == CONCAT) ? rep->concat()->depth() : 0;
}
// Creates a concatenation of the specified nodes.
CordRepConcat* CreateConcat(CordRep* left, CordRep* right) {
auto* concat = new CordRepConcat();
concat->tag = CONCAT;
concat->left = left;
concat->right = right;
concat->length = left->length + right->length;
concat->set_depth(1 + (std::max)(Depth(left), Depth(right)));
return concat;
}
// Creates a flat with the length set to `length`
CordRepFlat* CreateFlatWithLength(size_t length) {
auto* flat = CordRepFlat::New(length);
flat->length = length;
return flat;
}
// Creates a substring node on the specified child.
CordRepSubstring* CreateSubstring(CordRep* child, size_t start, size_t length) {
auto* rep = new CordRepSubstring();
rep->length = length;
rep->tag = SUBSTRING;
rep->start = start;
rep->child = child;
return rep;
}
// Flats we use in the tests
CordRep* flat[6];
// Creates a test tree
CordRep* CreateTestTree() {
flat[0] = CreateFlatWithLength(1);
flat[1] = CreateFlatWithLength(7);
CordRepConcat* left = CreateConcat(flat[0], CreateSubstring(flat[1], 2, 4));
flat[2] = CreateFlatWithLength(9);
flat[3] = CreateFlatWithLength(13);
CordRepConcat* right1 = CreateConcat(flat[2], flat[3]);
flat[4] = CreateFlatWithLength(15);
flat[5] = CreateFlatWithLength(19);
CordRepConcat* right2 = CreateConcat(flat[4], flat[5]);
CordRepConcat* right = CreateConcat(right1, CreateSubstring(right2, 5, 17));
return CreateConcat(left, right);
}
TEST(CordRepConsumeTest, Consume) {
InSequence in_sequence;
CordRep* tree = CreateTestTree();
MockFunction<void(CordRep*, size_t, size_t)> consume;
EXPECT_CALL(consume, Call(flat[0], 0, 1));
EXPECT_CALL(consume, Call(flat[1], 2, 4));
EXPECT_CALL(consume, Call(flat[2], 0, 9));
EXPECT_CALL(consume, Call(flat[3], 0, 13));
EXPECT_CALL(consume, Call(flat[4], 5, 10));
EXPECT_CALL(consume, Call(flat[5], 0, 7));
Consume(tree, consume.AsStdFunction());
for (CordRep* rep : flat) {
EXPECT_TRUE(rep->refcount.IsOne());
CordRep::Unref(rep);
}
}
TEST(CordRepConsumeTest, ConsumeShared) {
InSequence in_sequence;
CordRep* tree = CreateTestTree();
MockFunction<void(CordRep*, size_t, size_t)> consume;
EXPECT_CALL(consume, Call(flat[0], 0, 1));
EXPECT_CALL(consume, Call(flat[1], 2, 4));
EXPECT_CALL(consume, Call(flat[2], 0, 9));
EXPECT_CALL(consume, Call(flat[3], 0, 13));
EXPECT_CALL(consume, Call(flat[4], 5, 10));
EXPECT_CALL(consume, Call(flat[5], 0, 7));
Consume(CordRep::Ref(tree), consume.AsStdFunction());
for (CordRep* rep : flat) {
EXPECT_FALSE(rep->refcount.IsOne());
CordRep::Unref(rep);
}
CordRep::Unref(tree);
}
TEST(CordRepConsumeTest, Reverse) {
InSequence in_sequence;
CordRep* tree = CreateTestTree();
MockFunction<void(CordRep*, size_t, size_t)> consume;
EXPECT_CALL(consume, Call(flat[5], 0, 7));
EXPECT_CALL(consume, Call(flat[4], 5, 10));
EXPECT_CALL(consume, Call(flat[3], 0, 13));
EXPECT_CALL(consume, Call(flat[2], 0, 9));
EXPECT_CALL(consume, Call(flat[1], 2, 4));
EXPECT_CALL(consume, Call(flat[0], 0, 1));
ReverseConsume(tree, consume.AsStdFunction());
for (CordRep* rep : flat) {
EXPECT_TRUE(rep->refcount.IsOne());
CordRep::Unref(rep);
}
}
TEST(CordRepConsumeTest, ReverseShared) {
InSequence in_sequence;
CordRep* tree = CreateTestTree();
MockFunction<void(CordRep*, size_t, size_t)> consume;
EXPECT_CALL(consume, Call(flat[5], 0, 7));
EXPECT_CALL(consume, Call(flat[4], 5, 10));
EXPECT_CALL(consume, Call(flat[3], 0, 13));
EXPECT_CALL(consume, Call(flat[2], 0, 9));
EXPECT_CALL(consume, Call(flat[1], 2, 4));
EXPECT_CALL(consume, Call(flat[0], 0, 1));
ReverseConsume(CordRep::Ref(tree), consume.AsStdFunction());
for (CordRep* rep : flat) {
EXPECT_FALSE(rep->refcount.IsOne());
CordRep::Unref(rep);
}
CordRep::Unref(tree);
}
TEST(CordRepConsumeTest, UnreachableFlat) {
InSequence in_sequence;
CordRepFlat* flat1 = CreateFlatWithLength(10);
CordRepFlat* flat2 = CreateFlatWithLength(20);
CordRepConcat* concat = CreateConcat(flat1, flat2);
CordRepSubstring* tree = CreateSubstring(concat, 15, 10);
MockFunction<void(CordRep*, size_t, size_t)> consume;
EXPECT_CALL(consume, Call(flat2, 5, 10));
Consume(tree, consume.AsStdFunction());
EXPECT_TRUE(flat2->refcount.IsOne());
CordRep::Unref(flat2);
}
} // namespace
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
...@@ -42,18 +42,6 @@ inline cord_internal::CordRepSubstring* MakeSubstring( ...@@ -42,18 +42,6 @@ inline cord_internal::CordRepSubstring* MakeSubstring(
return sub; return sub;
} }
inline cord_internal::CordRepConcat* MakeConcat(cord_internal::CordRep* left,
cord_internal::CordRep* right,
int depth = 0) {
auto* concat = new cord_internal::CordRepConcat;
concat->tag = cord_internal::CONCAT;
concat->length = left->length + right->length;
concat->left = left;
concat->right = right;
concat->set_depth(depth);
return concat;
}
inline cord_internal::CordRepFlat* MakeFlat(absl::string_view value) { inline cord_internal::CordRepFlat* MakeFlat(absl::string_view value) {
assert(value.length() <= cord_internal::kMaxFlatLength); assert(value.length() <= cord_internal::kMaxFlatLength);
auto* flat = cord_internal::CordRepFlat::New(value.length()); auto* flat = cord_internal::CordRepFlat::New(value.length());
...@@ -126,7 +114,7 @@ inline void CordVisitReps(cord_internal::CordRep* rep, Fn&& fn) { ...@@ -126,7 +114,7 @@ inline void CordVisitReps(cord_internal::CordRep* rep, Fn&& fn) {
for (cord_internal::CordRep* edge : rep->btree()->Edges()) { for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
CordVisitReps(edge, fn); CordVisitReps(edge, fn);
} }
} else if (rep->tag == cord_internal::CONCAT) { } else if (rep->IsConcat()) {
CordVisitReps(rep->concat()->left, fn); CordVisitReps(rep->concat()->left, fn);
CordVisitReps(rep->concat()->right, fn); CordVisitReps(rep->concat()->right, fn);
} }
......
...@@ -98,7 +98,7 @@ class CordRepAnalyzer { ...@@ -98,7 +98,7 @@ class CordRepAnalyzer {
AnalyzeRing(repref); AnalyzeRing(repref);
} else if (repref.rep->tag == BTREE) { } else if (repref.rep->tag == BTREE) {
AnalyzeBtree(repref); AnalyzeBtree(repref);
} else if (repref.rep->tag == CONCAT) { } else if (repref.rep->IsConcat()) {
AnalyzeConcat(repref); AnalyzeConcat(repref);
} else { } else {
// We should have either a concat, btree, or ring node if not null. // We should have either a concat, btree, or ring node if not null.
...@@ -145,8 +145,8 @@ class CordRepAnalyzer { ...@@ -145,8 +145,8 @@ class CordRepAnalyzer {
// Asserts that `rr.rep` is a concat node or null. // Asserts that `rr.rep` is a concat node or null.
static RepRef AssertConcat(RepRef repref) { static RepRef AssertConcat(RepRef repref) {
const CordRep* rep = repref.rep; const CordRep* rep = repref.rep;
assert(rep == nullptr || rep->tag == CONCAT); assert(rep == nullptr || rep->IsConcat());
return (rep != nullptr && rep->tag == CONCAT) ? repref : RepRef{nullptr, 0}; return (rep != nullptr && rep->IsConcat()) ? repref : RepRef{nullptr, 0};
} }
// Counts a flat of the provide allocated size // Counts a flat of the provide allocated size
......
...@@ -76,16 +76,6 @@ CordRepSubstring* Substring(CordRep* rep) { ...@@ -76,16 +76,6 @@ CordRepSubstring* Substring(CordRep* rep) {
return substring; return substring;
} }
// Creates a concat on the provided reps
CordRepConcat* Concat(CordRep* left, CordRep* right) {
auto* concat = new CordRepConcat;
concat->length = left->length + right->length;
concat->tag = CONCAT;
concat->left = left;
concat->right = right;
return concat;
}
// Reference count helper // Reference count helper
struct RefHelper { struct RefHelper {
std::vector<CordRep*> refs; std::vector<CordRep*> refs;
...@@ -158,7 +148,7 @@ double FairShareImpl(CordRep* rep, size_t ref) { ...@@ -158,7 +148,7 @@ double FairShareImpl(CordRep* rep, size_t ref) {
rep->ring()->ForEach([&](CordRepRing::index_type i) { rep->ring()->ForEach([&](CordRepRing::index_type i) {
self += FairShareImpl(rep->ring()->entry_child(i), 1); self += FairShareImpl(rep->ring()->entry_child(i), 1);
}); });
} else if (rep->tag == CONCAT) { } else if (rep->IsConcat()) {
self = SizeOf(rep->concat()); self = SizeOf(rep->concat());
children = FairShareImpl(rep->concat()->left, ref) + children = FairShareImpl(rep->concat()->left, ref) +
FairShareImpl(rep->concat()->right, ref); FairShareImpl(rep->concat()->right, ref);
...@@ -307,80 +297,6 @@ TEST(CordzInfoStatisticsTest, SharedSubstring) { ...@@ -307,80 +297,6 @@ TEST(CordzInfoStatisticsTest, SharedSubstring) {
EXPECT_THAT(SampleCord(substring), EqStatistics(expected)); EXPECT_THAT(SampleCord(substring), EqStatistics(expected));
} }
TEST(CordzInfoStatisticsTest, Concat) {
RefHelper ref;
auto* flat1 = Flat(300);
auto* flat2 = Flat(2000);
auto* concat = ref.NeedsUnref(Concat(flat1, flat2));
CordzStatistics expected;
expected.size = concat->length;
expected.estimated_memory_usage =
SizeOf(concat) + SizeOf(flat1) + SizeOf(flat2);
expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
expected.node_count = 3;
expected.node_counts.flat = 2;
expected.node_counts.flat_512 = 1;
expected.node_counts.concat = 1;
EXPECT_THAT(SampleCord(concat), EqStatistics(expected));
}
TEST(CordzInfoStatisticsTest, DeepConcat) {
RefHelper ref;
auto* flat1 = Flat(300);
auto* flat2 = Flat(2000);
auto* flat3 = Flat(400);
auto* external = External(3000);
auto* substring = Substring(external);
auto* concat1 = Concat(flat1, flat2);
auto* concat2 = Concat(flat3, substring);
auto* concat = ref.NeedsUnref(Concat(concat1, concat2));
CordzStatistics expected;
expected.size = concat->length;
expected.estimated_memory_usage = SizeOf(concat) * 3 + SizeOf(flat1) +
SizeOf(flat2) + SizeOf(flat3) +
SizeOf(external) + SizeOf(substring);
expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
expected.node_count = 8;
expected.node_counts.flat = 3;
expected.node_counts.flat_512 = 2;
expected.node_counts.external = 1;
expected.node_counts.concat = 3;
expected.node_counts.substring = 1;
EXPECT_THAT(SampleCord(concat), EqStatistics(expected));
}
TEST(CordzInfoStatisticsTest, DeepSharedConcat) {
RefHelper ref;
auto* flat1 = Flat(40);
auto* flat2 = ref.Ref(Flat(2000), 4);
auto* flat3 = Flat(70);
auto* external = ref.Ref(External(3000));
auto* substring = ref.Ref(Substring(external), 3);
auto* concat1 = Concat(flat1, flat2);
auto* concat2 = Concat(flat3, substring);
auto* concat = ref.Ref(ref.NeedsUnref(Concat(concat1, concat2)));
CordzStatistics expected;
expected.size = concat->length;
expected.estimated_memory_usage = SizeOf(concat) * 3 + SizeOf(flat1) +
SizeOf(flat2) + SizeOf(flat3) +
SizeOf(external) + SizeOf(substring);
expected.estimated_fair_share_memory_usage = FairShare(concat);
expected.node_count = 8;
expected.node_counts.flat = 3;
expected.node_counts.flat_64 = 1;
expected.node_counts.flat_128 = 1;
expected.node_counts.external = 1;
expected.node_counts.concat = 3;
expected.node_counts.substring = 1;
EXPECT_THAT(SampleCord(concat), EqStatistics(expected));
}
TEST(CordzInfoStatisticsTest, Ring) { TEST(CordzInfoStatisticsTest, Ring) {
RefHelper ref; RefHelper ref;
...@@ -539,19 +455,15 @@ TEST(CordzInfoStatisticsTest, BtreeNodeShared) { ...@@ -539,19 +455,15 @@ TEST(CordzInfoStatisticsTest, BtreeNodeShared) {
TEST(CordzInfoStatisticsTest, Crc) { TEST(CordzInfoStatisticsTest, Crc) {
RefHelper ref; RefHelper ref;
auto* left = Flat(1000); auto* left = Flat(1000);
auto* right = Flat(1000); auto* crc = ref.NeedsUnref(CordRepCrc::New(left, 12345));
auto* concat = Concat(left, right);
auto* crc = ref.NeedsUnref(CordRepCrc::New(concat, 12345));
CordzStatistics expected; CordzStatistics expected;
expected.size = concat->length; expected.size = left->length;
expected.estimated_memory_usage = expected.estimated_memory_usage = SizeOf(crc) + SizeOf(left);
SizeOf(crc) + SizeOf(concat) + SizeOf(left) + SizeOf(right);
expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage; expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
expected.node_count = 4; expected.node_count = 2;
expected.node_counts.flat = 2; expected.node_counts.flat = 1;
expected.node_counts.flat_1k = 2; expected.node_counts.flat_1k = 1;
expected.node_counts.concat = 1;
expected.node_counts.crc = 1; expected.node_counts.crc = 1;
EXPECT_THAT(SampleCord(crc), EqStatistics(expected)); EXPECT_THAT(SampleCord(crc), EqStatistics(expected));
......
...@@ -120,7 +120,7 @@ using EnableIfFloat = ...@@ -120,7 +120,7 @@ using EnableIfFloat =
// Duration // Duration
// //
// The `absl::Duration` class represents a signed, fixed-length span of time. // The `absl::Duration` class represents a signed, fixed-length amount of time.
// A `Duration` is generated using a unit-specific factory function, or is // A `Duration` is generated using a unit-specific factory function, or is
// the result of subtracting one `absl::Time` from another. Durations behave // the result of subtracting one `absl::Time` from another. Durations behave
// like unit-safe integers and they support all the natural integer-like // like unit-safe integers and they support all the natural integer-like
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment