1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include <gtest/gtest.h> 21 22 #include <nvram/messages/io.h> 23 24 namespace nvram { 25 26 namespace { 27 28 // A simple |InputStreamBuffer| implementation that sets up a sequence of 29 // windows of |sizes| specified by the template parameters. Each byte read from 30 // the buffer has a value corresponding to its position in the stream. 31 template<size_t... sizes> 32 class TestInputStreamBuffer : public InputStreamBuffer { 33 public: 34 TestInputStreamBuffer() { 35 Advance(); 36 } 37 38 private: 39 bool Advance() override { 40 if (index_ >= (sizeof(kSizes) / sizeof(kSizes[0]))) { 41 return false; 42 } 43 44 memset(buffer, 0xff, kMaxSize); 45 const size_t size = kSizes[index_] < kMaxSize ? kSizes[index_] : kMaxSize; 46 pos_ = buffer; 47 end_ = buffer + size; 48 for (uint8_t* p = buffer; p < end_; ++p) { 49 *p = static_cast<uint8_t>(count_++ % 256); 50 } 51 ++index_; 52 return true; 53 } 54 55 static constexpr size_t kMaxSize = 256; 56 static constexpr size_t kSizes[] = { sizes... }; 57 58 uint8_t buffer[kMaxSize]; 59 size_t index_ = 0; 60 size_t count_ = 0; 61 }; 62 63 template<size_t... sizes> 64 constexpr size_t TestInputStreamBuffer<sizes...>::kSizes[]; 65 66 // Tests whether a read of the given size returns the correct data, i.e. bytes 67 // with consecutive values starting at |pos|. 68 void CheckRead(InputStreamBuffer* buffer, size_t size, size_t pos) { 69 uint8_t data[256]; 70 ASSERT_LE(size, sizeof(data)); 71 EXPECT_TRUE(buffer->Read(data, size)); 72 for (uint8_t* p = data; p < data + size; ++p) { 73 EXPECT_EQ(pos++ % 256, *p); 74 } 75 } 76 77 } // namespace 78 79 TEST(InputStreamBufferTest, Basic) { 80 TestInputStreamBuffer<10> buf; 81 EXPECT_FALSE(buf.Done()); 82 83 uint8_t byte = 0; 84 EXPECT_TRUE(buf.ReadByte(&byte)); 85 EXPECT_EQ(0, byte); 86 EXPECT_FALSE(buf.Done()); 87 88 CheckRead(&buf, 6, 1); 89 EXPECT_FALSE(buf.Done()); 90 91 EXPECT_TRUE(buf.Skip(3)); 92 EXPECT_TRUE(buf.Done()); 93 } 94 95 TEST(InputStreamBufferTest, Empty) { 96 InputStreamBuffer buf(nullptr, nullptr); 97 EXPECT_TRUE(buf.Done()); 98 uint8_t byte = 0; 99 EXPECT_FALSE(buf.ReadByte(&byte)); 100 } 101 102 TEST(InputStreamBufferTest, LargeRead) { 103 TestInputStreamBuffer<10> buf; 104 uint8_t read_buf[10]; 105 EXPECT_FALSE(buf.Read(read_buf, SIZE_MAX)); 106 } 107 108 TEST(InputStreamBufferTest, LargeSkip) { 109 TestInputStreamBuffer<10> buf; 110 EXPECT_FALSE(buf.Skip(SIZE_MAX)); 111 } 112 113 TEST(InputStreamBufferTest, OverlappingReadByte) { 114 TestInputStreamBuffer<1, 1> buf; 115 116 uint8_t byte = 0; 117 EXPECT_TRUE(buf.ReadByte(&byte)); 118 EXPECT_EQ(0, byte); 119 EXPECT_FALSE(buf.Done()); 120 121 EXPECT_TRUE(buf.ReadByte(&byte)); 122 EXPECT_EQ(1, byte); 123 EXPECT_TRUE(buf.Done()); 124 } 125 126 TEST(InputStreamBufferTest, OverlappingRead) { 127 TestInputStreamBuffer<10, 10, 10> buf; 128 CheckRead(&buf, 15, 0); 129 CheckRead(&buf, 10, 15); 130 CheckRead(&buf, 5, 25); 131 EXPECT_TRUE(buf.Done()); 132 } 133 134 TEST(InputStreamBufferTest, OverlappingSkip) { 135 TestInputStreamBuffer<10, 10, 10> buf; 136 EXPECT_TRUE(buf.Skip(15)); 137 EXPECT_TRUE(buf.Skip(10)); 138 EXPECT_TRUE(buf.Skip(5)); 139 EXPECT_TRUE(buf.Done()); 140 } 141 142 TEST(NestedInputStreamBufferTest, Large) { 143 TestInputStreamBuffer<10> buf; 144 NestedInputStreamBuffer nested(&buf, SIZE_MAX); 145 EXPECT_FALSE(nested.Skip(SIZE_MAX)); 146 } 147 148 TEST(NestedInputStreamBufferTest, Short) { 149 TestInputStreamBuffer<10> buf; 150 NestedInputStreamBuffer nested(&buf, 5); 151 CheckRead(&nested, 5, 0); 152 EXPECT_TRUE(nested.Done()); 153 EXPECT_FALSE(nested.Skip(1)); 154 } 155 156 TEST(NestedInputStreamBufferTest, Matching) { 157 TestInputStreamBuffer<10, 5> buf; 158 NestedInputStreamBuffer nested(&buf, 10); 159 CheckRead(&nested, 10, 0); 160 EXPECT_TRUE(nested.Done()); 161 EXPECT_FALSE(nested.Skip(1)); 162 } 163 164 TEST(NestedInputStreamBufferTest, Overlapping) { 165 TestInputStreamBuffer<2, 3, 5, 8> buf; 166 NestedInputStreamBuffer nested(&buf, 16); 167 CheckRead(&nested, 8, 0); 168 EXPECT_FALSE(nested.Done()); 169 CheckRead(&nested, 8, 8); 170 EXPECT_TRUE(nested.Done()); 171 EXPECT_FALSE(nested.Skip(1)); 172 } 173 174 namespace { 175 176 // An |OutputStreamBuffer| implementation backed by a sequence of buffer windows 177 // of |sizes| specified as template parameters. The output is expected to be 178 // sequential byte values starting at 0. 179 template<size_t... sizes> 180 class TestOutputStreamBuffer : public OutputStreamBuffer { 181 public: 182 TestOutputStreamBuffer() { 183 Advance(); 184 } 185 186 ~TestOutputStreamBuffer() { 187 EXPECT_TRUE(Verify()); 188 } 189 190 bool Verify() { 191 for (; check_pos_ < pos_; check_pos_++, count_++) { 192 data_matches_ &= *check_pos_ == (count_ % 256); 193 } 194 195 return data_matches_; 196 } 197 198 private: 199 bool Advance() override { 200 if (index_ >= (sizeof(kSizes) / sizeof(kSizes[0]))) { 201 return false; 202 } 203 204 pos_ = end_; 205 Verify(); 206 207 memset(buffer, 0xff, kMaxSize); 208 const size_t size = kSizes[index_] < kMaxSize ? kSizes[index_] : kMaxSize; 209 pos_ = buffer; 210 check_pos_ = buffer; 211 end_ = buffer + size; 212 ++index_; 213 return true; 214 } 215 216 static constexpr size_t kMaxSize = 256; 217 static constexpr size_t kSizes[] = { sizes... }; 218 219 uint8_t buffer[kMaxSize]; 220 size_t index_ = 0; 221 222 // The pointer in buffer until which the data has been checked to match the 223 // expectations. 224 uint8_t* check_pos_ = nullptr; 225 226 // The counter that determines the expected value for the buffer bytes. 227 size_t count_ = 0; 228 229 // Whether all bytes that have been checked so far had the expected value. 230 bool data_matches_ = true; 231 }; 232 233 template<size_t... sizes> 234 constexpr size_t TestOutputStreamBuffer<sizes...>::kSizes[]; 235 236 // Writes a buffer of |size| to |buf|. The buffer contains consecutive byte 237 // value starting at pos. 238 void WriteBuf(OutputStreamBuffer* buffer, size_t size, size_t pos) { 239 uint8_t data[1024]; 240 ASSERT_LE(size, sizeof(data)); 241 for (uint8_t* p = data; p < data + size; ++p) { 242 *p = pos++ % 256; 243 } 244 EXPECT_TRUE(buffer->Write(data, size)); 245 } 246 247 } // namespace 248 249 TEST(OutputStreamBufferTest, Basic) { 250 TestOutputStreamBuffer<10> buf; 251 EXPECT_FALSE(buf.Done()); 252 253 EXPECT_TRUE(buf.WriteByte(0)); 254 EXPECT_TRUE(buf.WriteByte(1)); 255 EXPECT_FALSE(buf.Done()); 256 EXPECT_TRUE(buf.Verify()); 257 258 WriteBuf(&buf, 6, 2); 259 EXPECT_FALSE(buf.Done()); 260 EXPECT_TRUE(buf.Verify()); 261 262 WriteBuf(&buf, 2, 8); 263 EXPECT_TRUE(buf.Done()); 264 } 265 266 TEST(OutputStreamBufferTest, Empty) { 267 OutputStreamBuffer buf(nullptr, nullptr); 268 EXPECT_TRUE(buf.Done()); 269 EXPECT_FALSE(buf.WriteByte(0)); 270 } 271 272 TEST(OutputStreamBufferTest, ShortWrite) { 273 TestOutputStreamBuffer<10> buf; 274 WriteBuf(&buf, 5, 0); 275 } 276 277 TEST(OutputStreamBufferTest, LargeWrite) { 278 TestOutputStreamBuffer<5> buf; 279 uint8_t data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 280 EXPECT_FALSE(buf.Write(data, sizeof(data))); 281 } 282 283 TEST(OutputStreamBufferTest, OverlappingWriteByte) { 284 TestOutputStreamBuffer<1, 1> buf; 285 EXPECT_TRUE(buf.WriteByte(0)); 286 EXPECT_FALSE(buf.Done()); 287 EXPECT_TRUE(buf.WriteByte(1)); 288 EXPECT_TRUE(buf.Done()); 289 } 290 291 TEST(OutputStreamBufferTest, OverlappingWrite) { 292 TestOutputStreamBuffer<10, 10, 10> buf; 293 WriteBuf(&buf, 15, 0); 294 EXPECT_FALSE(buf.Done()); 295 WriteBuf(&buf, 10, 15); 296 EXPECT_FALSE(buf.Done()); 297 WriteBuf(&buf, 5, 25); 298 EXPECT_TRUE(buf.Done()); 299 } 300 301 TEST(CountingOutputStreamBuffer, Basic) { 302 CountingOutputStreamBuffer buf; 303 EXPECT_EQ(0U, buf.bytes_written()); 304 EXPECT_FALSE(buf.Done()); 305 306 WriteBuf(&buf, 15, 0); 307 EXPECT_EQ(15U, buf.bytes_written()); 308 EXPECT_FALSE(buf.Done()); 309 310 EXPECT_TRUE(buf.WriteByte(0)); 311 EXPECT_EQ(16U, buf.bytes_written()); 312 EXPECT_FALSE(buf.Done()); 313 314 WriteBuf(&buf, 1024, 0); 315 EXPECT_EQ(1040U, buf.bytes_written()); 316 EXPECT_FALSE(buf.Done()); 317 } 318 319 TEST(BlobOutputStreamBuffer, Basic) { 320 Blob blob; 321 ASSERT_TRUE(blob.Resize(1024 * 1024)); 322 BlobOutputStreamBuffer buf(&blob); 323 324 WriteBuf(&buf, 15, 0); 325 EXPECT_FALSE(buf.Done()); 326 327 EXPECT_TRUE(buf.WriteByte(15)); 328 EXPECT_FALSE(buf.Done()); 329 330 EXPECT_TRUE(buf.Truncate()); 331 EXPECT_EQ(16U, blob.size()); 332 for (size_t i = 0; i < blob.size(); ++i) { 333 EXPECT_EQ(i % 256, blob.data()[i]); 334 } 335 336 WriteBuf(&buf, 1024, 16); 337 EXPECT_FALSE(buf.Done()); 338 339 EXPECT_TRUE(buf.Truncate()); 340 EXPECT_EQ(1040U, blob.size()); 341 for (size_t i = 0; i < blob.size(); ++i) { 342 EXPECT_EQ(i % 256, blob.data()[i]); 343 } 344 } 345 346 } // namespace nvram 347