blob: ce4d1b29ca6a422baf1ea4c0c312faf28b2e8150 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/base/unix_task_runner.h"
#include "perfetto/heap_profile.h"
#include "src/profiling/memory/heap_profile_internal.h"
#include "src/profiling/memory/client.h"
#include "src/profiling/memory/client_api_factory.h"
#include "src/profiling/memory/shared_ring_buffer.h"
#include "src/profiling/memory/wire_protocol.h"
#include "test/gtest_and_gmock.h"
#include <memory>
namespace perfetto {
namespace profiling {
namespace {
ClientConfiguration g_client_config;
int g_shmem_fd;
base::UnixSocketRaw& GlobalServerSocket() {
static base::UnixSocketRaw* srv_sock = new base::UnixSocketRaw;
return *srv_sock;
}
void DisconnectGlobalServerSocket() {
base::UnixSocketRaw destroy;
std::swap(destroy, GlobalServerSocket());
}
} // namespace
// This is called by AHeapProfile_initSession (client_api.cc) to construct a
// client. The Client API requires to be linked against another compliation
// unit that provides this function. This way, it can be used in different
// circumstances (central heapprofd, fork heapprofd) and be agnostic about the
// details. This is is used to create a test Client here.
void StartHeapprofdIfStatic() {}
std::shared_ptr<Client> ConstructClient(
UnhookedAllocator<perfetto::profiling::Client> unhooked_allocator) {
base::UnixSocketRaw cli_sock;
base::UnixSocketRaw& srv_sock = GlobalServerSocket();
std::tie(cli_sock, srv_sock) = base::UnixSocketRaw::CreatePairPosix(
base::SockFamily::kUnix, base::SockType::kStream);
auto ringbuf = SharedRingBuffer::Create(8 * 1048576);
PERFETTO_CHECK(ringbuf);
PERFETTO_CHECK(cli_sock);
PERFETTO_CHECK(srv_sock);
g_shmem_fd = ringbuf->fd();
return std::allocate_shared<Client>(unhooked_allocator, std::move(cli_sock),
g_client_config, std::move(*ringbuf),
getpid(), GetMainThreadStackRange());
}
namespace {
TEST(ClientApiTest, NoClient) {
uint32_t heap_id = AHeapProfile_registerHeap(AHeapInfo_create("NoClient"));
EXPECT_FALSE(AHeapProfile_reportAllocation(heap_id, 1, 1));
}
TEST(ClientApiTest, ClientEnabledHeap) {
uint32_t heap_id =
AHeapProfile_registerHeap(AHeapInfo_create("ClientEnabledHeap"));
ClientConfiguration client_config{};
client_config.default_interval = 1;
strcpy(&client_config.heaps[0].name[0], "ClientEnabledHeap");
client_config.heaps[0].interval = 1;
client_config.num_heaps = 1;
g_client_config = client_config;
AHeapProfile_initSession(malloc, free);
PERFETTO_CHECK(g_shmem_fd);
auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
g_shmem_fd = 0;
PERFETTO_CHECK(ringbuf);
EXPECT_TRUE(AHeapProfile_reportAllocation(heap_id, 1, 1));
// Check that the service received something on the shmem.
EXPECT_TRUE(ringbuf->BeginRead());
DisconnectGlobalServerSocket();
ringbuf->SetShuttingDown();
EXPECT_FALSE(AHeapProfile_reportAllocation(heap_id, 1, 1));
}
TEST(ClientApiTest, ClientAllHeaps) {
uint32_t heap_id =
AHeapProfile_registerHeap(AHeapInfo_create("ClientAllHeaps"));
ClientConfiguration client_config{};
client_config.default_interval = 1;
client_config.all_heaps = true;
g_client_config = client_config;
AHeapProfile_initSession(malloc, free);
PERFETTO_CHECK(g_shmem_fd);
auto ringbuf = SharedRingBuffer::Attach(base::ScopedFile(dup(g_shmem_fd)));
g_shmem_fd = 0;
PERFETTO_CHECK(ringbuf);
EXPECT_TRUE(AHeapProfile_reportAllocation(heap_id, 1, 1));
// Check that the service received something on the shmem.
EXPECT_TRUE(ringbuf->BeginRead());
DisconnectGlobalServerSocket();
ringbuf->SetShuttingDown();
EXPECT_FALSE(AHeapProfile_reportAllocation(heap_id, 1, 1));
}
} // namespace
} // namespace profiling
} // namespace perfetto