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/tracing/core/trace_packet.h" 18 19 #include <string> 20 21 #include "gtest/gtest.h" 22 23 #include "perfetto/trace/trace.pb.h" 24 #include "perfetto/trace/trace_packet.pb.h" 25 #include "perfetto/trace/trusted_packet.pb.h" 26 27 namespace perfetto { 28 namespace { 29 30 static_assert(TracePacket::kPacketFieldNumber == 31 protos::Trace::kPacketFieldNumber, 32 "packet field id mismatch"); 33 34 static_assert(protos::TracePacket::kTrustedUidFieldNumber == 35 protos::TrustedPacket::kTrustedUidFieldNumber, 36 "trusted_uid field id mismatch"); 37 38 static_assert(protos::TracePacket::kTraceConfigFieldNumber == 39 protos::TrustedPacket::kTraceConfigFieldNumber, 40 "trace_config field id mismatch"); 41 42 static_assert(protos::TracePacket::kTraceStatsFieldNumber == 43 protos::TrustedPacket::kTraceStatsFieldNumber, 44 "trace_stats field id mismatch"); 45 46 static_assert(protos::TracePacket::kClockSnapshotFieldNumber == 47 protos::TrustedPacket::kClockSnapshotFieldNumber, 48 "clock_snapshot field id mismatch"); 49 50 TEST(TracePacketTest, Simple) { 51 protos::TracePacket proto; 52 proto.mutable_for_testing()->set_str("string field"); 53 std::string ser_buf = proto.SerializeAsString(); 54 TracePacket tp; 55 tp.AddSlice(ser_buf.data(), ser_buf.size()); 56 auto slice = tp.slices().begin(); 57 ASSERT_NE(tp.slices().end(), slice); 58 ASSERT_EQ(ser_buf.data(), slice->start); 59 ASSERT_EQ(ser_buf.size(), slice->size); 60 ASSERT_EQ(tp.slices().end(), ++slice); 61 62 protos::TracePacket decoded_packet; 63 ASSERT_TRUE(tp.Decode(&decoded_packet)); 64 ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str()); 65 } 66 67 TEST(TracePacketTest, Sliced) { 68 protos::TracePacket proto; 69 proto.mutable_for_testing()->set_str( 70 "this is an arbitrarily long string ........................"); 71 std::string ser_buf = proto.SerializeAsString(); 72 TracePacket tp; 73 tp.AddSlice({ser_buf.data(), 3}); 74 tp.AddSlice({ser_buf.data() + 3, 5}); 75 tp.AddSlice({ser_buf.data() + 3 + 5, ser_buf.size() - 3 - 5}); 76 ASSERT_EQ(ser_buf.size(), tp.size()); 77 78 auto slice = tp.slices().begin(); 79 ASSERT_NE(tp.slices().end(), slice); 80 ASSERT_EQ(ser_buf.data(), slice->start); 81 ASSERT_EQ(3u, slice->size); 82 83 ASSERT_NE(tp.slices().end(), ++slice); 84 ASSERT_EQ(ser_buf.data() + 3, slice->start); 85 ASSERT_EQ(5u, slice->size); 86 87 ASSERT_NE(tp.slices().end(), ++slice); 88 ASSERT_EQ(ser_buf.data() + 3 + 5, slice->start); 89 ASSERT_EQ(ser_buf.size() - 3 - 5, slice->size); 90 91 ASSERT_EQ(tp.slices().end(), ++slice); 92 93 protos::TracePacket decoded_packet; 94 ASSERT_TRUE(tp.Decode(&decoded_packet)); 95 ASSERT_EQ(proto.for_testing().str(), decoded_packet.for_testing().str()); 96 } 97 98 TEST(TracePacketTest, Corrupted) { 99 protos::TracePacket proto; 100 proto.mutable_for_testing()->set_str("string field"); 101 std::string ser_buf = proto.SerializeAsString(); 102 TracePacket tp; 103 tp.AddSlice({ser_buf.data(), ser_buf.size() - 2}); // corrupted. 104 protos::TracePacket decoded_packet; 105 ASSERT_FALSE(tp.Decode(&decoded_packet)); 106 } 107 108 // Tests that the GetProtoPreamble() logic returns a valid preamble that allows 109 // to encode a TracePacket as a field of the root trace.proto message. 110 TEST(TracePacketTest, GetProtoPreamble) { 111 char* preamble; 112 size_t preamble_size; 113 114 // Test empty packet. 115 TracePacket tp; 116 std::tie(preamble, preamble_size) = tp.GetProtoPreamble(); 117 ASSERT_EQ(2u, preamble_size); 118 ASSERT_EQ(0, preamble[1]); 119 120 // Test packet with one slice. 121 protos::TracePacket tp_proto; 122 char payload[257]; 123 for (size_t i = 0; i < sizeof(payload) - 1; i++) 124 payload[i] = 'a' + (i % 16); 125 payload[sizeof(payload) - 1] = '\0'; 126 tp_proto.mutable_for_testing()->set_str(payload); 127 std::string ser_buf = tp_proto.SerializeAsString(); 128 tp.AddSlice({ser_buf.data(), ser_buf.size()}); 129 130 std::tie(preamble, preamble_size) = tp.GetProtoPreamble(); 131 ASSERT_EQ(3u, preamble_size); 132 133 // Verify that the content is actually parsable using libprotobuf. 134 char buf[512]; 135 memcpy(buf, preamble, preamble_size); 136 ASSERT_EQ(1u, tp.slices().size()); 137 memcpy(&buf[preamble_size], tp.slices()[0].start, tp.slices()[0].size); 138 protos::Trace trace; 139 ASSERT_TRUE( 140 trace.ParseFromArray(buf, static_cast<int>(preamble_size + tp.size()))); 141 ASSERT_EQ(1, trace.packet_size()); 142 ASSERT_EQ(payload, trace.packet(0).for_testing().str()); 143 } 144 145 TEST(TracePacketTest, MoveOperators) { 146 char buf1[5]{}; 147 char buf2[7]{}; 148 149 TracePacket tp; 150 tp.AddSlice(buf1, sizeof(buf1)); 151 tp.AddSlice(buf2, sizeof(buf2)); 152 tp.AddSlice(Slice::Allocate(11)); 153 tp.AddSlice(Slice(std::unique_ptr<std::string>(new std::string("foobar")))); 154 155 TracePacket moved_tp(std::move(tp)); 156 ASSERT_EQ(0u, tp.size()); 157 ASSERT_TRUE(tp.slices().empty()); 158 ASSERT_EQ(4u, moved_tp.slices().size()); 159 ASSERT_EQ(5u + 7u + 11u + 6u, moved_tp.size()); 160 161 TracePacket moved_tp_2; 162 moved_tp_2 = std::move(moved_tp); 163 ASSERT_EQ(0u, moved_tp.size()); 164 ASSERT_TRUE(moved_tp.slices().empty()); 165 ASSERT_EQ(4u, moved_tp_2.slices().size()); 166 ASSERT_EQ(5u + 7u + 11u + 6u, moved_tp_2.size()); 167 } 168 169 } // namespace 170 } // namespace perfetto 171