xref: /aosp_15_r20/external/pigweed/pw_multibuf/multibuf_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2023 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker 
15*61c4878aSAndroid Build Coastguard Worker #include "pw_multibuf/multibuf.h"
16*61c4878aSAndroid Build Coastguard Worker 
17*61c4878aSAndroid Build Coastguard Worker #include "pw_assert/check.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/array.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/suffix.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_multibuf_private/test_utils.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_span/span.h"
22*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
23*61c4878aSAndroid Build Coastguard Worker 
24*61c4878aSAndroid Build Coastguard Worker namespace pw::multibuf {
25*61c4878aSAndroid Build Coastguard Worker namespace {
26*61c4878aSAndroid Build Coastguard Worker 
27*61c4878aSAndroid Build Coastguard Worker using namespace pw::multibuf::test_utils;
28*61c4878aSAndroid Build Coastguard Worker 
29*61c4878aSAndroid Build Coastguard Worker #if __cplusplus >= 202002L
30*61c4878aSAndroid Build Coastguard Worker static_assert(std::forward_iterator<MultiBuf::iterator>);
31*61c4878aSAndroid Build Coastguard Worker static_assert(std::forward_iterator<MultiBuf::const_iterator>);
32*61c4878aSAndroid Build Coastguard Worker static_assert(std::forward_iterator<MultiBufChunks::iterator>);
33*61c4878aSAndroid Build Coastguard Worker static_assert(std::forward_iterator<MultiBufChunks::const_iterator>);
34*61c4878aSAndroid Build Coastguard Worker #endif  // __cplusplus >= 202002L
35*61c4878aSAndroid Build Coastguard Worker 
36*61c4878aSAndroid Build Coastguard Worker static_assert(
37*61c4878aSAndroid Build Coastguard Worker     sizeof(MultiBufChunks) == sizeof(MultiBuf),
38*61c4878aSAndroid Build Coastguard Worker     "MultiBuf is a byte view of MultiBufChunks and does not add members");
39*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IsDefaultConstructible)40*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IsDefaultConstructible) { [[maybe_unused]] MultiBuf buf; }
41*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,WithOneChunkReleases)42*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, WithOneChunkReleases) {
43*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
44*61c4878aSAndroid Build Coastguard Worker   const auto& metrics = allocator.metrics();
45*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
46*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
47*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(metrics.num_allocations.value(), 2U);
48*61c4878aSAndroid Build Coastguard Worker   buf.Release();
49*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(metrics.num_deallocations.value(), 2U);
50*61c4878aSAndroid Build Coastguard Worker }
51*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,WithOneChunkReleasesOnDestruction)52*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, WithOneChunkReleasesOnDestruction) {
53*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
54*61c4878aSAndroid Build Coastguard Worker   const auto& metrics = allocator.metrics();
55*61c4878aSAndroid Build Coastguard Worker   {
56*61c4878aSAndroid Build Coastguard Worker     MultiBuf buf;
57*61c4878aSAndroid Build Coastguard Worker     buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
58*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(metrics.num_allocations.value(), 2U);
59*61c4878aSAndroid Build Coastguard Worker   }
60*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(metrics.num_deallocations.value(), 2U);
61*61c4878aSAndroid Build Coastguard Worker }
62*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,WithMultipleChunksReleasesAllOnDestruction)63*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, WithMultipleChunksReleasesAllOnDestruction) {
64*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
65*61c4878aSAndroid Build Coastguard Worker   const auto& metrics = allocator.metrics();
66*61c4878aSAndroid Build Coastguard Worker   {
67*61c4878aSAndroid Build Coastguard Worker     MultiBuf buf;
68*61c4878aSAndroid Build Coastguard Worker     buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
69*61c4878aSAndroid Build Coastguard Worker     buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
70*61c4878aSAndroid Build Coastguard Worker     EXPECT_EQ(metrics.num_allocations.value(), 4U);
71*61c4878aSAndroid Build Coastguard Worker   }
72*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(metrics.num_deallocations.value(), 4U);
73*61c4878aSAndroid Build Coastguard Worker }
74*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,SizeReturnsNumberOfBytes)75*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, SizeReturnsNumberOfBytes) {
76*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
77*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
78*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
79*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
80*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), kArbitraryChunkSize);
81*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
82*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), kArbitraryChunkSize * 2);
83*61c4878aSAndroid Build Coastguard Worker }
84*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,EmptyIfNoChunks)85*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, EmptyIfNoChunks) {
86*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
87*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
88*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
89*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.empty());
90*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
91*61c4878aSAndroid Build Coastguard Worker   EXPECT_NE(buf.size(), 0U);
92*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(buf.empty());
93*61c4878aSAndroid Build Coastguard Worker }
94*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,EmptyIfOnlyEmptyChunks)95*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, EmptyIfOnlyEmptyChunks) {
96*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
97*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
98*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.empty());
99*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 0));
100*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.empty());
101*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 0));
102*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.empty());
103*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
104*61c4878aSAndroid Build Coastguard Worker }
105*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,EmptyIsFalseIfAnyNonEmptyChunks)106*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, EmptyIsFalseIfAnyNonEmptyChunks) {
107*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
108*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
109*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 0));
110*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.empty());
111*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
112*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(buf.empty());
113*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), kArbitraryChunkSize);
114*61c4878aSAndroid Build Coastguard Worker }
115*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ClaimPrefixReclaimsFirstChunkPrefix)116*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ClaimPrefixReclaimsFirstChunkPrefix) {
117*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
118*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
119*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk = MakeChunk(allocator, 16);
120*61c4878aSAndroid Build Coastguard Worker   chunk->DiscardPrefix(7);
121*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(std::move(chunk));
122*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 9U);
123*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.ClaimPrefix(7), true);
124*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 16U);
125*61c4878aSAndroid Build Coastguard Worker }
126*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ClaimPrefixOnFirstChunkWithoutPrefixReturnsFalse)127*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ClaimPrefixOnFirstChunkWithoutPrefixReturnsFalse) {
128*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
129*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
130*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 16));
131*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 16U);
132*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.ClaimPrefix(7), false);
133*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 16U);
134*61c4878aSAndroid Build Coastguard Worker }
135*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ClaimPrefixWithoutChunksReturnsFalse)136*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ClaimPrefixWithoutChunksReturnsFalse) {
137*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
138*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
139*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
140*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.ClaimPrefix(7), false);
141*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
142*61c4878aSAndroid Build Coastguard Worker }
143*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ClaimSuffixReclaimsLastChunkSuffix)144*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ClaimSuffixReclaimsLastChunkSuffix) {
145*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
146*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
147*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk = MakeChunk(allocator, 16U);
148*61c4878aSAndroid Build Coastguard Worker   chunk->Truncate(9U);
149*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(std::move(chunk));
150*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 4U));
151*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 13U);
152*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.ClaimSuffix(7U), true);
153*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 20U);
154*61c4878aSAndroid Build Coastguard Worker }
155*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ClaimSuffixOnLastChunkWithoutSuffixReturnsFalse)156*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ClaimSuffixOnLastChunkWithoutSuffixReturnsFalse) {
157*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
158*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
159*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 16U));
160*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 16U);
161*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.ClaimPrefix(7U), false);
162*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 16U);
163*61c4878aSAndroid Build Coastguard Worker }
164*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ClaimSuffixWithoutChunksReturnsFalse)165*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ClaimSuffixWithoutChunksReturnsFalse) {
166*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
167*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
168*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
169*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.ClaimSuffix(7U), false);
170*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
171*61c4878aSAndroid Build Coastguard Worker }
172*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,DiscardPrefixWithZeroDoesNothing)173*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, DiscardPrefixWithZeroDoesNothing) {
174*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
175*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
176*61c4878aSAndroid Build Coastguard Worker   buf.DiscardPrefix(0);
177*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
178*61c4878aSAndroid Build Coastguard Worker }
179*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,DiscardPrefixDiscardsPartialChunk)180*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, DiscardPrefixDiscardsPartialChunk) {
181*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
182*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
183*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 16U));
184*61c4878aSAndroid Build Coastguard Worker   buf.DiscardPrefix(5U);
185*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 11U);
186*61c4878aSAndroid Build Coastguard Worker }
187*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,DiscardPrefixDiscardsWholeChunk)188*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, DiscardPrefixDiscardsWholeChunk) {
189*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
190*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
191*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 16U));
192*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
193*61c4878aSAndroid Build Coastguard Worker   buf.DiscardPrefix(16U);
194*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 3U);
195*61c4878aSAndroid Build Coastguard Worker }
196*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,DiscardPrefixDiscardsMultipleChunks)197*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, DiscardPrefixDiscardsMultipleChunks) {
198*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
199*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
200*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 16U));
201*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 4U));
202*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
203*61c4878aSAndroid Build Coastguard Worker   buf.DiscardPrefix(21U);
204*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 2U);
205*61c4878aSAndroid Build Coastguard Worker }
206*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,SliceDiscardsPrefixAndSuffixWholeAndPartialChunks)207*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, SliceDiscardsPrefixAndSuffixWholeAndPartialChunks) {
208*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
209*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
210*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 1_b, 1_b}));
211*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {2_b, 2_b, 2_b}));
212*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {3_b, 3_b, 3_b}));
213*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 4_b, 4_b}));
214*61c4878aSAndroid Build Coastguard Worker   buf.Slice(4, 7);
215*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, {2_b, 2_b, 3_b});
216*61c4878aSAndroid Build Coastguard Worker }
217*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,SliceDoesNotModifyChunkMemory)218*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, SliceDoesNotModifyChunkMemory) {
219*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
220*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
221*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 4> kBytes = {1_b, 2_b, 3_b, 4_b};
222*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk = MakeChunk(allocator, kBytes);
223*61c4878aSAndroid Build Coastguard Worker   ConstByteSpan span(chunk);
224*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(std::move(chunk));
225*61c4878aSAndroid Build Coastguard Worker   buf.Slice(2, 3);
226*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(span, kBytes);
227*61c4878aSAndroid Build Coastguard Worker }
228*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TruncateRemovesFinalEmptyChunk)229*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TruncateRemovesFinalEmptyChunk) {
230*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
231*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
232*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
233*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
234*61c4878aSAndroid Build Coastguard Worker   buf.Truncate(3U);
235*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 3U);
236*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.Chunks().size(), 1U);
237*61c4878aSAndroid Build Coastguard Worker }
238*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TruncateRemovesWholeAndPartialChunks)239*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TruncateRemovesWholeAndPartialChunks) {
240*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
241*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
242*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
243*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
244*61c4878aSAndroid Build Coastguard Worker   buf.Truncate(2U);
245*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 2U);
246*61c4878aSAndroid Build Coastguard Worker }
247*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TruncateAfterRemovesWholeAndPartialChunks)248*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TruncateAfterRemovesWholeAndPartialChunks) {
249*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
250*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
251*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 3U));
252*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 0U));
253*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, 1U));
254*61c4878aSAndroid Build Coastguard Worker   auto it = buf.begin();
255*61c4878aSAndroid Build Coastguard Worker   ++it;
256*61c4878aSAndroid Build Coastguard Worker   buf.TruncateAfter(it);
257*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 2U);
258*61c4878aSAndroid Build Coastguard Worker }
259*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TruncateEmptyBuffer)260*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TruncateEmptyBuffer) {
261*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
262*61c4878aSAndroid Build Coastguard Worker   buf.Truncate(0);
263*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.empty());
264*61c4878aSAndroid Build Coastguard Worker }
265*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TakePrefixWithNoBytesDoesNothing)266*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TakePrefixWithNoBytesDoesNothing) {
267*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
268*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
269*61c4878aSAndroid Build Coastguard Worker   std::optional<MultiBuf> empty_front = buf.TakePrefix(0);
270*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(empty_front.has_value());
271*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(buf.size(), 0U);
272*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(empty_front->size(), 0U);
273*61c4878aSAndroid Build Coastguard Worker }
274*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TakePrefixReturnsPartialChunk)275*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TakePrefixReturnsPartialChunk) {
276*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
277*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
278*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
279*61c4878aSAndroid Build Coastguard Worker   std::optional<MultiBuf> old_front = buf.TakePrefix(2);
280*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(old_front.has_value());
281*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(*old_front, {1_b, 2_b});
282*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, {3_b});
283*61c4878aSAndroid Build Coastguard Worker }
284*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TakePrefixReturnsWholeAndPartialChunks)285*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TakePrefixReturnsWholeAndPartialChunks) {
286*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
287*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
288*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
289*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
290*61c4878aSAndroid Build Coastguard Worker   std::optional<MultiBuf> old_front = buf.TakePrefix(4);
291*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(old_front.has_value());
292*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(*old_front, {1_b, 2_b, 3_b, 4_b});
293*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, {5_b, 6_b});
294*61c4878aSAndroid Build Coastguard Worker }
295*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TakeSuffixReturnsWholeAndPartialChunks)296*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TakeSuffixReturnsWholeAndPartialChunks) {
297*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
298*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
299*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
300*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
301*61c4878aSAndroid Build Coastguard Worker   std::optional<MultiBuf> old_tail = buf.TakeSuffix(4);
302*61c4878aSAndroid Build Coastguard Worker   ASSERT_TRUE(old_tail.has_value());
303*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, {1_b, 2_b});
304*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(*old_tail, {3_b, 4_b, 5_b, 6_b});
305*61c4878aSAndroid Build Coastguard Worker }
306*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,PushPrefixPrependsData)307*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, PushPrefixPrependsData) {
308*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
309*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
310*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
311*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
312*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf2;
313*61c4878aSAndroid Build Coastguard Worker   buf2.PushBackChunk(MakeChunk(allocator, {7_b, 8_b}));
314*61c4878aSAndroid Build Coastguard Worker   buf2.PushPrefix(std::move(buf));
315*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf2, {1_b, 2_b, 3_b, 4_b, 5_b, 6_b, 7_b, 8_b});
316*61c4878aSAndroid Build Coastguard Worker }
317*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,PushSuffixAppendsData)318*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, PushSuffixAppendsData) {
319*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
320*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
321*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
322*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
323*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf2;
324*61c4878aSAndroid Build Coastguard Worker   buf2.PushBackChunk(MakeChunk(allocator, {7_b, 8_b}));
325*61c4878aSAndroid Build Coastguard Worker   buf2.PushSuffix(std::move(buf));
326*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf2, {7_b, 8_b, 1_b, 2_b, 3_b, 4_b, 5_b, 6_b});
327*61c4878aSAndroid Build Coastguard Worker }
328*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,PushFrontChunkAddsBytesToFront)329*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, PushFrontChunkAddsBytesToFront) {
330*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
331*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
332*61c4878aSAndroid Build Coastguard Worker 
333*61c4878aSAndroid Build Coastguard Worker   const std::array<std::byte, 3> kBytesOne = {0_b, 1_b, 2_b};
334*61c4878aSAndroid Build Coastguard Worker   auto chunk_one = MakeChunk(allocator, kBytesOne);
335*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(std::move(chunk_one));
336*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, kBytesOne);
337*61c4878aSAndroid Build Coastguard Worker 
338*61c4878aSAndroid Build Coastguard Worker   const std::array<std::byte, 4> kBytesTwo = {9_b, 10_b, 11_b, 12_b};
339*61c4878aSAndroid Build Coastguard Worker   auto chunk_two = MakeChunk(allocator, kBytesTwo);
340*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(std::move(chunk_two));
341*61c4878aSAndroid Build Coastguard Worker 
342*61c4878aSAndroid Build Coastguard Worker   // clang-format off
343*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, {
344*61c4878aSAndroid Build Coastguard Worker       9_b, 10_b, 11_b, 12_b,
345*61c4878aSAndroid Build Coastguard Worker       0_b, 1_b, 2_b,
346*61c4878aSAndroid Build Coastguard Worker   });
347*61c4878aSAndroid Build Coastguard Worker   // clang-format on
348*61c4878aSAndroid Build Coastguard Worker }
349*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,InsertChunkOnEmptyBufAddsFirstChunk)350*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, InsertChunkOnEmptyBufAddsFirstChunk) {
351*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
352*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
353*61c4878aSAndroid Build Coastguard Worker 
354*61c4878aSAndroid Build Coastguard Worker   const std::array<std::byte, 3> kBytes = {0_b, 1_b, 2_b};
355*61c4878aSAndroid Build Coastguard Worker   auto chunk = MakeChunk(allocator, kBytes);
356*61c4878aSAndroid Build Coastguard Worker   auto inserted_iter = buf.InsertChunk(buf.Chunks().begin(), std::move(chunk));
357*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(inserted_iter, buf.Chunks().begin());
358*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(buf, kBytes);
359*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(++inserted_iter, buf.Chunks().end());
360*61c4878aSAndroid Build Coastguard Worker }
361*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,InsertChunkAtEndOfBufAddsLastChunk)362*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, InsertChunkAtEndOfBufAddsLastChunk) {
363*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
364*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
365*61c4878aSAndroid Build Coastguard Worker 
366*61c4878aSAndroid Build Coastguard Worker   // Add a chunk to the beginning
367*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, kArbitraryChunkSize));
368*61c4878aSAndroid Build Coastguard Worker 
369*61c4878aSAndroid Build Coastguard Worker   const std::array<std::byte, 3> kBytes = {0_b, 1_b, 2_b};
370*61c4878aSAndroid Build Coastguard Worker   auto chunk = MakeChunk(allocator, kBytes);
371*61c4878aSAndroid Build Coastguard Worker   auto inserted_iter = buf.InsertChunk(buf.Chunks().end(), std::move(chunk));
372*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(inserted_iter, ++buf.Chunks().begin());
373*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(++inserted_iter, buf.Chunks().end());
374*61c4878aSAndroid Build Coastguard Worker   const Chunk& second_chunk = *(++buf.Chunks().begin());
375*61c4878aSAndroid Build Coastguard Worker   ExpectElementsEqual(second_chunk, kBytes);
376*61c4878aSAndroid Build Coastguard Worker }
377*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TakeChunkAtBeginRemovesAndReturnsFirstChunk)378*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TakeChunkAtBeginRemovesAndReturnsFirstChunk) {
379*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
380*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
381*61c4878aSAndroid Build Coastguard Worker   auto insert_iter = buf.Chunks().begin();
382*61c4878aSAndroid Build Coastguard Worker   insert_iter = buf.InsertChunk(insert_iter, MakeChunk(allocator, 2));
383*61c4878aSAndroid Build Coastguard Worker   insert_iter = buf.InsertChunk(++insert_iter, MakeChunk(allocator, 4));
384*61c4878aSAndroid Build Coastguard Worker 
385*61c4878aSAndroid Build Coastguard Worker   auto [chunk_iter, chunk] = buf.TakeChunk(buf.Chunks().begin());
386*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(chunk.size(), 2U);
387*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(chunk_iter->size(), 4U);
388*61c4878aSAndroid Build Coastguard Worker   ++chunk_iter;
389*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(chunk_iter, buf.Chunks().end());
390*61c4878aSAndroid Build Coastguard Worker }
391*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,TakeChunkOnLastInsertedIterReturnsLastInserted)392*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, TakeChunkOnLastInsertedIterReturnsLastInserted) {
393*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
394*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
395*61c4878aSAndroid Build Coastguard Worker   auto iter = buf.Chunks().begin();
396*61c4878aSAndroid Build Coastguard Worker   iter = buf.InsertChunk(iter, MakeChunk(allocator, 42));
397*61c4878aSAndroid Build Coastguard Worker   iter = buf.InsertChunk(++iter, MakeChunk(allocator, 11));
398*61c4878aSAndroid Build Coastguard Worker   iter = buf.InsertChunk(++iter, MakeChunk(allocator, 65));
399*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk;
400*61c4878aSAndroid Build Coastguard Worker   std::tie(iter, chunk) = buf.TakeChunk(iter);
401*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(iter, buf.Chunks().end());
402*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(chunk.size(), 65U);
403*61c4878aSAndroid Build Coastguard Worker }
404*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,RangeBasedForLoopsCompile)405*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, RangeBasedForLoopsCompile) {
406*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
407*61c4878aSAndroid Build Coastguard Worker   for ([[maybe_unused]] std::byte& byte : buf) {
408*61c4878aSAndroid Build Coastguard Worker   }
409*61c4878aSAndroid Build Coastguard Worker   for ([[maybe_unused]] const std::byte& byte : buf) {
410*61c4878aSAndroid Build Coastguard Worker   }
411*61c4878aSAndroid Build Coastguard Worker   for ([[maybe_unused]] Chunk& chunk : buf.Chunks()) {
412*61c4878aSAndroid Build Coastguard Worker   }
413*61c4878aSAndroid Build Coastguard Worker   for ([[maybe_unused]] const Chunk& chunk : buf.Chunks()) {
414*61c4878aSAndroid Build Coastguard Worker   }
415*61c4878aSAndroid Build Coastguard Worker 
416*61c4878aSAndroid Build Coastguard Worker   const MultiBuf const_buf;
417*61c4878aSAndroid Build Coastguard Worker   for ([[maybe_unused]] const std::byte& byte : const_buf) {
418*61c4878aSAndroid Build Coastguard Worker   }
419*61c4878aSAndroid Build Coastguard Worker   for ([[maybe_unused]] const Chunk& chunk : const_buf.Chunks()) {
420*61c4878aSAndroid Build Coastguard Worker   }
421*61c4878aSAndroid Build Coastguard Worker }
422*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IteratorAdvancesNAcrossChunks)423*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IteratorAdvancesNAcrossChunks) {
424*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
425*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
426*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
427*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
428*61c4878aSAndroid Build Coastguard Worker 
429*61c4878aSAndroid Build Coastguard Worker   MultiBuf::iterator iter = buf.begin();
430*61c4878aSAndroid Build Coastguard Worker   iter += 4;
431*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*iter, 5_b);
432*61c4878aSAndroid Build Coastguard Worker }
433*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IteratorAdvancesNAcrossZeroLengthChunk)434*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IteratorAdvancesNAcrossZeroLengthChunk) {
435*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
436*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
437*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));
438*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
439*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));
440*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
441*61c4878aSAndroid Build Coastguard Worker 
442*61c4878aSAndroid Build Coastguard Worker   MultiBuf::iterator iter = buf.begin();
443*61c4878aSAndroid Build Coastguard Worker   iter += 4;
444*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*iter, 5_b);
445*61c4878aSAndroid Build Coastguard Worker }
446*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ConstIteratorAdvancesNAcrossChunks)447*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ConstIteratorAdvancesNAcrossChunks) {
448*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
449*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
450*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b}));
451*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
452*61c4878aSAndroid Build Coastguard Worker 
453*61c4878aSAndroid Build Coastguard Worker   MultiBuf::const_iterator iter = buf.cbegin();
454*61c4878aSAndroid Build Coastguard Worker   iter += 4;
455*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(*iter, 5_b);
456*61c4878aSAndroid Build Coastguard Worker }
457*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IteratorSkipsEmptyChunks)458*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IteratorSkipsEmptyChunks) {
459*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
460*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
461*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));
462*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));
463*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b}));
464*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));
465*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {2_b, 3_b}));
466*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));
467*61c4878aSAndroid Build Coastguard Worker 
468*61c4878aSAndroid Build Coastguard Worker   MultiBuf::iterator it = buf.begin();
469*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(*it++, 1_b);
470*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(*it++, 2_b);
471*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(*it++, 3_b);
472*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(it, buf.end());
473*61c4878aSAndroid Build Coastguard Worker }
474*61c4878aSAndroid Build Coastguard Worker 
475*61c4878aSAndroid Build Coastguard Worker constexpr auto kSequentialBytes =
__anon141f71f30202(size_t i) 476*61c4878aSAndroid Build Coastguard Worker     bytes::Initialized<6>([](size_t i) { return i + 1; });
477*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyToFromEmptyMultiBuf)478*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyToFromEmptyMultiBuf) {
479*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
480*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
481*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 6> buffer = {};
482*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = buf.CopyTo(buffer);
483*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
484*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
485*61c4878aSAndroid Build Coastguard Worker 
486*61c4878aSAndroid Build Coastguard Worker   result = buf.CopyTo({});
487*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
488*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
489*61c4878aSAndroid Build Coastguard Worker }
490*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyToEmptyDestination)491*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyToEmptyDestination) {
492*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
493*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
494*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b, 4_b}));
495*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = buf.CopyTo({});
496*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), Status::ResourceExhausted());
497*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
498*61c4878aSAndroid Build Coastguard Worker }
499*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyToOneChunk)500*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyToOneChunk) {
501*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
502*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
503*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b, 2_b, 3_b, 4_b}));
504*61c4878aSAndroid Build Coastguard Worker 
505*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 4> buffer = {};
506*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = buf.CopyTo(buffer);
507*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
508*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 4u);
509*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(
510*61c4878aSAndroid Build Coastguard Worker       std::equal(buffer.begin(), buffer.end(), kSequentialBytes.begin()));
511*61c4878aSAndroid Build Coastguard Worker }
512*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyToVariousChunks)513*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyToVariousChunks) {
514*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
515*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
516*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b}));
517*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {2_b, 3_b}));
518*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
519*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
520*61c4878aSAndroid Build Coastguard Worker 
521*61c4878aSAndroid Build Coastguard Worker   std::array<std::byte, 6> buffer = {};
522*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = buf.CopyTo(buffer);
523*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
524*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 6u);
525*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(
526*61c4878aSAndroid Build Coastguard Worker       std::equal(buffer.begin(), buffer.end(), kSequentialBytes.begin()));
527*61c4878aSAndroid Build Coastguard Worker }
528*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyToInTwoParts)529*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyToInTwoParts) {
530*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
531*61c4878aSAndroid Build Coastguard Worker 
532*61c4878aSAndroid Build Coastguard Worker   constexpr size_t kMultiBufSize = 6;
533*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
534*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b}));
535*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {2_b, 3_b}));
536*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
537*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {4_b, 5_b, 6_b}));
538*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(buf.size(), kMultiBufSize);
539*61c4878aSAndroid Build Coastguard Worker 
540*61c4878aSAndroid Build Coastguard Worker   for (size_t first = 0; first < kMultiBufSize; ++first) {
541*61c4878aSAndroid Build Coastguard Worker     std::array<std::byte, kMultiBufSize> buffer = {};
542*61c4878aSAndroid Build Coastguard Worker     StatusWithSize result = buf.CopyTo(span(buffer).first(first));
543*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.status(), Status::ResourceExhausted());
544*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.size(), first);
545*61c4878aSAndroid Build Coastguard Worker 
546*61c4878aSAndroid Build Coastguard Worker     result = buf.CopyTo(span(buffer).last(kMultiBufSize - first),
547*61c4878aSAndroid Build Coastguard Worker                         result.size());  // start from last offset
548*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.status(), OkStatus());
549*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.size(), kMultiBufSize - first);
550*61c4878aSAndroid Build Coastguard Worker 
551*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(
552*61c4878aSAndroid Build Coastguard Worker         std::equal(buffer.begin(), buffer.end(), kSequentialBytes.begin()))
553*61c4878aSAndroid Build Coastguard Worker         << "The whole buffer should have copied";
554*61c4878aSAndroid Build Coastguard Worker   }
555*61c4878aSAndroid Build Coastguard Worker }
556*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyToPositionIsEnd)557*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyToPositionIsEnd) {
558*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
559*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
560*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b}));
561*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {2_b, 3_b}));
562*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
563*61c4878aSAndroid Build Coastguard Worker 
564*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = buf.CopyTo({}, 3u);
565*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.status(), OkStatus());
566*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
567*61c4878aSAndroid Build Coastguard Worker }
568*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyFromIntoOneChunk)569*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyFromIntoOneChunk) {
570*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
571*61c4878aSAndroid Build Coastguard Worker   MultiBuf mb;
572*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 6));
573*61c4878aSAndroid Build Coastguard Worker 
574*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = mb.CopyFrom(kSequentialBytes);
575*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status(), OkStatus());
576*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), 6u);
577*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(std::equal(mb.begin(), mb.end(), kSequentialBytes.begin()));
578*61c4878aSAndroid Build Coastguard Worker }
579*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyFromIntoMultipleChunks)580*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyFromIntoMultipleChunks) {
581*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
582*61c4878aSAndroid Build Coastguard Worker   MultiBuf mb;
583*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 2));
584*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 0));
585*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 3));
586*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 1));
587*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 0));
588*61c4878aSAndroid Build Coastguard Worker 
589*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = mb.CopyFrom(kSequentialBytes);
590*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status(), OkStatus());
591*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(result.size(), 6u);
592*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(std::equal(mb.begin(), mb.end(), kSequentialBytes.begin()));
593*61c4878aSAndroid Build Coastguard Worker }
594*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyFromInTwoParts)595*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyFromInTwoParts) {
596*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
597*61c4878aSAndroid Build Coastguard Worker 
598*61c4878aSAndroid Build Coastguard Worker   for (size_t first = 0; first < kSequentialBytes.size(); ++first) {
599*61c4878aSAndroid Build Coastguard Worker     MultiBuf mb;
600*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 1));
601*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 0));
602*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 0));
603*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 2));
604*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 3));
605*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(mb.size(), kSequentialBytes.size());
606*61c4878aSAndroid Build Coastguard Worker 
607*61c4878aSAndroid Build Coastguard Worker     StatusWithSize result = mb.CopyFrom(span(kSequentialBytes).first(first));
608*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.status(), OkStatus());
609*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.size(), first);
610*61c4878aSAndroid Build Coastguard Worker 
611*61c4878aSAndroid Build Coastguard Worker     result = mb.CopyFrom(
612*61c4878aSAndroid Build Coastguard Worker         span(kSequentialBytes).last(kSequentialBytes.size() - first),
613*61c4878aSAndroid Build Coastguard Worker         result.size());  // start from last offset
614*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.status(), OkStatus());
615*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.size(), kSequentialBytes.size() - first);
616*61c4878aSAndroid Build Coastguard Worker 
617*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(std::equal(mb.begin(), mb.end(), kSequentialBytes.begin()))
618*61c4878aSAndroid Build Coastguard Worker         << "The whole buffer should have copied";
619*61c4878aSAndroid Build Coastguard Worker   }
620*61c4878aSAndroid Build Coastguard Worker }
621*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyFromAndTruncate)622*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyFromAndTruncate) {
623*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
624*61c4878aSAndroid Build Coastguard Worker 
625*61c4878aSAndroid Build Coastguard Worker   for (size_t to_copy = 0; to_copy < kSequentialBytes.size(); ++to_copy) {
626*61c4878aSAndroid Build Coastguard Worker     MultiBuf mb;
627*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 1));
628*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 0));
629*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 0));
630*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 2));
631*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 3));
632*61c4878aSAndroid Build Coastguard Worker     mb.PushBackChunk(MakeChunk(allocator, 0));
633*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(mb.size(), kSequentialBytes.size());
634*61c4878aSAndroid Build Coastguard Worker 
635*61c4878aSAndroid Build Coastguard Worker     StatusWithSize result =
636*61c4878aSAndroid Build Coastguard Worker         mb.CopyFromAndTruncate(span(kSequentialBytes).first(to_copy));
637*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.status(), OkStatus());
638*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(result.size(), to_copy);
639*61c4878aSAndroid Build Coastguard Worker     ASSERT_EQ(mb.size(), result.size());
640*61c4878aSAndroid Build Coastguard Worker     ASSERT_TRUE(std::equal(mb.begin(), mb.end(), kSequentialBytes.begin()));
641*61c4878aSAndroid Build Coastguard Worker   }
642*61c4878aSAndroid Build Coastguard Worker }
643*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyFromAndTruncateFromOffset)644*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyFromAndTruncateFromOffset) {
645*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
646*61c4878aSAndroid Build Coastguard Worker 
647*61c4878aSAndroid Build Coastguard Worker   static constexpr std::array<std::byte, 6> kZeroes = {};
648*61c4878aSAndroid Build Coastguard Worker 
649*61c4878aSAndroid Build Coastguard Worker   // Sweep offsets 0–6 (inclusive), and copy 0–all bytes for each offset.
650*61c4878aSAndroid Build Coastguard Worker   for (size_t offset = 0; offset <= kSequentialBytes.size(); ++offset) {
651*61c4878aSAndroid Build Coastguard Worker     for (size_t to_copy = 0; to_copy <= kSequentialBytes.size() - offset;
652*61c4878aSAndroid Build Coastguard Worker          ++to_copy) {
653*61c4878aSAndroid Build Coastguard Worker       MultiBuf mb;
654*61c4878aSAndroid Build Coastguard Worker       mb.PushBackChunk(MakeChunk(allocator, 2));
655*61c4878aSAndroid Build Coastguard Worker       mb.PushBackChunk(MakeChunk(allocator, 0));
656*61c4878aSAndroid Build Coastguard Worker       mb.PushBackChunk(MakeChunk(allocator, 3));
657*61c4878aSAndroid Build Coastguard Worker       mb.PushBackChunk(MakeChunk(allocator, 0));
658*61c4878aSAndroid Build Coastguard Worker       mb.PushBackChunk(MakeChunk(allocator, 0));
659*61c4878aSAndroid Build Coastguard Worker       mb.PushBackChunk(MakeChunk(allocator, 1));
660*61c4878aSAndroid Build Coastguard Worker       ASSERT_EQ(mb.size(), kSequentialBytes.size());
661*61c4878aSAndroid Build Coastguard Worker 
662*61c4878aSAndroid Build Coastguard Worker       StatusWithSize result =
663*61c4878aSAndroid Build Coastguard Worker           mb.CopyFromAndTruncate(span(kSequentialBytes).first(to_copy), offset);
664*61c4878aSAndroid Build Coastguard Worker       ASSERT_EQ(result.status(), OkStatus());
665*61c4878aSAndroid Build Coastguard Worker       ASSERT_EQ(result.size(), to_copy);
666*61c4878aSAndroid Build Coastguard Worker       ASSERT_EQ(mb.size(), offset + to_copy);
667*61c4878aSAndroid Build Coastguard Worker 
668*61c4878aSAndroid Build Coastguard Worker       // MultiBuf contains to_copy 0s followed by to_copy sequential bytes.
669*61c4878aSAndroid Build Coastguard Worker       ASSERT_TRUE(std::equal(mb.begin(), mb.begin() + offset, kZeroes.begin()));
670*61c4878aSAndroid Build Coastguard Worker       ASSERT_TRUE(
671*61c4878aSAndroid Build Coastguard Worker           std::equal(mb.begin() + offset, mb.end(), kSequentialBytes.begin()));
672*61c4878aSAndroid Build Coastguard Worker     }
673*61c4878aSAndroid Build Coastguard Worker   }
674*61c4878aSAndroid Build Coastguard Worker }
675*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,CopyFromIntoEmptyMultibuf)676*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, CopyFromIntoEmptyMultibuf) {
677*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
678*61c4878aSAndroid Build Coastguard Worker   MultiBuf mb;
679*61c4878aSAndroid Build Coastguard Worker 
680*61c4878aSAndroid Build Coastguard Worker   StatusWithSize result = mb.CopyFrom({});
681*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status(), OkStatus());  // empty source, so copy succeeded
682*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
683*61c4878aSAndroid Build Coastguard Worker 
684*61c4878aSAndroid Build Coastguard Worker   result = mb.CopyFrom(kSequentialBytes);
685*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status(), Status::ResourceExhausted());
686*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
687*61c4878aSAndroid Build Coastguard Worker 
688*61c4878aSAndroid Build Coastguard Worker   mb.PushBackChunk(MakeChunk(allocator, 0));  // add an empty chunk
689*61c4878aSAndroid Build Coastguard Worker 
690*61c4878aSAndroid Build Coastguard Worker   result = mb.CopyFrom({});
691*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status(), OkStatus());  // empty source, so copy succeeded
692*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
693*61c4878aSAndroid Build Coastguard Worker 
694*61c4878aSAndroid Build Coastguard Worker   result = mb.CopyFrom(kSequentialBytes);
695*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.status(), Status::ResourceExhausted());
696*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(result.size(), 0u);
697*61c4878aSAndroid Build Coastguard Worker }
698*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IsContiguousTrueForEmptyBuffer)699*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IsContiguousTrueForEmptyBuffer) {
700*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
701*61c4878aSAndroid Build Coastguard Worker 
702*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
703*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
704*61c4878aSAndroid Build Coastguard Worker 
705*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
706*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
707*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
708*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
709*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
710*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
711*61c4878aSAndroid Build Coastguard Worker }
712*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IsContiguousTrueForSingleNonEmptyChunk)713*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IsContiguousTrueForSingleNonEmptyChunk) {
714*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
715*61c4878aSAndroid Build Coastguard Worker 
716*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
717*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b}));
718*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
719*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {}));
720*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
721*61c4878aSAndroid Build Coastguard Worker   buf.PushFrontChunk(MakeChunk(allocator, {}));
722*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
723*61c4878aSAndroid Build Coastguard Worker }
724*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,IsContiguousFalseIfMultipleNonEmptyChunks)725*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, IsContiguousFalseIfMultipleNonEmptyChunks) {
726*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
727*61c4878aSAndroid Build Coastguard Worker 
728*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
729*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {1_b}));
730*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, {2_b}));
731*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(buf.IsContiguous());
732*61c4878aSAndroid Build Coastguard Worker }
733*61c4878aSAndroid Build Coastguard Worker 
TEST(MultiBuf,ContiguousSpanAcrossMultipleChunks)734*61c4878aSAndroid Build Coastguard Worker TEST(MultiBuf, ContiguousSpanAcrossMultipleChunks) {
735*61c4878aSAndroid Build Coastguard Worker   AllocatorForTest<kArbitraryAllocatorSize> allocator;
736*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk_1 = MakeChunk(allocator, 10);
737*61c4878aSAndroid Build Coastguard Worker   const ConstByteSpan contiguous_span = chunk_1;
738*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk_2 = chunk_1->TakeSuffix(5).value();
739*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk_3 = chunk_2->TakeSuffix(5).value();
740*61c4878aSAndroid Build Coastguard Worker   OwnedChunk chunk_4 = chunk_3->TakeSuffix(1).value();
741*61c4878aSAndroid Build Coastguard Worker 
742*61c4878aSAndroid Build Coastguard Worker   MultiBuf buf;
743*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(std::move(chunk_1));       // 5 bytes
744*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(std::move(chunk_2));       // 0 bytes
745*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(std::move(chunk_3));       // 4 bytes
746*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(std::move(chunk_4));       // 1 byte
747*61c4878aSAndroid Build Coastguard Worker   buf.PushBackChunk(MakeChunk(allocator, 0));  // empty
748*61c4878aSAndroid Build Coastguard Worker 
749*61c4878aSAndroid Build Coastguard Worker   auto it = buf.Chunks().begin();
750*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ((it++)->size(), 5u);
751*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ((it++)->size(), 0u);
752*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ((it++)->size(), 4u);
753*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ((it++)->size(), 1u);
754*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ((it++)->size(), 0u);
755*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(it, buf.Chunks().end());
756*61c4878aSAndroid Build Coastguard Worker 
757*61c4878aSAndroid Build Coastguard Worker   EXPECT_TRUE(buf.IsContiguous());
758*61c4878aSAndroid Build Coastguard Worker   ByteSpan span = buf.ContiguousSpan().value();
759*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(span.data(), contiguous_span.data());
760*61c4878aSAndroid Build Coastguard Worker   EXPECT_EQ(span.size(), contiguous_span.size());
761*61c4878aSAndroid Build Coastguard Worker 
762*61c4878aSAndroid Build Coastguard Worker   it = buf.Chunks().begin();
763*61c4878aSAndroid Build Coastguard Worker   buf.InsertChunk(++it, MakeChunk(allocator, 1));
764*61c4878aSAndroid Build Coastguard Worker   EXPECT_FALSE(buf.IsContiguous());
765*61c4878aSAndroid Build Coastguard Worker }
766*61c4878aSAndroid Build Coastguard Worker 
767*61c4878aSAndroid Build Coastguard Worker }  // namespace
768*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::multibuf
769