• 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 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