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 26using protozero::proto_utils::ParseVarInt; 27using protozero::proto_utils::WriteVarInt; 28 29namespace perfetto { 30 31FakePacketFragment::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 75FakePacketFragment::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]); 80 header_size_ = static_cast<size_t>(end - &header_[0]); 81} 82 83void 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 88size_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 94bool 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 101std::ostream& operator<<(std::ostream& os, const FakePacketFragment& packet) { 102 return os << "{len:" << packet.payload().size() << ", payload:\"" 103 << packet.payload() << "\"}"; 104} 105 106FakeChunk::FakeChunk(TraceBuffer* t, ProducerID p, WriterID w, ChunkID c) 107 : trace_buffer_{t}, producer_id{p}, writer_id{w}, chunk_id{c} {} 108 109FakeChunk& 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 123FakeChunk& 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 129FakeChunk& FakeChunk::IncrementNumPackets() { 130 num_packets++; 131 return *this; 132} 133 134FakeChunk& 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 140FakeChunk& FakeChunk::SetUID(uid_t u) { 141 uid = u; 142 return *this; 143} 144 145size_t FakeChunk::CopyIntoTraceBuffer() { 146 trace_buffer_->CopyChunkUntrusted(producer_id, uid, writer_id, chunk_id, 147 num_packets, flags, data.data(), 148 data.size()); 149 return data.size() + TraceBuffer::InlineChunkHeaderSize; 150} 151 152} // namespace perfetto 153