Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2018 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 "src/tracing/test/fake_packet.h" |
| 18 | |
| 19 | #include <ostream> |
| 20 | |
| 21 | #include "perfetto/base/logging.h" |
| 22 | #include "perfetto/protozero/proto_utils.h" |
| 23 | #include "perfetto/tracing/core/shared_memory_abi.h" |
| 24 | #include "src/tracing/core/trace_buffer.h" |
| 25 | |
| 26 | using protozero::proto_utils::ParseVarInt; |
| 27 | using protozero::proto_utils::WriteVarInt; |
| 28 | |
| 29 | namespace perfetto { |
| 30 | |
| 31 | FakePacketFragment::FakePacketFragment(size_t size, char prefix) { |
| 32 | // |size| has to be at least == 2, because one byte will be taken just by the |
| 33 | // varint header. |
| 34 | PERFETTO_CHECK(size > 1); |
| 35 | |
| 36 | // Finding the |payload_size| from |size| is quite tricky: |
| 37 | // A packet with 127 bytes of payload requires: |
| 38 | // 1B header (to represent the number 127 in varint) + 127 = 128 bytes. |
| 39 | // A packet with 128 bytes payload requires: |
| 40 | // 2B header (to represent the number 128 in varint) + 128 = 130 bytes. |
| 41 | // So the only way to generate a packet of 129 bytes in total we need to |
| 42 | // generate a redundant varint header of 2 bytes + 127 bytes of payload. |
| 43 | if (size <= 128) { |
| 44 | header_[0] = static_cast<uint8_t>(size - 1); |
| 45 | header_size_ = 1; |
| 46 | payload_.resize(size - 1); |
| 47 | } else if (size == 129) { |
| 48 | header_[0] = 0x80 | 127; |
| 49 | header_size_ = 2; |
| 50 | payload_.resize(127); |
| 51 | } else { |
| 52 | WriteVarInt(size - 2, &header_[0]); |
| 53 | header_size_ = 2; |
| 54 | payload_.resize(size - 2); |
| 55 | } |
| 56 | // Fills the payload as follow: X00-X01-X02 (where X == |prefix|); |
| 57 | for (size_t i = 0; i < payload_.size(); i++) { |
| 58 | switch (i % 4) { |
| 59 | case 0: |
| 60 | payload_[i] = prefix; |
| 61 | break; |
| 62 | case 1: |
| 63 | payload_[i] = '0' + ((i / 4 / 10) % 10); |
| 64 | break; |
| 65 | case 2: |
| 66 | payload_[i] = '0' + ((i / 4) % 10); |
| 67 | break; |
| 68 | case 3: |
| 69 | payload_[i] = '-'; |
| 70 | break; |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | FakePacketFragment::FakePacketFragment(const void* payload, |
| 76 | size_t payload_size) { |
| 77 | PERFETTO_CHECK(payload_size <= 4096 - 2); |
| 78 | payload_.assign(reinterpret_cast<const char*>(payload), payload_size); |
| 79 | uint8_t* end = WriteVarInt(payload_.size(), &header_[0]); |
Primiano Tucci | 3cbb10a | 2018-04-10 17:52:40 +0100 | [diff] [blame] | 80 | header_size_ = static_cast<size_t>(end - &header_[0]); |
Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | void FakePacketFragment::CopyInto(std::vector<uint8_t>* data) const { |
| 84 | data->insert(data->end(), &header_[0], &header_[0] + header_size_); |
| 85 | data->insert(data->end(), payload_.begin(), payload_.end()); |
| 86 | } |
| 87 | |
| 88 | size_t FakePacketFragment::GetSizeHeader() const { |
| 89 | uint64_t size = 0; |
| 90 | ParseVarInt(&header_[0], &header_[0] + header_size_, &size); |
| 91 | return static_cast<size_t>(size); |
| 92 | } |
| 93 | |
| 94 | bool FakePacketFragment::operator==(const FakePacketFragment& o) const { |
| 95 | if (payload_ != o.payload_) |
| 96 | return false; |
| 97 | PERFETTO_CHECK(GetSizeHeader() == o.GetSizeHeader()); |
| 98 | return true; |
| 99 | } |
| 100 | |
| 101 | std::ostream& operator<<(std::ostream& os, const FakePacketFragment& packet) { |
| 102 | return os << "{len:" << packet.payload().size() << ", payload:\"" |
| 103 | << packet.payload() << "\"}"; |
| 104 | } |
| 105 | |
Hector Dearman | 6214c8f | 2018-03-27 16:16:22 +0100 | [diff] [blame] | 106 | FakeChunk::FakeChunk(TraceBuffer* t, ProducerID p, WriterID w, ChunkID c) |
Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 107 | : trace_buffer_{t}, producer_id{p}, writer_id{w}, chunk_id{c} {} |
| 108 | |
| 109 | FakeChunk& FakeChunk::AddPacket(size_t size, char seed, uint8_t packet_flag) { |
| 110 | PERFETTO_DCHECK(size <= 4096); |
| 111 | PERFETTO_CHECK( |
| 112 | !(packet_flag & |
| 113 | SharedMemoryABI::ChunkHeader::kFirstPacketContinuesFromPrevChunk) || |
| 114 | num_packets == 0); |
| 115 | PERFETTO_CHECK( |
| 116 | !(flags & SharedMemoryABI::ChunkHeader::kLastPacketContinuesOnNextChunk)); |
| 117 | flags |= packet_flag; |
| 118 | FakePacketFragment(size, seed).CopyInto(&data); |
| 119 | num_packets++; |
| 120 | return *this; |
| 121 | } |
| 122 | |
| 123 | FakeChunk& FakeChunk::AddPacket(std::initializer_list<uint8_t> raw) { |
| 124 | data.insert(data.end(), raw.begin(), raw.end()); |
| 125 | num_packets++; |
| 126 | return *this; |
| 127 | } |
| 128 | |
Primiano Tucci | 7b14f65 | 2018-04-06 12:16:34 +0200 | [diff] [blame] | 129 | FakeChunk& FakeChunk::IncrementNumPackets() { |
| 130 | num_packets++; |
| 131 | return *this; |
| 132 | } |
| 133 | |
Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 134 | FakeChunk& FakeChunk::ClearBytes(size_t offset, size_t len) { |
| 135 | PERFETTO_DCHECK(offset + len <= data.size()); |
| 136 | memset(data.data() + offset, 0, len); |
| 137 | return *this; |
| 138 | } |
| 139 | |
Primiano Tucci | 09db827 | 2018-03-08 17:47:47 +0000 | [diff] [blame] | 140 | FakeChunk& FakeChunk::SetUID(uid_t u) { |
| 141 | uid = u; |
| 142 | return *this; |
| 143 | } |
| 144 | |
Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 145 | size_t FakeChunk::CopyIntoTraceBuffer() { |
Primiano Tucci | 09db827 | 2018-03-08 17:47:47 +0000 | [diff] [blame] | 146 | trace_buffer_->CopyChunkUntrusted(producer_id, uid, writer_id, chunk_id, |
Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 147 | num_packets, flags, data.data(), |
| 148 | data.size()); |
Hector Dearman | 6214c8f | 2018-03-27 16:16:22 +0100 | [diff] [blame] | 149 | return data.size() + TraceBuffer::InlineChunkHeaderSize; |
Primiano Tucci | 5c59901 | 2018-03-01 17:52:07 +0000 | [diff] [blame] | 150 | } |
| 151 | |
| 152 | } // namespace perfetto |