xref: /aosp_15_r20/external/perfetto/src/profiling/memory/wire_protocol_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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/profiling/memory/wire_protocol.h"
18 
19 #include <sys/socket.h>
20 #include <sys/types.h>
21 
22 #include "perfetto/base/logging.h"
23 #include "perfetto/ext/base/scoped_file.h"
24 #include "perfetto/ext/base/unix_socket.h"
25 #include "test/gtest_and_gmock.h"
26 
27 namespace perfetto {
28 namespace profiling {
29 
30 bool operator==(const AllocMetadata& one, const AllocMetadata& other);
operator ==(const AllocMetadata & one,const AllocMetadata & other)31 bool operator==(const AllocMetadata& one, const AllocMetadata& other) {
32   return std::tie(one.sequence_number, one.alloc_size, one.sample_size,
33                   one.alloc_address, one.stack_pointer,
34                   one.clock_monotonic_coarse_timestamp, one.heap_id,
35                   one.arch) == std::tie(other.sequence_number, other.alloc_size,
36                                         other.sample_size, other.alloc_address,
37                                         other.stack_pointer,
38                                         other.clock_monotonic_coarse_timestamp,
39                                         other.heap_id, other.arch) &&
40          memcmp(one.register_data, other.register_data, kMaxRegisterDataSize) ==
41              0;
42 }
43 
44 bool operator==(const FreeEntry& one, const FreeEntry& other);
operator ==(const FreeEntry & one,const FreeEntry & other)45 bool operator==(const FreeEntry& one, const FreeEntry& other) {
46   return (std::tie(one.sequence_number, one.addr, one.heap_id) ==
47           std::tie(other.sequence_number, other.addr, other.heap_id));
48 }
49 
50 namespace {
51 
CopyFD(int fd)52 base::ScopedFile CopyFD(int fd) {
53   int sv[2];
54   PERFETTO_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0);
55   base::UnixSocketRaw send_sock(base::ScopedFile(sv[0]),
56                                 base::SockFamily::kUnix,
57                                 base::SockType::kStream);
58   base::UnixSocketRaw recv_sock(base::ScopedFile(sv[1]),
59                                 base::SockFamily::kUnix,
60                                 base::SockType::kStream);
61   char msg[] = "a";
62   PERFETTO_CHECK(send_sock.Send(msg, sizeof(msg), &fd, 1));
63   base::ScopedFile res;
64   recv_sock.Receive(msg, sizeof(msg), &res, 1);
65   return res;
66 }
67 
68 constexpr auto kShmemSize = 1048576;
69 
TEST(WireProtocolTest,AllocMessage)70 TEST(WireProtocolTest, AllocMessage) {
71   char payload[] = {0x77, 0x77, 0x77, 0x00};
72   WireMessage msg = {};
73   msg.record_type = RecordType::Malloc;
74   AllocMetadata metadata = {};
75   metadata.sequence_number = 0xA1A2A3A4A5A6A7A8;
76   metadata.alloc_size = 0xB1B2B3B4B5B6B7B8;
77   metadata.alloc_address = 0xC1C2C3C4C5C6C7C8;
78   metadata.stack_pointer = 0xD1D2D3D4D5D6D7D8;
79   metadata.arch = unwindstack::ARCH_X86;
80   for (size_t i = 0; i < kMaxRegisterDataSize; ++i)
81     metadata.register_data[i] = 0x66;
82   msg.alloc_header = &metadata;
83   msg.payload = payload;
84   msg.payload_size = sizeof(payload);
85 
86   auto shmem_client = SharedRingBuffer::Create(kShmemSize);
87   ASSERT_TRUE(shmem_client);
88   ASSERT_TRUE(shmem_client->is_valid());
89   auto shmem_server = SharedRingBuffer::Attach(CopyFD(shmem_client->fd()));
90 
91   ASSERT_GE(SendWireMessage(&shmem_client.value(), msg), 0);
92 
93   auto buf = shmem_server->BeginRead();
94   ASSERT_TRUE(buf);
95   WireMessage recv_msg;
96   ASSERT_TRUE(ReceiveWireMessage(reinterpret_cast<char*>(buf.data), buf.size,
97                                  &recv_msg));
98 
99   ASSERT_EQ(recv_msg.record_type, msg.record_type);
100   ASSERT_EQ(*recv_msg.alloc_header, *msg.alloc_header);
101   ASSERT_EQ(recv_msg.payload_size, msg.payload_size);
102   ASSERT_STREQ(recv_msg.payload, msg.payload);
103 
104   shmem_server->EndRead(std::move(buf));
105 }
106 
TEST(WireProtocolTest,FreeMessage)107 TEST(WireProtocolTest, FreeMessage) {
108   WireMessage msg = {};
109   msg.record_type = RecordType::Free;
110   FreeEntry entry = {};
111   entry.sequence_number = 0x111111111111111;
112   entry.addr = 0x222222222222222;
113   msg.free_header = &entry;
114 
115   auto shmem_client = SharedRingBuffer::Create(kShmemSize);
116   ASSERT_TRUE(shmem_client);
117   ASSERT_TRUE(shmem_client->is_valid());
118   auto shmem_server = SharedRingBuffer::Attach(CopyFD(shmem_client->fd()));
119 
120   ASSERT_GE(SendWireMessage(&shmem_client.value(), msg), 0);
121 
122   auto buf = shmem_server->BeginRead();
123   ASSERT_TRUE(buf);
124   WireMessage recv_msg;
125   ASSERT_TRUE(ReceiveWireMessage(reinterpret_cast<char*>(buf.data), buf.size,
126                                  &recv_msg));
127 
128   ASSERT_EQ(recv_msg.record_type, msg.record_type);
129   ASSERT_EQ(*recv_msg.free_header, *msg.free_header);
130   ASSERT_EQ(recv_msg.payload_size, msg.payload_size);
131 
132   shmem_server->EndRead(std::move(buf));
133 }
134 
TEST(GetHeapSamplingInterval,Default)135 TEST(GetHeapSamplingInterval, Default) {
136   ClientConfiguration cli_config{};
137   cli_config.all_heaps = true;
138   cli_config.num_heaps = 0;
139   cli_config.default_interval = 4096u;
140   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 4096u);
141 }
142 
TEST(GetHeapSamplingInterval,Selected)143 TEST(GetHeapSamplingInterval, Selected) {
144   ClientConfiguration cli_config{};
145   cli_config.all_heaps = false;
146   cli_config.num_heaps = 1;
147   cli_config.default_interval = 1;
148   memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
149   cli_config.heaps[0].interval = 4096u;
150   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 4096u);
151   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 0u);
152 }
153 
TEST(GetHeapSamplingInterval,SelectedAndDefault)154 TEST(GetHeapSamplingInterval, SelectedAndDefault) {
155   ClientConfiguration cli_config{};
156   cli_config.all_heaps = true;
157   cli_config.num_heaps = 1;
158   cli_config.default_interval = 1;
159   memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
160   cli_config.heaps[0].interval = 4096u;
161   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 4096u);
162   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 1u);
163 }
164 
TEST(GetHeapSamplingInterval,DisabledAndDefault)165 TEST(GetHeapSamplingInterval, DisabledAndDefault) {
166   ClientConfiguration cli_config{};
167   cli_config.all_heaps = true;
168   cli_config.num_heaps = 1;
169   cli_config.default_interval = 1;
170   memcpy(cli_config.heaps[0].name, "something", sizeof("something"));
171   cli_config.heaps[0].interval = 0u;
172   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "something"), 0u);
173   EXPECT_EQ(GetHeapSamplingInterval(cli_config, "else"), 1u);
174 }
175 
176 }  // namespace
177 }  // namespace profiling
178 }  // namespace perfetto
179