1 /*
2 * Copyright (C) 2019 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 <cinttypes>
18 #include <string>
19
20 #include "perfetto/base/logging.h"
21 #include "perfetto/tracing/core/data_source_config.h"
22
23 #include "src/base/test/test_task_runner.h"
24 #include "test/android_test_utils.h"
25 #include "test/cts/heapprofd_test_helper.h"
26 #include "test/gtest_and_gmock.h"
27 #include "test/test_helper.h"
28
29 #include "protos/perfetto/config/process_stats/process_stats_config.gen.h"
30 #include "protos/perfetto/config/profiling/heapprofd_config.gen.h"
31
32 namespace perfetto {
33 namespace {
34
35 // Size of individual (repeated) allocations done by the test apps (must be kept
36 // in sync with their sources).
37 constexpr uint64_t kTestSamplingInterval = 4096;
38 constexpr uint64_t kExpectedIndividualAllocSz = 4153;
39 // Tests rely on the sampling behaviour where allocations larger than the
40 // sampling interval are recorded at their actual size.
41 static_assert(kExpectedIndividualAllocSz > kTestSamplingInterval,
42 "kTestSamplingInterval invalid");
43
44 // Activity that runs a JNI thread that repeatedly calls
45 // malloc(kExpectedIndividualAllocSz).
46 static char kMallocActivity[] = "MainActivity";
47
TEST(HeapprofdCtsTest,DebuggableAppRuntime)48 TEST(HeapprofdCtsTest, DebuggableAppRuntime) {
49 std::string app_name = "android.perfetto.cts.app.debuggable";
50 const auto& packets = ProfileRuntime(
51 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
52 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
53 StopApp(app_name);
54 }
55
TEST(HeapprofdCtsTest,DebuggableAppStartup)56 TEST(HeapprofdCtsTest, DebuggableAppStartup) {
57 std::string app_name = "android.perfetto.cts.app.debuggable";
58 const auto& packets = ProfileStartup(
59 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
60 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
61 StopApp(app_name);
62 }
63
TEST(HeapprofdCtsTest,ProfileableAppRuntime)64 TEST(HeapprofdCtsTest, ProfileableAppRuntime) {
65 std::string app_name = "android.perfetto.cts.app.profileable";
66 const auto& packets = ProfileRuntime(
67 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
68 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
69 StopApp(app_name);
70 }
71
TEST(HeapprofdCtsTest,ProfileableAppStartup)72 TEST(HeapprofdCtsTest, ProfileableAppStartup) {
73 std::string app_name = "android.perfetto.cts.app.profileable";
74 const auto& packets = ProfileStartup(
75 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
76 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
77 StopApp(app_name);
78 }
79
TEST(HeapprofdCtsTest,ReleaseAppRuntime)80 TEST(HeapprofdCtsTest, ReleaseAppRuntime) {
81 std::string app_name = "android.perfetto.cts.app.release";
82 const auto& packets = ProfileRuntime(
83 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
84
85 if (IsUserBuild())
86 AssertNoProfileContents(packets);
87 else
88 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
89 StopApp(app_name);
90 }
91
TEST(HeapprofdCtsTest,ReleaseAppStartup)92 TEST(HeapprofdCtsTest, ReleaseAppStartup) {
93 std::string app_name = "android.perfetto.cts.app.release";
94 const auto& packets = ProfileStartup(
95 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
96
97 if (IsUserBuild())
98 AssertNoProfileContents(packets);
99 else
100 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
101 StopApp(app_name);
102 }
103
TEST(HeapprofdCtsTest,NonProfileableAppRuntime)104 TEST(HeapprofdCtsTest, NonProfileableAppRuntime) {
105 std::string app_name = "android.perfetto.cts.app.nonprofileable";
106 const auto& packets = ProfileRuntime(
107 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
108 if (IsUserBuild())
109 AssertNoProfileContents(packets);
110 else
111 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
112 StopApp(app_name);
113 }
114
TEST(HeapprofdCtsTest,NonProfileableAppStartup)115 TEST(HeapprofdCtsTest, NonProfileableAppStartup) {
116 std::string app_name = "android.perfetto.cts.app.nonprofileable";
117 const auto& packets = ProfileStartup(
118 app_name, kMallocActivity, kTestSamplingInterval, /*heap_names=*/{});
119 if (IsUserBuild())
120 AssertNoProfileContents(packets);
121 else
122 AssertExpectedMallocsPresent(kExpectedIndividualAllocSz, packets);
123 StopApp(app_name);
124 }
125
TEST(HeapprofdCtsTest,ProfilePlatformProcess)126 TEST(HeapprofdCtsTest, ProfilePlatformProcess) {
127 int target_pid = PidForProcessName("/system/bin/traced_probes");
128 ASSERT_GT(target_pid, 0) << "failed to find pid for target process";
129
130 // Construct config.
131 TraceConfig trace_config;
132 trace_config.add_buffers()->set_size_kb(20 * 1024);
133 trace_config.set_duration_ms(3000);
134 trace_config.set_data_source_stop_timeout_ms(8000);
135 trace_config.set_unique_session_name(RandomSessionName().c_str());
136
137 // process.stats to cause work in traced_probes
138 protos::gen::ProcessStatsConfig ps_config;
139 ps_config.set_proc_stats_poll_ms(100);
140 ps_config.set_record_thread_names(true);
141
142 auto* ds_config = trace_config.add_data_sources()->mutable_config();
143 ds_config->set_name("linux.process_stats");
144 ds_config->set_process_stats_config_raw(ps_config.SerializeAsString());
145
146 // profile native heap of traced_probes
147 protos::gen::HeapprofdConfig heapprofd_config;
148 heapprofd_config.set_sampling_interval_bytes(kTestSamplingInterval);
149 heapprofd_config.add_pid(static_cast<uint64_t>(target_pid));
150 heapprofd_config.set_block_client(true);
151
152 ds_config = trace_config.add_data_sources()->mutable_config();
153 ds_config->set_name("android.heapprofd");
154 ds_config->set_heapprofd_config_raw(heapprofd_config.SerializeAsString());
155
156 // Collect trace.
157 base::TestTaskRunner task_runner;
158 TestHelper helper(&task_runner);
159 helper.ConnectConsumer();
160 helper.WaitForConsumerConnect();
161
162 helper.StartTracing(trace_config);
163 helper.WaitForTracingDisabled(15000 /*ms*/);
164 helper.ReadData();
165 helper.WaitForReadData();
166 auto packets = helper.trace();
167
168 int target_pid_after = PidForProcessName("/system/bin/traced_probes");
169 ASSERT_EQ(target_pid, target_pid_after) << "traced_probes died during test";
170
171 if (IsUserBuild())
172 AssertNoProfileContents(packets);
173 else
174 AssertHasSampledAllocs(packets);
175 }
176
177 } // namespace
178 } // namespace perfetto
179