• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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