1 // Copyright 2020 The Abseil Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <cstdlib>
16 #include <ctime>
17 #include <memory>
18 #include <random>
19 #include <sstream>
20
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include "absl/debugging/leak_check.h"
24 #include "absl/strings/internal/cord_internal.h"
25 #include "absl/strings/internal/cord_rep_ring.h"
26 #include "absl/strings/internal/cord_rep_ring_reader.h"
27 #include "absl/strings/string_view.h"
28
29 namespace absl {
30 ABSL_NAMESPACE_BEGIN
31 namespace cord_internal {
32 namespace {
33
34 using testing::Eq;
35
36 // Creates a flat for testing
MakeFlat(absl::string_view s)37 CordRep* MakeFlat(absl::string_view s) {
38 CordRepFlat* flat = CordRepFlat::New(s.length());
39 memcpy(flat->Data(), s.data(), s.length());
40 flat->length = s.length();
41 return flat;
42 }
43
FromFlats(Span<absl::string_view const> flats)44 CordRepRing* FromFlats(Span<absl::string_view const> flats) {
45 CordRepRing* ring = CordRepRing::Create(MakeFlat(flats[0]), flats.size() - 1);
46 for (int i = 1; i < flats.size(); ++i) {
47 ring = CordRepRing::Append(ring, MakeFlat(flats[i]));
48 }
49 return ring;
50 }
51
TestFlats()52 std::array<absl::string_view, 12> TestFlats() {
53 return {"abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
54 "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
55 "+-=", "[]\\{}|;':", ",/<>?", "."};
56 }
57
TEST(CordRingReaderTest,DefaultInstance)58 TEST(CordRingReaderTest, DefaultInstance) {
59 CordRepRingReader reader;
60 EXPECT_FALSE(static_cast<bool>(reader));
61 EXPECT_THAT(reader.ring(), Eq(nullptr));
62 #ifndef NDEBUG
63 EXPECT_DEATH_IF_SUPPORTED(reader.length(), ".*");
64 EXPECT_DEATH_IF_SUPPORTED(reader.consumed(), ".*");
65 EXPECT_DEATH_IF_SUPPORTED(reader.remaining(), ".*");
66 EXPECT_DEATH_IF_SUPPORTED(reader.Next(), ".*");
67 EXPECT_DEATH_IF_SUPPORTED(reader.Seek(0), ".*");
68 #endif
69 }
70
TEST(CordRingReaderTest,Reset)71 TEST(CordRingReaderTest, Reset) {
72 CordRepRingReader reader;
73 auto flats = TestFlats();
74 CordRepRing* ring = FromFlats(flats);
75
76 absl::string_view first = reader.Reset(ring);
77 EXPECT_THAT(first, Eq(flats[0]));
78 EXPECT_TRUE(static_cast<bool>(reader));
79 EXPECT_THAT(reader.ring(), Eq(ring));
80 EXPECT_THAT(reader.index(), Eq(ring->head()));
81 EXPECT_THAT(reader.node(), Eq(ring->entry_child(ring->head())));
82 EXPECT_THAT(reader.length(), Eq(ring->length));
83 EXPECT_THAT(reader.consumed(), Eq(flats[0].length()));
84 EXPECT_THAT(reader.remaining(), Eq(ring->length - reader.consumed()));
85
86 reader.Reset();
87 EXPECT_FALSE(static_cast<bool>(reader));
88 EXPECT_THAT(reader.ring(), Eq(nullptr));
89
90 CordRep::Unref(ring);
91 }
92
TEST(CordRingReaderTest,Next)93 TEST(CordRingReaderTest, Next) {
94 CordRepRingReader reader;
95 auto flats = TestFlats();
96 CordRepRing* ring = FromFlats(flats);
97 CordRepRing::index_type head = ring->head();
98
99 reader.Reset(ring);
100 size_t consumed = reader.consumed();
101 size_t remaining = reader.remaining();
102 for (int i = 1; i < flats.size(); ++i) {
103 CordRepRing::index_type index = ring->advance(head, i);
104 consumed += flats[i].length();
105 remaining -= flats[i].length();
106 absl::string_view next = reader.Next();
107 ASSERT_THAT(next, Eq(flats[i]));
108 ASSERT_THAT(reader.index(), Eq(index));
109 ASSERT_THAT(reader.node(), Eq(ring->entry_child(index)));
110 ASSERT_THAT(reader.consumed(), Eq(consumed));
111 ASSERT_THAT(reader.remaining(), Eq(remaining));
112 }
113
114 #ifndef NDEBUG
115 EXPECT_DEATH_IF_SUPPORTED(reader.Next(), ".*");
116 #endif
117
118 CordRep::Unref(ring);
119 }
120
TEST(CordRingReaderTest,SeekForward)121 TEST(CordRingReaderTest, SeekForward) {
122 CordRepRingReader reader;
123 auto flats = TestFlats();
124 CordRepRing* ring = FromFlats(flats);
125 CordRepRing::index_type head = ring->head();
126
127 reader.Reset(ring);
128 size_t consumed = 0;
129 size_t remaining = ring->length;;
130 for (int i = 0; i < flats.size(); ++i) {
131 CordRepRing::index_type index = ring->advance(head, i);
132 size_t offset = consumed;
133 consumed += flats[i].length();
134 remaining -= flats[i].length();
135 for (int off = 0; off < flats[i].length(); ++off) {
136 absl::string_view chunk = reader.Seek(offset + off);
137 ASSERT_THAT(chunk, Eq(flats[i].substr(off)));
138 ASSERT_THAT(reader.index(), Eq(index));
139 ASSERT_THAT(reader.node(), Eq(ring->entry_child(index)));
140 ASSERT_THAT(reader.consumed(), Eq(consumed));
141 ASSERT_THAT(reader.remaining(), Eq(remaining));
142 }
143 }
144
145 CordRep::Unref(ring);
146 }
147
TEST(CordRingReaderTest,SeekBackward)148 TEST(CordRingReaderTest, SeekBackward) {
149 CordRepRingReader reader;
150 auto flats = TestFlats();
151 CordRepRing* ring = FromFlats(flats);
152 CordRepRing::index_type head = ring->head();
153
154 reader.Reset(ring);
155 size_t consumed = ring->length;
156 size_t remaining = 0;
157 for (int i = flats.size() - 1; i >= 0; --i) {
158 CordRepRing::index_type index = ring->advance(head, i);
159 size_t offset = consumed - flats[i].length();
160 for (int off = 0; off < flats[i].length(); ++off) {
161 absl::string_view chunk = reader.Seek(offset + off);
162 ASSERT_THAT(chunk, Eq(flats[i].substr(off)));
163 ASSERT_THAT(reader.index(), Eq(index));
164 ASSERT_THAT(reader.node(), Eq(ring->entry_child(index)));
165 ASSERT_THAT(reader.consumed(), Eq(consumed));
166 ASSERT_THAT(reader.remaining(), Eq(remaining));
167 }
168 consumed -= flats[i].length();
169 remaining += flats[i].length();
170 }
171 #ifndef NDEBUG
172 EXPECT_DEATH_IF_SUPPORTED(reader.Seek(ring->length), ".*");
173 #endif
174 CordRep::Unref(ring);
175 }
176
177 } // namespace
178 } // namespace cord_internal
179 ABSL_NAMESPACE_END
180 } // namespace absl
181