• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // 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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_stream/memory_stream.h"
16 
17 #include "gtest/gtest.h"
18 #include "pw_preprocessor/compiler.h"
19 
20 namespace pw::stream {
21 namespace {
22 
23 // Size of the in-memory buffer to use for this test.
24 constexpr size_t kSinkBufferSize = 1013;
25 
26 struct TestStruct {
27   uint8_t day;
28   uint8_t month;
29   uint16_t year;
30 };
31 
32 constexpr TestStruct kExpectedStruct = {.day = 18, .month = 5, .year = 2020};
33 
34 class MemoryWriterTest : public ::testing::Test {
35  protected:
MemoryWriterTest()36   MemoryWriterTest() : memory_buffer_ {}
37   {}
38   std::array<std::byte, kSinkBufferSize> memory_buffer_;
39 };
40 
TEST_F(MemoryWriterTest,BytesWritten)41 TEST_F(MemoryWriterTest, BytesWritten) {
42   MemoryWriter memory_writer(memory_buffer_);
43   EXPECT_EQ(memory_writer.bytes_written(), 0u);
44   Status status =
45       memory_writer.Write(&kExpectedStruct, sizeof(kExpectedStruct));
46   EXPECT_EQ(status, OkStatus());
47   EXPECT_EQ(memory_writer.bytes_written(), sizeof(kExpectedStruct));
48 }
49 
TEST_F(MemoryWriterTest,BytesWrittenOnConstruction)50 TEST_F(MemoryWriterTest, BytesWrittenOnConstruction) {
51   constexpr size_t bytes_written = kSinkBufferSize / 2;
52   std::memset(memory_buffer_.data(), 1u, bytes_written);
53   MemoryWriter memory_writer(memory_buffer_, bytes_written);
54   EXPECT_EQ(memory_writer.bytes_written(), bytes_written);
55   EXPECT_EQ(memcmp(memory_writer.data(), memory_buffer_.data(), bytes_written),
56             0);
57 }
58 
TEST_F(MemoryWriterTest,ValidateContents)59 TEST_F(MemoryWriterTest, ValidateContents) {
60   MemoryWriter memory_writer(memory_buffer_);
61   EXPECT_TRUE(
62       memory_writer.Write(&kExpectedStruct, sizeof(kExpectedStruct)).ok());
63 
64   std::span<const std::byte> written_data = memory_writer.WrittenData();
65   EXPECT_EQ(written_data.size_bytes(), sizeof(kExpectedStruct));
66   TestStruct temp;
67   std::memcpy(&temp, written_data.data(), written_data.size_bytes());
68   EXPECT_EQ(memcmp(&temp, &kExpectedStruct, sizeof(kExpectedStruct)), 0);
69 }
70 
TEST_F(MemoryWriterTest,MultipleWrites)71 TEST_F(MemoryWriterTest, MultipleWrites) {
72   constexpr size_t kTempBufferSize = 72;
73   std::byte buffer[kTempBufferSize] = {};
74 
75   for (std::byte& value : memory_buffer_) {
76     value = std::byte(0);
77   }
78   MemoryWriter memory_writer(memory_buffer_);
79 
80   size_t counter = 0;
81   while (memory_writer.ConservativeWriteLimit() >= kTempBufferSize) {
82     for (size_t i = 0; i < sizeof(buffer); ++i) {
83       buffer[i] = std::byte(counter++);
84     }
85     EXPECT_EQ(memory_writer.Write(std::span(buffer)), OkStatus());
86   }
87 
88   EXPECT_GT(memory_writer.ConservativeWriteLimit(), 0u);
89   EXPECT_LT(memory_writer.ConservativeWriteLimit(), kTempBufferSize);
90 
91   EXPECT_EQ(memory_writer.Write(std::span(buffer)),
92             Status::ResourceExhausted());
93   EXPECT_EQ(memory_writer.bytes_written(), counter);
94 
95   counter = 0;
96   for (const std::byte& value : memory_writer) {
97     EXPECT_EQ(value, std::byte(counter++));
98   }
99 }
100 
TEST_F(MemoryWriterTest,FullWriter)101 TEST_F(MemoryWriterTest, FullWriter) {
102   constexpr size_t kTempBufferSize = 32;
103   std::byte buffer[kTempBufferSize] = {};
104   const int fill_byte = 0x25;
105   memset(buffer, fill_byte, sizeof(buffer));
106 
107   for (std::byte& value : memory_buffer_) {
108     value = std::byte(0);
109   }
110   MemoryWriter memory_writer(memory_buffer_);
111 
112   while (memory_writer.ConservativeWriteLimit() > 0) {
113     size_t bytes_to_write =
114         std::min(sizeof(buffer), memory_writer.ConservativeWriteLimit());
115     EXPECT_EQ(memory_writer.Write(std::span(buffer, bytes_to_write)),
116               OkStatus());
117   }
118 
119   EXPECT_EQ(memory_writer.ConservativeWriteLimit(), 0u);
120 
121   EXPECT_EQ(memory_writer.Write(std::span(buffer)), Status::OutOfRange());
122   EXPECT_EQ(memory_writer.bytes_written(), memory_buffer_.size());
123 
124   for (const std::byte& value : memory_writer) {
125     EXPECT_EQ(value, std::byte(fill_byte));
126   }
127 }
128 
TEST_F(MemoryWriterTest,EmptyData)129 TEST_F(MemoryWriterTest, EmptyData) {
130   std::byte buffer[5] = {};
131 
132   MemoryWriter memory_writer(memory_buffer_);
133   EXPECT_EQ(memory_writer.Write(buffer, 0), OkStatus());
134   EXPECT_EQ(memory_writer.bytes_written(), 0u);
135 }
136 
TEST_F(MemoryWriterTest,ValidateContents_SingleByteWrites)137 TEST_F(MemoryWriterTest, ValidateContents_SingleByteWrites) {
138   MemoryWriter memory_writer(memory_buffer_);
139   EXPECT_TRUE(memory_writer.Write(std::byte{0x01}).ok());
140   EXPECT_EQ(memory_writer.bytes_written(), 1u);
141   EXPECT_EQ(memory_writer.data()[0], std::byte{0x01});
142 
143   EXPECT_TRUE(memory_writer.Write(std::byte{0x7E}).ok());
144   EXPECT_EQ(memory_writer.bytes_written(), 2u);
145   EXPECT_EQ(memory_writer.data()[1], std::byte{0x7E});
146 }
147 
TEST_F(MemoryWriterTest,OverlappingBuffer)148 TEST_F(MemoryWriterTest, OverlappingBuffer) {
149   constexpr std::string_view kTestString("This is staged into the same buffer");
150   // Write at a five-byte offset from the start of the destination buffer.
151   std::byte* const kOverlappingStart = memory_buffer_.data() + 5;
152   std::memcpy(kOverlappingStart, kTestString.data(), kTestString.size());
153   MemoryWriter memory_writer(memory_buffer_);
154   EXPECT_TRUE(memory_writer.Write(kOverlappingStart, kTestString.size()).ok());
155   EXPECT_TRUE(memory_writer.Write(std::byte(0)).ok());
156   EXPECT_EQ(memory_writer.bytes_written(), kTestString.size() + 1);
157 
158   EXPECT_STREQ(reinterpret_cast<const char*>(memory_writer.data()),
159                kTestString.data());
160 }
161 
TEST_F(MemoryWriterTest,Clear)162 TEST_F(MemoryWriterTest, Clear) {
163   MemoryWriter writer(memory_buffer_);
164   EXPECT_EQ(OkStatus(), writer.Write(std::byte{1}));
165   ASSERT_FALSE(writer.empty());
166   writer.clear();
167   EXPECT_TRUE(writer.empty());
168 
169   EXPECT_EQ(OkStatus(), writer.Write(std::byte{99}));
170   EXPECT_EQ(writer[0], std::byte{99});
171 }
172 
TEST_F(MemoryWriterTest,Seek_To0)173 TEST_F(MemoryWriterTest, Seek_To0) {
174   MemoryWriter writer(memory_buffer_);
175   EXPECT_EQ(OkStatus(), writer.Seek(0));
176 }
177 
TEST_F(MemoryWriterTest,Tell_StartsAt0)178 TEST_F(MemoryWriterTest, Tell_StartsAt0) {
179   MemoryWriter writer(memory_buffer_);
180   EXPECT_EQ(0u, writer.Tell());
181 }
182 
TEST_F(MemoryWriterTest,Tell_UpdatesOnSeek)183 TEST_F(MemoryWriterTest, Tell_UpdatesOnSeek) {
184   MemoryWriter writer(memory_buffer_);
185   ASSERT_EQ(OkStatus(), writer.Seek(2, Stream::kCurrent));
186   EXPECT_EQ(2u, writer.Tell());
187 }
188 
TEST_F(MemoryWriterTest,Tell_UpdatesOnRead)189 TEST_F(MemoryWriterTest, Tell_UpdatesOnRead) {
190   MemoryWriter writer(memory_buffer_);
191   std::byte buffer[4] = {};
192   ASSERT_EQ(OkStatus(), writer.Write(buffer));
193   EXPECT_EQ(4u, writer.Tell());
194 }
195 
196 #define TESTING_CHECK_FAILURES_IS_SUPPORTED 0
197 #if TESTING_CHECK_FAILURES_IS_SUPPORTED
198 
199 // TODO(amontanez): Ensure that this test triggers an assert.
TEST_F(MemoryWriterTest,NullPointer)200 TEST_F(MemoryWriterTest, NullPointer) {
201   MemoryWriter memory_writer(memory_buffer_);
202   memory_writer.Write(nullptr, 21);
203 }
204 
205 // TODO(davidrogers): Ensure that this test triggers an assert.
TEST(MemoryReader,NullSpan)206 TEST(MemoryReader, NullSpan) {
207   std::byte memory_buffer[32];
208   ByteSpan dest(nullptr, 5);
209   MemoryReader memory_reader(memory_buffer);
210   memory_reader.Read(dest);
211 }
212 
213 // TODO(davidrogers): Ensure that this test triggers an assert.
TEST(MemoryReader,NullPointer)214 TEST(MemoryReader, NullPointer) {
215   std::byte memory_buffer[32];
216   MemoryReader memory_reader(memory_buffer);
217   memory_reader.Read(nullptr, 21);
218 }
219 
220 #endif  // TESTING_CHECK_FAILURES_IS_SUPPORTED
221 
TEST(MemoryReader,SingleFullRead)222 TEST(MemoryReader, SingleFullRead) {
223   constexpr size_t kTempBufferSize = 32;
224 
225   std::array<std::byte, kTempBufferSize> source;
226   std::array<std::byte, kTempBufferSize> dest;
227 
228   uint8_t counter = 0;
229   for (std::byte& value : source) {
230     value = std::byte(counter++);
231   }
232 
233   MemoryReader memory_reader(source);
234 
235   // Read exactly the available bytes.
236   EXPECT_EQ(memory_reader.ConservativeReadLimit(), dest.size());
237   Result<ByteSpan> result = memory_reader.Read(dest);
238   EXPECT_EQ(result.status(), OkStatus());
239   EXPECT_EQ(result.value().size_bytes(), dest.size());
240 
241   ASSERT_EQ(source.size(), result.value().size_bytes());
242   for (size_t i = 0; i < source.size(); i++) {
243     EXPECT_EQ(source[i], result.value()[i]);
244   }
245 
246   // Shoud be no byte remaining.
247   EXPECT_EQ(memory_reader.ConservativeReadLimit(), 0u);
248   result = memory_reader.Read(dest);
249   EXPECT_EQ(result.status(), Status::OutOfRange());
250 }
251 
TEST(MemoryReader,EmptySpanRead)252 TEST(MemoryReader, EmptySpanRead) {
253   constexpr size_t kTempBufferSize = 32;
254   std::array<std::byte, kTempBufferSize> source;
255 
256   // Use a span with nullptr and zero length;
257   ByteSpan dest(nullptr, 0);
258   EXPECT_EQ(dest.size_bytes(), 0u);
259 
260   MemoryReader memory_reader(source);
261 
262   // Read exactly the available bytes.
263   Result<ByteSpan> result = memory_reader.Read(dest);
264   EXPECT_EQ(result.status(), OkStatus());
265   EXPECT_EQ(result.value().size_bytes(), 0u);
266   EXPECT_EQ(result.value().data(), dest.data());
267 
268   // Shoud be original bytes remaining.
269   EXPECT_EQ(memory_reader.ConservativeReadLimit(), source.size());
270 }
271 
TEST(MemoryReader,SinglePartialRead)272 TEST(MemoryReader, SinglePartialRead) {
273   constexpr size_t kTempBufferSize = 32;
274   std::array<std::byte, kTempBufferSize> source;
275   std::array<std::byte, kTempBufferSize * 2> dest;
276 
277   uint8_t counter = 0;
278   for (std::byte& value : source) {
279     value = std::byte(counter++);
280   }
281 
282   MemoryReader memory_reader(source);
283 
284   // Try and read double the bytes available. Use the pointer/size version of
285   // the API.
286   Result<ByteSpan> result = memory_reader.Read(dest.data(), dest.size());
287   EXPECT_EQ(result.status(), OkStatus());
288   EXPECT_EQ(result.value().size_bytes(), source.size());
289 
290   ASSERT_EQ(source.size(), result.value().size_bytes());
291   for (size_t i = 0; i < source.size(); i++) {
292     EXPECT_EQ(source[i], result.value()[i]);
293   }
294 
295   // Shoud be no byte remaining.
296   EXPECT_EQ(memory_reader.ConservativeReadLimit(), 0u);
297   result = memory_reader.Read(dest);
298   EXPECT_EQ(result.status(), Status::OutOfRange());
299 }
300 
TEST(MemoryReader,MultipleReads)301 TEST(MemoryReader, MultipleReads) {
302   constexpr size_t kTempBufferSize = 32;
303 
304   std::array<std::byte, kTempBufferSize * 5> source;
305   std::array<std::byte, kTempBufferSize> dest;
306 
307   uint8_t counter = 0;
308 
309   for (std::byte& value : source) {
310     value = std::byte(counter++);
311   }
312 
313   MemoryReader memory_reader(source);
314 
315   size_t source_chunk_base = 0;
316 
317   while (memory_reader.ConservativeReadLimit() > 0) {
318     size_t read_limit = memory_reader.ConservativeReadLimit();
319 
320     // Try and read a chunk of bytes.
321     Result<ByteSpan> result = memory_reader.Read(dest);
322     EXPECT_EQ(result.status(), OkStatus());
323     EXPECT_EQ(result.value().size_bytes(), dest.size());
324     EXPECT_EQ(memory_reader.ConservativeReadLimit(),
325               read_limit - result.value().size_bytes());
326 
327     // Verify the chunk of byte that was read.
328     for (size_t i = 0; i < result.value().size_bytes(); i++) {
329       EXPECT_EQ(source[source_chunk_base + i], result.value()[i]);
330     }
331     source_chunk_base += result.value().size_bytes();
332   }
333 }
334 
TEST(MemoryReader,Seek)335 TEST(MemoryReader, Seek) {
336   constexpr std::string_view data = "0123456789";
337   MemoryReader reader(std::as_bytes(std::span(data)));
338 
339   char buffer[5] = {};  // Leave a null terminator at the end.
340   ASSERT_EQ(OkStatus(), reader.Read(buffer, sizeof(buffer) - 1).status());
341   EXPECT_STREQ(buffer, "0123");
342 
343   ASSERT_EQ(OkStatus(), reader.Seek(1));
344   ASSERT_EQ(OkStatus(), reader.Read(buffer, sizeof(buffer) - 1).status());
345   EXPECT_STREQ(buffer, "1234");
346 
347   ASSERT_EQ(OkStatus(), reader.Seek(0));
348   ASSERT_EQ(OkStatus(), reader.Read(buffer, sizeof(buffer) - 1).status());
349   EXPECT_STREQ(buffer, "0123");
350 }
351 
TEST(MemoryReader,Tell_StartsAt0)352 TEST(MemoryReader, Tell_StartsAt0) {
353   MemoryReader reader(std::as_bytes(std::span("\3\2\1")));
354   EXPECT_EQ(0u, reader.Tell());
355 }
356 
TEST(MemoryReader,Tell_UpdatesOnSeek)357 TEST(MemoryReader, Tell_UpdatesOnSeek) {
358   MemoryReader reader(std::as_bytes(std::span("\3\2\1")));
359   ASSERT_EQ(OkStatus(), reader.Seek(2, Stream::kCurrent));
360   EXPECT_EQ(2u, reader.Tell());
361 }
362 
TEST(MemoryReader,Tell_UpdatesOnRead)363 TEST(MemoryReader, Tell_UpdatesOnRead) {
364   MemoryReader reader(std::as_bytes(std::span("\3\2\1")));
365   std::byte buffer[4];
366   ASSERT_EQ(OkStatus(), reader.Read(buffer).status());
367   EXPECT_EQ(4u, reader.Tell());
368 }
369 
370 }  // namespace
371 }  // namespace pw::stream
372