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 std::array<std::byte, kSinkBufferSize> memory_buffer;
35
TEST(MemoryWriter,BytesWritten)36 TEST(MemoryWriter, BytesWritten) {
37 MemoryWriter memory_writer(memory_buffer);
38 EXPECT_EQ(memory_writer.bytes_written(), 0u);
39 Status status =
40 memory_writer.Write(&kExpectedStruct, sizeof(kExpectedStruct));
41 EXPECT_EQ(status, OkStatus());
42 EXPECT_EQ(memory_writer.bytes_written(), sizeof(kExpectedStruct));
43 } // namespace
44
TEST(MemoryWriter,ValidateContents)45 TEST(MemoryWriter, ValidateContents) {
46 MemoryWriter memory_writer(memory_buffer);
47 EXPECT_TRUE(
48 memory_writer.Write(&kExpectedStruct, sizeof(kExpectedStruct)).ok());
49
50 std::span<const std::byte> written_data = memory_writer.WrittenData();
51 EXPECT_EQ(written_data.size_bytes(), sizeof(kExpectedStruct));
52 TestStruct temp;
53 std::memcpy(&temp, written_data.data(), written_data.size_bytes());
54 EXPECT_EQ(memcmp(&temp, &kExpectedStruct, sizeof(kExpectedStruct)), 0);
55 }
56
TEST(MemoryWriter,MultipleWrites)57 TEST(MemoryWriter, MultipleWrites) {
58 constexpr size_t kTempBufferSize = 72;
59 std::byte buffer[kTempBufferSize] = {};
60
61 for (std::byte& value : memory_buffer) {
62 value = std::byte(0);
63 }
64 MemoryWriter memory_writer(memory_buffer);
65
66 size_t counter = 0;
67 while (memory_writer.ConservativeWriteLimit() >= kTempBufferSize) {
68 for (size_t i = 0; i < sizeof(buffer); ++i) {
69 buffer[i] = std::byte(counter++);
70 }
71 EXPECT_EQ(memory_writer.Write(std::span(buffer)), OkStatus());
72 }
73
74 EXPECT_GT(memory_writer.ConservativeWriteLimit(), 0u);
75 EXPECT_LT(memory_writer.ConservativeWriteLimit(), kTempBufferSize);
76
77 EXPECT_EQ(memory_writer.Write(std::span(buffer)),
78 Status::ResourceExhausted());
79 EXPECT_EQ(memory_writer.bytes_written(), counter);
80
81 counter = 0;
82 for (const std::byte& value : memory_writer.WrittenData()) {
83 EXPECT_EQ(value, std::byte(counter++));
84 }
85 }
86
TEST(MemoryWriter,FullWriter)87 TEST(MemoryWriter, FullWriter) {
88 constexpr size_t kTempBufferSize = 32;
89 std::byte buffer[kTempBufferSize] = {};
90 const int fill_byte = 0x25;
91 memset(buffer, fill_byte, sizeof(buffer));
92
93 for (std::byte& value : memory_buffer) {
94 value = std::byte(0);
95 }
96 MemoryWriter memory_writer(memory_buffer);
97
98 while (memory_writer.ConservativeWriteLimit() > 0) {
99 size_t bytes_to_write =
100 std::min(sizeof(buffer), memory_writer.ConservativeWriteLimit());
101 EXPECT_EQ(memory_writer.Write(std::span(buffer, bytes_to_write)),
102 OkStatus());
103 }
104
105 EXPECT_EQ(memory_writer.ConservativeWriteLimit(), 0u);
106
107 EXPECT_EQ(memory_writer.Write(std::span(buffer)), Status::OutOfRange());
108 EXPECT_EQ(memory_writer.bytes_written(), memory_buffer.size());
109
110 for (const std::byte& value : memory_writer.WrittenData()) {
111 EXPECT_EQ(value, std::byte(fill_byte));
112 }
113 }
114
TEST(MemoryWriter,EmptyData)115 TEST(MemoryWriter, EmptyData) {
116 std::byte buffer[5] = {};
117
118 MemoryWriter memory_writer(memory_buffer);
119 EXPECT_EQ(memory_writer.Write(buffer, 0), OkStatus());
120 EXPECT_EQ(memory_writer.bytes_written(), 0u);
121 }
122
TEST(MemoryWriter,ValidateContents_SingleByteWrites)123 TEST(MemoryWriter, ValidateContents_SingleByteWrites) {
124 MemoryWriter memory_writer(memory_buffer);
125 EXPECT_TRUE(memory_writer.Write(std::byte{0x01}).ok());
126 EXPECT_EQ(memory_writer.bytes_written(), 1u);
127 EXPECT_EQ(memory_writer.data()[0], std::byte{0x01});
128
129 EXPECT_TRUE(memory_writer.Write(std::byte{0x7E}).ok());
130 EXPECT_EQ(memory_writer.bytes_written(), 2u);
131 EXPECT_EQ(memory_writer.data()[1], std::byte{0x7E});
132 }
133
134 #define TESTING_CHECK_FAILURES_IS_SUPPORTED 0
135 #if TESTING_CHECK_FAILURES_IS_SUPPORTED
136
137 // TODO(amontanez): Ensure that this test triggers an assert.
TEST(MemoryWriter,NullPointer)138 TEST(MemoryWriter, NullPointer) {
139 MemoryWriter memory_writer(memory_buffer);
140 memory_writer.Write(nullptr, 21);
141 }
142
143 // TODO(davidrogers): Ensure that this test triggers an assert.
TEST(MemoryReader,NullSpan)144 TEST(MemoryReader, NullSpan) {
145 ByteSpan dest(nullptr, 5);
146 MemoryReader memory_reader(memory_buffer);
147 memory_reader.Read(dest);
148 }
149
150 // TODO(davidrogers): Ensure that this test triggers an assert.
TEST(MemoryReader,NullPointer)151 TEST(MemoryReader, NullPointer) {
152 MemoryReader memory_reader(memory_buffer);
153 memory_reader.Read(nullptr, 21);
154 }
155
156 #endif // TESTING_CHECK_FAILURES_IS_SUPPORTED
157
TEST(MemoryReader,SingleFullRead)158 TEST(MemoryReader, SingleFullRead) {
159 constexpr size_t kTempBufferSize = 32;
160
161 std::array<std::byte, kTempBufferSize> source;
162 std::array<std::byte, kTempBufferSize> dest;
163
164 uint8_t counter = 0;
165 for (std::byte& value : source) {
166 value = std::byte(counter++);
167 }
168
169 MemoryReader memory_reader(source);
170
171 // Read exactly the available bytes.
172 EXPECT_EQ(memory_reader.ConservativeReadLimit(), dest.size());
173 Result<ByteSpan> result = memory_reader.Read(dest);
174 EXPECT_EQ(result.status(), OkStatus());
175 EXPECT_EQ(result.value().size_bytes(), dest.size());
176
177 ASSERT_EQ(source.size(), result.value().size_bytes());
178 for (size_t i = 0; i < source.size(); i++) {
179 EXPECT_EQ(source[i], result.value()[i]);
180 }
181
182 // Shoud be no byte remaining.
183 EXPECT_EQ(memory_reader.ConservativeReadLimit(), 0u);
184 result = memory_reader.Read(dest);
185 EXPECT_EQ(result.status(), Status::OutOfRange());
186 }
187
TEST(MemoryReader,EmptySpanRead)188 TEST(MemoryReader, EmptySpanRead) {
189 constexpr size_t kTempBufferSize = 32;
190 std::array<std::byte, kTempBufferSize> source;
191
192 // Use a span with nullptr and zero length;
193 ByteSpan dest(nullptr, 0);
194 EXPECT_EQ(dest.size_bytes(), 0u);
195
196 MemoryReader memory_reader(source);
197
198 // Read exactly the available bytes.
199 Result<ByteSpan> result = memory_reader.Read(dest);
200 EXPECT_EQ(result.status(), OkStatus());
201 EXPECT_EQ(result.value().size_bytes(), 0u);
202 EXPECT_EQ(result.value().data(), dest.data());
203
204 // Shoud be original bytes remaining.
205 EXPECT_EQ(memory_reader.ConservativeReadLimit(), source.size());
206 }
207
TEST(MemoryReader,SinglePartialRead)208 TEST(MemoryReader, SinglePartialRead) {
209 constexpr size_t kTempBufferSize = 32;
210 std::array<std::byte, kTempBufferSize> source;
211 std::array<std::byte, kTempBufferSize * 2> dest;
212
213 uint8_t counter = 0;
214 for (std::byte& value : source) {
215 value = std::byte(counter++);
216 }
217
218 MemoryReader memory_reader(source);
219
220 // Try and read double the bytes available. Use the pointer/size version of
221 // the API.
222 Result<ByteSpan> result = memory_reader.Read(dest.data(), dest.size());
223 EXPECT_EQ(result.status(), OkStatus());
224 EXPECT_EQ(result.value().size_bytes(), source.size());
225
226 ASSERT_EQ(source.size(), result.value().size_bytes());
227 for (size_t i = 0; i < source.size(); i++) {
228 EXPECT_EQ(source[i], result.value()[i]);
229 }
230
231 // Shoud be no byte remaining.
232 EXPECT_EQ(memory_reader.ConservativeReadLimit(), 0u);
233 result = memory_reader.Read(dest);
234 EXPECT_EQ(result.status(), Status::OutOfRange());
235 }
236
TEST(MemoryReader,MultipleReads)237 TEST(MemoryReader, MultipleReads) {
238 constexpr size_t kTempBufferSize = 32;
239
240 std::array<std::byte, kTempBufferSize * 5> source;
241 std::array<std::byte, kTempBufferSize> dest;
242
243 uint8_t counter = 0;
244
245 for (std::byte& value : source) {
246 value = std::byte(counter++);
247 }
248
249 MemoryReader memory_reader(source);
250
251 size_t source_chunk_base = 0;
252
253 while (memory_reader.ConservativeReadLimit() > 0) {
254 size_t read_limit = memory_reader.ConservativeReadLimit();
255
256 // Try and read a chunk of bytes.
257 Result<ByteSpan> result = memory_reader.Read(dest);
258 EXPECT_EQ(result.status(), OkStatus());
259 EXPECT_EQ(result.value().size_bytes(), dest.size());
260 EXPECT_EQ(memory_reader.ConservativeReadLimit(),
261 read_limit - result.value().size_bytes());
262
263 // Verify the chunk of byte that was read.
264 for (size_t i = 0; i < result.value().size_bytes(); i++) {
265 EXPECT_EQ(source[source_chunk_base + i], result.value()[i]);
266 }
267 source_chunk_base += result.value().size_bytes();
268 }
269 }
270
271 } // namespace
272 } // namespace pw::stream
273