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