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