1*07fb1d06SElliott Hughes // Copyright 2017 The ChromiumOS Authors
2*07fb1d06SElliott Hughes // Use of this source code is governed by a BSD-style license that can be
3*07fb1d06SElliott Hughes // found in the LICENSE file.
4*07fb1d06SElliott Hughes
5*07fb1d06SElliott Hughes #include "gtest/gtest.h"
6*07fb1d06SElliott Hughes
7*07fb1d06SElliott Hughes #include "puffin/src/puff_reader.h"
8*07fb1d06SElliott Hughes #include "puffin/src/puff_writer.h"
9*07fb1d06SElliott Hughes #include "puffin/src/unittest_common.h"
10*07fb1d06SElliott Hughes
11*07fb1d06SElliott Hughes namespace puffin {
12*07fb1d06SElliott Hughes
13*07fb1d06SElliott Hughes namespace {
TestLiteralLength(size_t length)14*07fb1d06SElliott Hughes void TestLiteralLength(size_t length) {
15*07fb1d06SElliott Hughes Buffer buf(length + 10);
16*07fb1d06SElliott Hughes PuffData pd;
17*07fb1d06SElliott Hughes
18*07fb1d06SElliott Hughes BufferPuffWriter pw(buf.data(), buf.size());
19*07fb1d06SElliott Hughes // We need to insert a metadata otherwise it will fail.
20*07fb1d06SElliott Hughes pd.type = PuffData::Type::kBlockMetadata;
21*07fb1d06SElliott Hughes pd.length = 1;
22*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
23*07fb1d06SElliott Hughes
24*07fb1d06SElliott Hughes BufferPuffReader pr(buf.data(), buf.size());
25*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
26*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
27*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 1);
28*07fb1d06SElliott Hughes
29*07fb1d06SElliott Hughes // We insert |length| bytes.
30*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLiterals;
31*07fb1d06SElliott Hughes pd.length = length;
32*07fb1d06SElliott Hughes pd.read_fn = [](uint8_t* buffer, size_t count) {
33*07fb1d06SElliott Hughes std::fill(buffer, buffer + count, 10);
34*07fb1d06SElliott Hughes return true;
35*07fb1d06SElliott Hughes };
36*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
37*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
38*07fb1d06SElliott Hughes
39*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLenDist;
40*07fb1d06SElliott Hughes pd.distance = 1;
41*07fb1d06SElliott Hughes pd.length = 3;
42*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
43*07fb1d06SElliott Hughes
44*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
45*07fb1d06SElliott Hughes if (length == 0) {
46*07fb1d06SElliott Hughes // If length is zero, then nothing should've been inserted.
47*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
48*07fb1d06SElliott Hughes } else {
49*07fb1d06SElliott Hughes // We have to see |length| bytes.
50*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
51*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, length);
52*07fb1d06SElliott Hughes for (size_t i = 0; i < pd.length; i++) {
53*07fb1d06SElliott Hughes uint8_t byte;
54*07fb1d06SElliott Hughes pd.read_fn(&byte, 1);
55*07fb1d06SElliott Hughes EXPECT_EQ(byte, 10);
56*07fb1d06SElliott Hughes }
57*07fb1d06SElliott Hughes }
58*07fb1d06SElliott Hughes }
59*07fb1d06SElliott Hughes } // namespace
60*07fb1d06SElliott Hughes
61*07fb1d06SElliott Hughes // Testing read/write from/into a puff buffer using |PuffReader|/|PuffWriter|.
TEST(PuffIOTest,InputOutputTest)62*07fb1d06SElliott Hughes TEST(PuffIOTest, InputOutputTest) {
63*07fb1d06SElliott Hughes Buffer buf(100);
64*07fb1d06SElliott Hughes BufferPuffReader pr(buf.data(), buf.size());
65*07fb1d06SElliott Hughes BufferPuffWriter pw(buf.data(), buf.size());
66*07fb1d06SElliott Hughes BufferPuffWriter epw(nullptr, 0);
67*07fb1d06SElliott Hughes uint8_t block = 123;
68*07fb1d06SElliott Hughes
69*07fb1d06SElliott Hughes {
70*07fb1d06SElliott Hughes PuffData pd;
71*07fb1d06SElliott Hughes pd.type = PuffData::Type::kBlockMetadata;
72*07fb1d06SElliott Hughes pd.block_metadata[0] = 0xCC; // header
73*07fb1d06SElliott Hughes memcpy(&pd.block_metadata[1], &block, sizeof(block));
74*07fb1d06SElliott Hughes pd.length = sizeof(block) + 1;
75*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
76*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
77*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
78*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
79*07fb1d06SElliott Hughes }
80*07fb1d06SElliott Hughes {
81*07fb1d06SElliott Hughes PuffData pd;
82*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
83*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
84*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, sizeof(block) + 1);
85*07fb1d06SElliott Hughes ASSERT_EQ(pd.block_metadata[0], 0xCC);
86*07fb1d06SElliott Hughes ASSERT_EQ(pd.block_metadata[1], block);
87*07fb1d06SElliott Hughes }
88*07fb1d06SElliott Hughes {
89*07fb1d06SElliott Hughes PuffData pd;
90*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLenDist;
91*07fb1d06SElliott Hughes pd.distance = 321;
92*07fb1d06SElliott Hughes pd.length = 3;
93*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
94*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
95*07fb1d06SElliott Hughes pd.length = 127;
96*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
97*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
98*07fb1d06SElliott Hughes pd.length = 258;
99*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
100*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
101*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
102*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
103*07fb1d06SElliott Hughes
104*07fb1d06SElliott Hughes pd.length = 259;
105*07fb1d06SElliott Hughes ASSERT_FALSE(pw.Insert(pd));
106*07fb1d06SElliott Hughes ASSERT_FALSE(epw.Insert(pd));
107*07fb1d06SElliott Hughes }
108*07fb1d06SElliott Hughes {
109*07fb1d06SElliott Hughes PuffData pd;
110*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
111*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
112*07fb1d06SElliott Hughes ASSERT_EQ(pd.distance, 321);
113*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 3);
114*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
115*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
116*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 127);
117*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
118*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLenDist);
119*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 258);
120*07fb1d06SElliott Hughes }
121*07fb1d06SElliott Hughes {
122*07fb1d06SElliott Hughes PuffData pd;
123*07fb1d06SElliott Hughes pd.type = PuffData::Type::kEndOfBlock;
124*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
125*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
126*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
127*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
128*07fb1d06SElliott Hughes }
129*07fb1d06SElliott Hughes {
130*07fb1d06SElliott Hughes PuffData pd;
131*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
132*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kEndOfBlock);
133*07fb1d06SElliott Hughes }
134*07fb1d06SElliott Hughes {
135*07fb1d06SElliott Hughes PuffData pd;
136*07fb1d06SElliott Hughes pd.type = PuffData::Type::kBlockMetadata;
137*07fb1d06SElliott Hughes block = 123;
138*07fb1d06SElliott Hughes pd.block_metadata[0] = 0xCC; // header
139*07fb1d06SElliott Hughes memcpy(&pd.block_metadata[1], &block, sizeof(block));
140*07fb1d06SElliott Hughes pd.length = sizeof(block) + 1;
141*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
142*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
143*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
144*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
145*07fb1d06SElliott Hughes }
146*07fb1d06SElliott Hughes {
147*07fb1d06SElliott Hughes PuffData pd;
148*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
149*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
150*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, sizeof(block) + 1);
151*07fb1d06SElliott Hughes ASSERT_EQ(pd.block_metadata[0], 0xCC);
152*07fb1d06SElliott Hughes ASSERT_EQ(pd.block_metadata[1], block);
153*07fb1d06SElliott Hughes }
154*07fb1d06SElliott Hughes
155*07fb1d06SElliott Hughes uint8_t tmp[] = {1, 2, 100};
156*07fb1d06SElliott Hughes {
157*07fb1d06SElliott Hughes PuffData pd;
158*07fb1d06SElliott Hughes size_t index = 0;
159*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLiterals;
160*07fb1d06SElliott Hughes pd.length = 3;
161*07fb1d06SElliott Hughes pd.read_fn = [&tmp, &index](uint8_t* buffer, size_t count) {
162*07fb1d06SElliott Hughes if (count > 3 - index)
163*07fb1d06SElliott Hughes return false;
164*07fb1d06SElliott Hughes if (buffer != nullptr) {
165*07fb1d06SElliott Hughes memcpy(buffer, &tmp[index], count);
166*07fb1d06SElliott Hughes }
167*07fb1d06SElliott Hughes index += count;
168*07fb1d06SElliott Hughes return true;
169*07fb1d06SElliott Hughes };
170*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
171*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
172*07fb1d06SElliott Hughes // We have to refresh the read_fn function for the second insert.
173*07fb1d06SElliott Hughes index = 0;
174*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
175*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
176*07fb1d06SElliott Hughes }
177*07fb1d06SElliott Hughes {
178*07fb1d06SElliott Hughes PuffData pd;
179*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLiteral;
180*07fb1d06SElliott Hughes pd.byte = 10;
181*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
182*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
183*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
184*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
185*07fb1d06SElliott Hughes }
186*07fb1d06SElliott Hughes
187*07fb1d06SElliott Hughes uint8_t tmp3[3];
188*07fb1d06SElliott Hughes {
189*07fb1d06SElliott Hughes PuffData pd;
190*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
191*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
192*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 3);
193*07fb1d06SElliott Hughes ASSERT_TRUE(pd.read_fn(tmp3, 3));
194*07fb1d06SElliott Hughes ASSERT_FALSE(pd.read_fn(tmp3, 1));
195*07fb1d06SElliott Hughes ASSERT_EQ(0, memcmp(tmp3, tmp, 3));
196*07fb1d06SElliott Hughes }
197*07fb1d06SElliott Hughes {
198*07fb1d06SElliott Hughes PuffData pd;
199*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
200*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
201*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 1);
202*07fb1d06SElliott Hughes ASSERT_TRUE(pd.read_fn(tmp3, 1));
203*07fb1d06SElliott Hughes ASSERT_EQ(tmp3[0], 10);
204*07fb1d06SElliott Hughes ASSERT_FALSE(pd.read_fn(tmp3, 2));
205*07fb1d06SElliott Hughes }
206*07fb1d06SElliott Hughes {
207*07fb1d06SElliott Hughes PuffData pd;
208*07fb1d06SElliott Hughes pd.type = PuffData::Type::kEndOfBlock;
209*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
210*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Insert(pd));
211*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
212*07fb1d06SElliott Hughes ASSERT_TRUE(epw.Flush());
213*07fb1d06SElliott Hughes }
214*07fb1d06SElliott Hughes {
215*07fb1d06SElliott Hughes PuffData pd;
216*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
217*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kEndOfBlock);
218*07fb1d06SElliott Hughes }
219*07fb1d06SElliott Hughes
220*07fb1d06SElliott Hughes ASSERT_EQ(buf.size() - pr.BytesLeft(), pw.Size());
221*07fb1d06SElliott Hughes ASSERT_EQ(buf.size() - pr.BytesLeft(), epw.Size());
222*07fb1d06SElliott Hughes }
223*07fb1d06SElliott Hughes
224*07fb1d06SElliott Hughes // Testing metadata boundary.
TEST(PuffIOTest,MetadataBoundaryTest)225*07fb1d06SElliott Hughes TEST(PuffIOTest, MetadataBoundaryTest) {
226*07fb1d06SElliott Hughes PuffData pd;
227*07fb1d06SElliott Hughes Buffer buf(3);
228*07fb1d06SElliott Hughes BufferPuffWriter pw(buf.data(), buf.size());
229*07fb1d06SElliott Hughes
230*07fb1d06SElliott Hughes // Block metadata takes two + varied bytes, so on a thre byte buffer, only one
231*07fb1d06SElliott Hughes // bytes is left for the varied part of metadata.
232*07fb1d06SElliott Hughes pd.type = PuffData::Type::kBlockMetadata;
233*07fb1d06SElliott Hughes pd.length = 2;
234*07fb1d06SElliott Hughes ASSERT_FALSE(pw.Insert(pd));
235*07fb1d06SElliott Hughes pd.length = 0; // length should be at least 1.
236*07fb1d06SElliott Hughes ASSERT_FALSE(pw.Insert(pd));
237*07fb1d06SElliott Hughes pd.length = 1;
238*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
239*07fb1d06SElliott Hughes
240*07fb1d06SElliott Hughes Buffer puff_buffer = {0x00, 0x03, 0x02, 0x00, 0x00};
241*07fb1d06SElliott Hughes BufferPuffReader pr(puff_buffer.data(), puff_buffer.size());
242*07fb1d06SElliott Hughes ASSERT_FALSE(pr.GetNext(&pd));
243*07fb1d06SElliott Hughes }
244*07fb1d06SElliott Hughes
TEST(PuffIOTest,InvalidCopyLengthsDistanceTest)245*07fb1d06SElliott Hughes TEST(PuffIOTest, InvalidCopyLengthsDistanceTest) {
246*07fb1d06SElliott Hughes PuffData pd;
247*07fb1d06SElliott Hughes Buffer puff_buffer(20);
248*07fb1d06SElliott Hughes BufferPuffWriter pw(puff_buffer.data(), puff_buffer.size());
249*07fb1d06SElliott Hughes
250*07fb1d06SElliott Hughes // Invalid Lenght values.
251*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLenDist;
252*07fb1d06SElliott Hughes pd.distance = 1;
253*07fb1d06SElliott Hughes pd.length = 0;
254*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
255*07fb1d06SElliott Hughes pd.length = 1;
256*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
257*07fb1d06SElliott Hughes pd.length = 2;
258*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
259*07fb1d06SElliott Hughes pd.length = 3;
260*07fb1d06SElliott Hughes EXPECT_TRUE(pw.Insert(pd));
261*07fb1d06SElliott Hughes pd.length = 259;
262*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
263*07fb1d06SElliott Hughes pd.length = 258;
264*07fb1d06SElliott Hughes EXPECT_TRUE(pw.Insert(pd));
265*07fb1d06SElliott Hughes
266*07fb1d06SElliott Hughes // Invalid distance values.
267*07fb1d06SElliott Hughes pd.length = 3;
268*07fb1d06SElliott Hughes pd.distance = 0;
269*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
270*07fb1d06SElliott Hughes pd.distance = 1;
271*07fb1d06SElliott Hughes EXPECT_TRUE(pw.Insert(pd));
272*07fb1d06SElliott Hughes pd.distance = 32769;
273*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
274*07fb1d06SElliott Hughes pd.distance = 32768;
275*07fb1d06SElliott Hughes EXPECT_TRUE(pw.Insert(pd));
276*07fb1d06SElliott Hughes
277*07fb1d06SElliott Hughes // First three bytes header, four bytes value lit/len, and four bytes
278*07fb1d06SElliott Hughes // invalid lit/len.
279*07fb1d06SElliott Hughes puff_buffer = {0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00,
280*07fb1d06SElliott Hughes 0x00, 0xFF, 0x82, 0x00, 0x00};
281*07fb1d06SElliott Hughes BufferPuffReader pr(puff_buffer.data(), puff_buffer.size());
282*07fb1d06SElliott Hughes EXPECT_TRUE(pr.GetNext(&pd));
283*07fb1d06SElliott Hughes EXPECT_EQ(pd.type, PuffData::Type::kBlockMetadata);
284*07fb1d06SElliott Hughes EXPECT_TRUE(pr.GetNext(&pd));
285*07fb1d06SElliott Hughes EXPECT_EQ(pd.type, PuffData::Type::kLenDist);
286*07fb1d06SElliott Hughes EXPECT_FALSE(pr.GetNext(&pd));
287*07fb1d06SElliott Hughes }
288*07fb1d06SElliott Hughes
TEST(PuffIOTest,InvalidCopyLenghtDistanceBoundaryTest)289*07fb1d06SElliott Hughes TEST(PuffIOTest, InvalidCopyLenghtDistanceBoundaryTest) {
290*07fb1d06SElliott Hughes PuffData pd;
291*07fb1d06SElliott Hughes Buffer puff_buffer(5);
292*07fb1d06SElliott Hughes
293*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLenDist;
294*07fb1d06SElliott Hughes pd.distance = 1;
295*07fb1d06SElliott Hughes pd.length = 129;
296*07fb1d06SElliott Hughes for (size_t i = 1; i < 2; i++) {
297*07fb1d06SElliott Hughes BufferPuffWriter pw(puff_buffer.data(), i);
298*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
299*07fb1d06SElliott Hughes }
300*07fb1d06SElliott Hughes
301*07fb1d06SElliott Hughes pd.length = 130;
302*07fb1d06SElliott Hughes for (size_t i = 1; i < 3; i++) {
303*07fb1d06SElliott Hughes BufferPuffWriter pw(puff_buffer.data(), i);
304*07fb1d06SElliott Hughes EXPECT_FALSE(pw.Insert(pd));
305*07fb1d06SElliott Hughes }
306*07fb1d06SElliott Hughes
307*07fb1d06SElliott Hughes // First three bytes header, three bytes value lit/len.
308*07fb1d06SElliott Hughes puff_buffer = {0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00};
309*07fb1d06SElliott Hughes BufferPuffReader pr(puff_buffer.data(), puff_buffer.size());
310*07fb1d06SElliott Hughes EXPECT_TRUE(pr.GetNext(&pd));
311*07fb1d06SElliott Hughes EXPECT_EQ(pd.type, PuffData::Type::kBlockMetadata);
312*07fb1d06SElliott Hughes EXPECT_FALSE(pr.GetNext(&pd));
313*07fb1d06SElliott Hughes }
314*07fb1d06SElliott Hughes
TEST(PuffIOTest,LiteralsTest)315*07fb1d06SElliott Hughes TEST(PuffIOTest, LiteralsTest) {
316*07fb1d06SElliott Hughes TestLiteralLength(0);
317*07fb1d06SElliott Hughes TestLiteralLength(1);
318*07fb1d06SElliott Hughes TestLiteralLength(2);
319*07fb1d06SElliott Hughes TestLiteralLength(126);
320*07fb1d06SElliott Hughes TestLiteralLength(127);
321*07fb1d06SElliott Hughes TestLiteralLength(128);
322*07fb1d06SElliott Hughes }
323*07fb1d06SElliott Hughes
324*07fb1d06SElliott Hughes // Testing maximum literals length.
TEST(PuffIOTest,MaxLiteralsTest)325*07fb1d06SElliott Hughes TEST(PuffIOTest, MaxLiteralsTest) {
326*07fb1d06SElliott Hughes Buffer buf((1 << 16) + 127 + 20);
327*07fb1d06SElliott Hughes PuffData pd;
328*07fb1d06SElliott Hughes
329*07fb1d06SElliott Hughes BufferPuffWriter pw(buf.data(), buf.size());
330*07fb1d06SElliott Hughes // We need to insert a metadata otherwise it will fail.
331*07fb1d06SElliott Hughes pd.type = PuffData::Type::kBlockMetadata;
332*07fb1d06SElliott Hughes pd.length = 1;
333*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
334*07fb1d06SElliott Hughes
335*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLiterals;
336*07fb1d06SElliott Hughes pd.length = (1 << 16);
337*07fb1d06SElliott Hughes pd.read_fn = [](uint8_t* buffer, size_t count) {
338*07fb1d06SElliott Hughes std::fill(buffer, buffer + count, 10);
339*07fb1d06SElliott Hughes return true;
340*07fb1d06SElliott Hughes };
341*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Insert(pd));
342*07fb1d06SElliott Hughes ASSERT_TRUE(pw.Flush());
343*07fb1d06SElliott Hughes
344*07fb1d06SElliott Hughes BufferPuffReader pr(buf.data(), buf.size());
345*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
346*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
347*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 1);
348*07fb1d06SElliott Hughes
349*07fb1d06SElliott Hughes ASSERT_TRUE(pr.GetNext(&pd));
350*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
351*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 1 << 16);
352*07fb1d06SElliott Hughes for (size_t i = 0; i < pd.length; i++) {
353*07fb1d06SElliott Hughes uint8_t byte;
354*07fb1d06SElliott Hughes pd.read_fn(&byte, 1);
355*07fb1d06SElliott Hughes ASSERT_EQ(byte, 10);
356*07fb1d06SElliott Hughes }
357*07fb1d06SElliott Hughes
358*07fb1d06SElliott Hughes BufferPuffWriter pw2(buf.data(), buf.size());
359*07fb1d06SElliott Hughes pd.type = PuffData::Type::kBlockMetadata;
360*07fb1d06SElliott Hughes pd.length = 1;
361*07fb1d06SElliott Hughes ASSERT_TRUE(pw2.Insert(pd));
362*07fb1d06SElliott Hughes
363*07fb1d06SElliott Hughes pd.type = PuffData::Type::kLiteral;
364*07fb1d06SElliott Hughes pd.length = 1;
365*07fb1d06SElliott Hughes pd.byte = 12;
366*07fb1d06SElliott Hughes // We have to be able to fill 65663 bytes.
367*07fb1d06SElliott Hughes for (size_t i = 0; i < ((1 << 16) + 127); i++) {
368*07fb1d06SElliott Hughes ASSERT_TRUE(pw2.Insert(pd));
369*07fb1d06SElliott Hughes }
370*07fb1d06SElliott Hughes // If we add one more, then it should have been flushed.
371*07fb1d06SElliott Hughes pd.byte = 13;
372*07fb1d06SElliott Hughes ASSERT_TRUE(pw2.Insert(pd));
373*07fb1d06SElliott Hughes ASSERT_TRUE(pw2.Flush());
374*07fb1d06SElliott Hughes
375*07fb1d06SElliott Hughes // Now read it back.
376*07fb1d06SElliott Hughes BufferPuffReader pr2(buf.data(), buf.size());
377*07fb1d06SElliott Hughes ASSERT_TRUE(pr2.GetNext(&pd));
378*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kBlockMetadata);
379*07fb1d06SElliott Hughes
380*07fb1d06SElliott Hughes // Now we should read on kLiterals with lenght 1 << 16 and just one literal
381*07fb1d06SElliott Hughes // after that.
382*07fb1d06SElliott Hughes ASSERT_TRUE(pr2.GetNext(&pd));
383*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
384*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, (1 << 16) + 127);
385*07fb1d06SElliott Hughes for (size_t i = 0; i < pd.length; i++) {
386*07fb1d06SElliott Hughes uint8_t byte;
387*07fb1d06SElliott Hughes pd.read_fn(&byte, 1);
388*07fb1d06SElliott Hughes ASSERT_EQ(byte, 12);
389*07fb1d06SElliott Hughes }
390*07fb1d06SElliott Hughes
391*07fb1d06SElliott Hughes ASSERT_TRUE(pr2.GetNext(&pd));
392*07fb1d06SElliott Hughes ASSERT_EQ(pd.type, PuffData::Type::kLiterals);
393*07fb1d06SElliott Hughes ASSERT_EQ(pd.length, 1);
394*07fb1d06SElliott Hughes uint8_t byte;
395*07fb1d06SElliott Hughes pd.read_fn(&byte, 1);
396*07fb1d06SElliott Hughes ASSERT_EQ(byte, 13);
397*07fb1d06SElliott Hughes }
398*07fb1d06SElliott Hughes
399*07fb1d06SElliott Hughes } // namespace puffin
400