blob: 0e42fa588bda1f32168d70fc2e9b0ec7699d199f [file] [log] [blame]
Armando Montanez0bcae732020-05-27 13:28:11 -07001// 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
20namespace pw::stream {
21namespace {
22
23// Size of the in-memory buffer to use for this test.
24constexpr size_t kSinkBufferSize = 1013;
25
26struct TestStruct {
27 uint8_t day;
28 uint8_t month;
29 uint16_t year;
30};
31
32constexpr TestStruct kExpectedStruct = {.day = 18, .month = 5, .year = 2020};
33
34std::array<std::byte, kSinkBufferSize> memory_buffer;
35
36TEST(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));
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080041 EXPECT_EQ(status, OkStatus());
Armando Montanez0bcae732020-05-27 13:28:11 -070042 EXPECT_EQ(memory_writer.bytes_written(), sizeof(kExpectedStruct));
Prashanth Swaminathan5b5d9dd2021-06-11 15:59:25 -070043}
44
45TEST(MemoryWriter, BytesWrittenOnConstruction) {
46 constexpr size_t bytes_written = kSinkBufferSize / 2;
47 std::memset(memory_buffer.data(), 1u, bytes_written);
48 MemoryWriter memory_writer(memory_buffer, bytes_written);
49 EXPECT_EQ(memory_writer.bytes_written(), bytes_written);
50 EXPECT_EQ(memcmp(memory_writer.WrittenData().data(),
51 memory_buffer.data(),
52 bytes_written),
53 0);
54}
Armando Montanez0bcae732020-05-27 13:28:11 -070055
56TEST(MemoryWriter, ValidateContents) {
57 MemoryWriter memory_writer(memory_buffer);
58 EXPECT_TRUE(
59 memory_writer.Write(&kExpectedStruct, sizeof(kExpectedStruct)).ok());
60
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070061 std::span<const std::byte> written_data = memory_writer.WrittenData();
Armando Montanez0bcae732020-05-27 13:28:11 -070062 EXPECT_EQ(written_data.size_bytes(), sizeof(kExpectedStruct));
63 TestStruct temp;
64 std::memcpy(&temp, written_data.data(), written_data.size_bytes());
65 EXPECT_EQ(memcmp(&temp, &kExpectedStruct, sizeof(kExpectedStruct)), 0);
66}
67
68TEST(MemoryWriter, MultipleWrites) {
69 constexpr size_t kTempBufferSize = 72;
70 std::byte buffer[kTempBufferSize] = {};
Armando Montanez0bcae732020-05-27 13:28:11 -070071
David Rogers6d4f6302020-07-22 14:27:41 -070072 for (std::byte& value : memory_buffer) {
73 value = std::byte(0);
74 }
Armando Montanez0bcae732020-05-27 13:28:11 -070075 MemoryWriter memory_writer(memory_buffer);
76
David Rogers6d4f6302020-07-22 14:27:41 -070077 size_t counter = 0;
78 while (memory_writer.ConservativeWriteLimit() >= kTempBufferSize) {
Armando Montanez0bcae732020-05-27 13:28:11 -070079 for (size_t i = 0; i < sizeof(buffer); ++i) {
80 buffer[i] = std::byte(counter++);
81 }
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080082 EXPECT_EQ(memory_writer.Write(std::span(buffer)), OkStatus());
David Rogers6d4f6302020-07-22 14:27:41 -070083 }
Armando Montanez0bcae732020-05-27 13:28:11 -070084
David Rogers6d4f6302020-07-22 14:27:41 -070085 EXPECT_GT(memory_writer.ConservativeWriteLimit(), 0u);
86 EXPECT_LT(memory_writer.ConservativeWriteLimit(), kTempBufferSize);
Armando Montanez0bcae732020-05-27 13:28:11 -070087
Wyatt Heplerd78f7c62020-09-28 14:27:32 -070088 EXPECT_EQ(memory_writer.Write(std::span(buffer)),
89 Status::ResourceExhausted());
David Rogers6d4f6302020-07-22 14:27:41 -070090 EXPECT_EQ(memory_writer.bytes_written(), counter);
Armando Montanez0bcae732020-05-27 13:28:11 -070091
92 counter = 0;
93 for (const std::byte& value : memory_writer.WrittenData()) {
94 EXPECT_EQ(value, std::byte(counter++));
95 }
96}
97
David Rogers6d4f6302020-07-22 14:27:41 -070098TEST(MemoryWriter, FullWriter) {
99 constexpr size_t kTempBufferSize = 32;
100 std::byte buffer[kTempBufferSize] = {};
101 const int fill_byte = 0x25;
102 memset(buffer, fill_byte, sizeof(buffer));
103
104 for (std::byte& value : memory_buffer) {
105 value = std::byte(0);
106 }
107 MemoryWriter memory_writer(memory_buffer);
108
109 while (memory_writer.ConservativeWriteLimit() > 0) {
110 size_t bytes_to_write =
111 std::min(sizeof(buffer), memory_writer.ConservativeWriteLimit());
112 EXPECT_EQ(memory_writer.Write(std::span(buffer, bytes_to_write)),
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800113 OkStatus());
David Rogers6d4f6302020-07-22 14:27:41 -0700114 }
115
116 EXPECT_EQ(memory_writer.ConservativeWriteLimit(), 0u);
117
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700118 EXPECT_EQ(memory_writer.Write(std::span(buffer)), Status::OutOfRange());
David Rogers6d4f6302020-07-22 14:27:41 -0700119 EXPECT_EQ(memory_writer.bytes_written(), memory_buffer.size());
120
121 for (const std::byte& value : memory_writer.WrittenData()) {
122 EXPECT_EQ(value, std::byte(fill_byte));
123 }
124}
125
Armando Montanez0bcae732020-05-27 13:28:11 -0700126TEST(MemoryWriter, EmptyData) {
127 std::byte buffer[5] = {};
128
129 MemoryWriter memory_writer(memory_buffer);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800130 EXPECT_EQ(memory_writer.Write(buffer, 0), OkStatus());
Armando Montanez0bcae732020-05-27 13:28:11 -0700131 EXPECT_EQ(memory_writer.bytes_written(), 0u);
132}
133
shaneajgfdb2e502020-07-13 16:18:59 -0400134TEST(MemoryWriter, ValidateContents_SingleByteWrites) {
135 MemoryWriter memory_writer(memory_buffer);
136 EXPECT_TRUE(memory_writer.Write(std::byte{0x01}).ok());
137 EXPECT_EQ(memory_writer.bytes_written(), 1u);
138 EXPECT_EQ(memory_writer.data()[0], std::byte{0x01});
139
140 EXPECT_TRUE(memory_writer.Write(std::byte{0x7E}).ok());
141 EXPECT_EQ(memory_writer.bytes_written(), 2u);
142 EXPECT_EQ(memory_writer.data()[1], std::byte{0x7E});
143}
144
Armando Montanezf82d95b2021-04-08 12:00:09 -0700145TEST(MemoryWriter, OverlappingBuffer) {
146 constexpr std::string_view kTestString("This is staged into the same buffer");
147 // Write at a five-byte offset from the start of the destination buffer.
148 constexpr std::byte* kOverlappingStart = memory_buffer.data() + 5;
149 std::memcpy(kOverlappingStart, kTestString.data(), kTestString.size());
150 MemoryWriter memory_writer(memory_buffer);
151 EXPECT_TRUE(memory_writer.Write(kOverlappingStart, kTestString.size()).ok());
152 EXPECT_TRUE(memory_writer.Write(std::byte(0)).ok());
153 EXPECT_EQ(memory_writer.bytes_written(), kTestString.size() + 1);
154
155 EXPECT_STREQ(
156 reinterpret_cast<const char*>(memory_writer.WrittenData().data()),
157 kTestString.data());
158}
159
Ewout van Bekkume4d7b692020-10-15 13:12:30 -0700160#define TESTING_CHECK_FAILURES_IS_SUPPORTED 0
161#if TESTING_CHECK_FAILURES_IS_SUPPORTED
Armando Montanez0bcae732020-05-27 13:28:11 -0700162
163// TODO(amontanez): Ensure that this test triggers an assert.
164TEST(MemoryWriter, NullPointer) {
165 MemoryWriter memory_writer(memory_buffer);
166 memory_writer.Write(nullptr, 21);
167}
168
David Rogers795fecf2020-07-28 00:36:45 -0700169// TODO(davidrogers): Ensure that this test triggers an assert.
170TEST(MemoryReader, NullSpan) {
171 ByteSpan dest(nullptr, 5);
172 MemoryReader memory_reader(memory_buffer);
173 memory_reader.Read(dest);
174}
175
176// TODO(davidrogers): Ensure that this test triggers an assert.
177TEST(MemoryReader, NullPointer) {
178 MemoryReader memory_reader(memory_buffer);
179 memory_reader.Read(nullptr, 21);
180}
181
Ewout van Bekkume4d7b692020-10-15 13:12:30 -0700182#endif // TESTING_CHECK_FAILURES_IS_SUPPORTED
Armando Montanez0bcae732020-05-27 13:28:11 -0700183
David Rogers795fecf2020-07-28 00:36:45 -0700184TEST(MemoryReader, SingleFullRead) {
185 constexpr size_t kTempBufferSize = 32;
186
187 std::array<std::byte, kTempBufferSize> source;
188 std::array<std::byte, kTempBufferSize> dest;
189
190 uint8_t counter = 0;
191 for (std::byte& value : source) {
192 value = std::byte(counter++);
193 }
194
195 MemoryReader memory_reader(source);
196
197 // Read exactly the available bytes.
198 EXPECT_EQ(memory_reader.ConservativeReadLimit(), dest.size());
199 Result<ByteSpan> result = memory_reader.Read(dest);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800200 EXPECT_EQ(result.status(), OkStatus());
David Rogers795fecf2020-07-28 00:36:45 -0700201 EXPECT_EQ(result.value().size_bytes(), dest.size());
202
203 ASSERT_EQ(source.size(), result.value().size_bytes());
204 for (size_t i = 0; i < source.size(); i++) {
205 EXPECT_EQ(source[i], result.value()[i]);
206 }
207
208 // Shoud be no byte remaining.
209 EXPECT_EQ(memory_reader.ConservativeReadLimit(), 0u);
210 result = memory_reader.Read(dest);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700211 EXPECT_EQ(result.status(), Status::OutOfRange());
David Rogers795fecf2020-07-28 00:36:45 -0700212}
213
214TEST(MemoryReader, EmptySpanRead) {
215 constexpr size_t kTempBufferSize = 32;
216 std::array<std::byte, kTempBufferSize> source;
217
218 // Use a span with nullptr and zero length;
219 ByteSpan dest(nullptr, 0);
220 EXPECT_EQ(dest.size_bytes(), 0u);
221
222 MemoryReader memory_reader(source);
223
224 // Read exactly the available bytes.
225 Result<ByteSpan> result = memory_reader.Read(dest);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800226 EXPECT_EQ(result.status(), OkStatus());
David Rogers795fecf2020-07-28 00:36:45 -0700227 EXPECT_EQ(result.value().size_bytes(), 0u);
228 EXPECT_EQ(result.value().data(), dest.data());
229
230 // Shoud be original bytes remaining.
231 EXPECT_EQ(memory_reader.ConservativeReadLimit(), source.size());
232}
233
234TEST(MemoryReader, SinglePartialRead) {
235 constexpr size_t kTempBufferSize = 32;
236 std::array<std::byte, kTempBufferSize> source;
237 std::array<std::byte, kTempBufferSize * 2> dest;
238
239 uint8_t counter = 0;
240 for (std::byte& value : source) {
241 value = std::byte(counter++);
242 }
243
244 MemoryReader memory_reader(source);
245
246 // Try and read double the bytes available. Use the pointer/size version of
247 // the API.
248 Result<ByteSpan> result = memory_reader.Read(dest.data(), dest.size());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800249 EXPECT_EQ(result.status(), OkStatus());
David Rogers795fecf2020-07-28 00:36:45 -0700250 EXPECT_EQ(result.value().size_bytes(), source.size());
251
252 ASSERT_EQ(source.size(), result.value().size_bytes());
253 for (size_t i = 0; i < source.size(); i++) {
254 EXPECT_EQ(source[i], result.value()[i]);
255 }
256
257 // Shoud be no byte remaining.
258 EXPECT_EQ(memory_reader.ConservativeReadLimit(), 0u);
259 result = memory_reader.Read(dest);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700260 EXPECT_EQ(result.status(), Status::OutOfRange());
David Rogers795fecf2020-07-28 00:36:45 -0700261}
262
263TEST(MemoryReader, MultipleReads) {
264 constexpr size_t kTempBufferSize = 32;
265
266 std::array<std::byte, kTempBufferSize * 5> source;
267 std::array<std::byte, kTempBufferSize> dest;
268
269 uint8_t counter = 0;
270
271 for (std::byte& value : source) {
272 value = std::byte(counter++);
273 }
274
275 MemoryReader memory_reader(source);
276
277 size_t source_chunk_base = 0;
278
279 while (memory_reader.ConservativeReadLimit() > 0) {
280 size_t read_limit = memory_reader.ConservativeReadLimit();
281
282 // Try and read a chunk of bytes.
283 Result<ByteSpan> result = memory_reader.Read(dest);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800284 EXPECT_EQ(result.status(), OkStatus());
David Rogers795fecf2020-07-28 00:36:45 -0700285 EXPECT_EQ(result.value().size_bytes(), dest.size());
286 EXPECT_EQ(memory_reader.ConservativeReadLimit(),
287 read_limit - result.value().size_bytes());
288
289 // Verify the chunk of byte that was read.
290 for (size_t i = 0; i < result.value().size_bytes(); i++) {
291 EXPECT_EQ(source[source_chunk_base + i], result.value()[i]);
292 }
293 source_chunk_base += result.value().size_bytes();
294 }
295}
296
Armando Montanez0bcae732020-05-27 13:28:11 -0700297} // namespace
David Rogers6d4f6302020-07-22 14:27:41 -0700298} // namespace pw::stream