Home | History | Annotate | Download | only in core
      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