1 /* 2 * Copyright (C) 2017 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 "perfetto/protozero/scattered_stream_writer.h" 18 19 #include <string.h> 20 21 #include <memory> 22 23 #include "gtest/gtest.h" 24 #include "perfetto/base/logging.h" 25 #include "src/protozero/test/fake_scattered_buffer.h" 26 27 namespace protozero { 28 namespace { 29 30 constexpr size_t kChunkSize = 8; 31 32 TEST(ScatteredStreamWriterTest, ScatteredWrites) { 33 FakeScatteredBuffer delegate(kChunkSize); 34 ScatteredStreamWriter ssw(&delegate); 35 36 const uint8_t kOneByteBuf[] = {0x40}; 37 const uint8_t kThreeByteBuf[] = {0x50, 0x51, 0x52}; 38 const uint8_t kFourByteBuf[] = {0x60, 0x61, 0x62, 0x63}; 39 uint8_t kTwentyByteBuf[20]; 40 for (uint8_t i = 0; i < sizeof(kTwentyByteBuf); ++i) 41 kTwentyByteBuf[i] = 0xA0 + i; 42 43 // Writing up to the chunk size should cause only the initial extension. 44 for (uint8_t i = 0; i < kChunkSize; ++i) { 45 ssw.WriteByte(i); 46 EXPECT_EQ(kChunkSize - i - 1, ssw.bytes_available()); 47 } 48 EXPECT_EQ(1u, delegate.chunks().size()); 49 EXPECT_EQ(0u, ssw.bytes_available()); 50 51 // This extra write will cause the first extension. 52 ssw.WriteBytes(kOneByteBuf, sizeof(kOneByteBuf)); 53 EXPECT_EQ(2u, delegate.chunks().size()); 54 EXPECT_EQ(7u, ssw.bytes_available()); 55 56 // This starts at offset 1, to make sure we don't hardcode any assumption 57 // about alignment. 58 uint8_t* reserved_range_1 = ssw.ReserveBytes(4); 59 EXPECT_EQ(2u, delegate.chunks().size()); 60 EXPECT_EQ(3u, ssw.bytes_available()); 61 62 ssw.WriteByte(0xFF); 63 ssw.WriteBytes(kThreeByteBuf, sizeof(kThreeByteBuf)); 64 EXPECT_EQ(3u, delegate.chunks().size()); 65 EXPECT_EQ(7u, ssw.bytes_available()); 66 67 uint8_t* reserved_range_2 = ssw.ReserveBytes(4); 68 ssw.WriteBytes(kTwentyByteBuf, sizeof(kTwentyByteBuf)); 69 EXPECT_EQ(6u, delegate.chunks().size()); 70 EXPECT_EQ(7u, ssw.bytes_available()); 71 72 // Writing reserved bytes should not change the bytes_available(). 73 memcpy(reserved_range_1, kFourByteBuf, sizeof(kFourByteBuf)); 74 memcpy(reserved_range_2, kFourByteBuf, sizeof(kFourByteBuf)); 75 EXPECT_EQ(6u, delegate.chunks().size()); 76 EXPECT_EQ(7u, ssw.bytes_available()); 77 78 // Check that reserving more bytes than what left creates a brand new chunk 79 // even if the previous one is not exhausted 80 for (uint8_t i = 0; i < 5; ++i) 81 ssw.WriteByte(0xFF); 82 memcpy(ssw.ReserveBytes(4), kFourByteBuf, sizeof(kFourByteBuf)); 83 memcpy(ssw.ReserveBytesUnsafe(3), kThreeByteBuf, sizeof(kThreeByteBuf)); 84 memcpy(ssw.ReserveBytes(3), kThreeByteBuf, sizeof(kThreeByteBuf)); 85 memcpy(ssw.ReserveBytesUnsafe(1), kOneByteBuf, sizeof(kOneByteBuf)); 86 memcpy(ssw.ReserveBytes(1), kOneByteBuf, sizeof(kOneByteBuf)); 87 88 EXPECT_EQ(8u, delegate.chunks().size()); 89 EXPECT_EQ(3u, ssw.bytes_available()); 90 91 EXPECT_EQ("0001020304050607", delegate.GetChunkAsString(0)); 92 EXPECT_EQ("4060616263FF5051", delegate.GetChunkAsString(1)); 93 EXPECT_EQ("5260616263A0A1A2", delegate.GetChunkAsString(2)); 94 EXPECT_EQ("A3A4A5A6A7A8A9AA", delegate.GetChunkAsString(3)); 95 EXPECT_EQ("ABACADAEAFB0B1B2", delegate.GetChunkAsString(4)); 96 EXPECT_EQ("B3FFFFFFFFFF0000", delegate.GetChunkAsString(5)); 97 EXPECT_EQ("6061626350515200", delegate.GetChunkAsString(6)); 98 EXPECT_EQ("5051524040000000", delegate.GetChunkAsString(7)); 99 100 // Finally reset the writer to a new buffer. 101 uint8_t other_buffer[8] = {0}; 102 ssw.Reset({other_buffer, other_buffer + sizeof(other_buffer)}); 103 EXPECT_EQ(other_buffer, ssw.write_ptr()); 104 ssw.WriteByte(1); 105 ssw.WriteBytes(kThreeByteBuf, sizeof(kThreeByteBuf)); 106 EXPECT_EQ(1u, other_buffer[0]); 107 EXPECT_EQ(0x52u, other_buffer[3]); 108 } 109 110 } // namespace 111 } // namespace protozero 112