blob: 873d977614942260f2d00bccad8b598a5bdba7ba [file] [log] [blame]
Kaido Kert56d7c4e2024-04-13 12:59:27 -07001/*
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
27namespace perfetto {
28namespace profiling {
29
30bool operator==(const AllocMetadata& one, const AllocMetadata& other);
31bool 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
44bool operator==(const FreeEntry& one, const FreeEntry& other);
45bool 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
50namespace {
51
52base::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
68constexpr auto kShmemSize = 1048576;
69
70TEST(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
107TEST(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
135TEST(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
143TEST(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
154TEST(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
165TEST(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