Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2020 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 | |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 17 | #include <stdio.h> |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 18 | #include <stdlib.h> |
| 19 | #include <sys/types.h> |
| 20 | |
Ryan Savitski | 38eb1d1 | 2021-01-20 13:59:04 +0000 | [diff] [blame] | 21 | #include <string> |
| 22 | |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 23 | #include "perfetto/base/logging.h" |
Daniele Di Proietto | 5ce0d14 | 2021-11-01 18:30:44 +0000 | [diff] [blame] | 24 | #include "perfetto/ext/base/android_utils.h" |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 25 | #include "perfetto/ext/base/string_utils.h" |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 26 | #include "perfetto/tracing/core/data_source_config.h" |
| 27 | #include "src/base/test/test_task_runner.h" |
Primiano Tucci | d6dc0c0 | 2020-12-01 16:15:28 +0100 | [diff] [blame] | 28 | #include "test/android_test_utils.h" |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 29 | #include "test/gtest_and_gmock.h" |
| 30 | #include "test/test_helper.h" |
| 31 | |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 32 | #include "protos/perfetto/common/perf_events.gen.h" |
| 33 | #include "protos/perfetto/config/process_stats/process_stats_config.gen.h" |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 34 | #include "protos/perfetto/config/profiling/perf_event_config.gen.h" |
| 35 | #include "protos/perfetto/trace/profiling/profile_common.gen.h" |
| 36 | #include "protos/perfetto/trace/profiling/profile_packet.gen.h" |
| 37 | #include "protos/perfetto/trace/trace_packet.gen.h" |
| 38 | |
| 39 | namespace perfetto { |
| 40 | namespace { |
| 41 | |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 42 | // Skip these tests if the device in question doesn't have the necessary kernel |
| 43 | // LSM hooks in perf_event_open. This comes up when a device with an older |
| 44 | // kernel upgrades to R. |
| 45 | bool HasPerfLsmHooks() { |
Daniele Di Proietto | 5ce0d14 | 2021-11-01 18:30:44 +0000 | [diff] [blame] | 46 | return base::GetAndroidProp("sys.init.perf_lsm_hooks") == "1"; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 47 | } |
| 48 | |
Ryan Savitski | 38eb1d1 | 2021-01-20 13:59:04 +0000 | [diff] [blame] | 49 | std::string RandomSessionName() { |
| 50 | std::random_device rd; |
| 51 | std::default_random_engine generator(rd()); |
Daniele Di Proietto | 69e7f7d | 2022-03-08 13:39:23 +0000 | [diff] [blame] | 52 | std::uniform_int_distribution<> distribution('a', 'z'); |
Ryan Savitski | 38eb1d1 | 2021-01-20 13:59:04 +0000 | [diff] [blame] | 53 | |
| 54 | constexpr size_t kSessionNameLen = 20; |
| 55 | std::string result(kSessionNameLen, '\0'); |
| 56 | for (size_t i = 0; i < kSessionNameLen; ++i) |
Daniele Di Proietto | 69e7f7d | 2022-03-08 13:39:23 +0000 | [diff] [blame] | 57 | result[i] = static_cast<char>(distribution(generator)); |
Ryan Savitski | 38eb1d1 | 2021-01-20 13:59:04 +0000 | [diff] [blame] | 58 | return result; |
| 59 | } |
| 60 | |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 61 | std::vector<protos::gen::TracePacket> CollectTrace( |
| 62 | base::TestTaskRunner* task_runner, |
| 63 | const TraceConfig& trace_config) { |
| 64 | TestHelper helper(task_runner); |
| 65 | helper.ConnectConsumer(); |
| 66 | helper.WaitForConsumerConnect(); |
| 67 | |
| 68 | helper.StartTracing(trace_config); |
| 69 | helper.WaitForTracingDisabled(15000 /*ms*/); |
| 70 | helper.ReadData(); |
| 71 | helper.WaitForReadData(); |
| 72 | return helper.trace(); |
| 73 | } |
| 74 | |
Florian Mayer | ca07498 | 2021-04-28 17:09:25 +0100 | [diff] [blame] | 75 | std::vector<protos::gen::TracePacket> ProfileSystemWide(std::string app_name) { |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 76 | base::TestTaskRunner task_runner; |
| 77 | |
| 78 | // (re)start the target app's main activity |
| 79 | if (IsAppRunning(app_name)) { |
| 80 | StopApp(app_name, "old.app.stopped", &task_runner); |
Daniele Di Proietto | a615209 | 2022-03-02 21:28:42 +0000 | [diff] [blame] | 81 | task_runner.RunUntilCheckpoint("old.app.stopped", 10000 /*ms*/); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 82 | } |
| 83 | StartAppActivity(app_name, "BusyWaitActivity", "target.app.running", |
| 84 | &task_runner, |
| 85 | /*delay_ms=*/100); |
Daniele Di Proietto | a615209 | 2022-03-02 21:28:42 +0000 | [diff] [blame] | 86 | task_runner.RunUntilCheckpoint("target.app.running", 10000 /*ms*/); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 87 | |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 88 | // build config |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 89 | TraceConfig trace_config; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 90 | trace_config.add_buffers()->set_size_kb(20 * 1024); |
| 91 | trace_config.set_duration_ms(3000); |
| 92 | trace_config.set_data_source_stop_timeout_ms(8000); |
Ryan Savitski | 38eb1d1 | 2021-01-20 13:59:04 +0000 | [diff] [blame] | 93 | trace_config.set_unique_session_name(RandomSessionName().c_str()); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 94 | |
| 95 | auto* ds_config = trace_config.add_data_sources()->mutable_config(); |
| 96 | ds_config->set_name("linux.perf"); |
| 97 | ds_config->set_target_buffer(0); |
| 98 | |
| 99 | protos::gen::PerfEventConfig perf_config; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 100 | perf_config.set_all_cpus(true); |
| 101 | perf_config.set_sampling_frequency(10); // Hz |
| 102 | ds_config->set_perf_event_config_raw(perf_config.SerializeAsString()); |
| 103 | |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 104 | return CollectTrace(&task_runner, trace_config); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | void AssertHasSampledStacksForPid(std::vector<protos::gen::TracePacket> packets, |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 108 | int pid) { |
| 109 | uint32_t target_pid = static_cast<uint32_t>(pid); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 110 | ASSERT_GT(packets.size(), 0u); |
| 111 | |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 112 | int total_perf_packets = 0; |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 113 | int lost_records_packets = 0; |
| 114 | int full_samples = 0; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 115 | int target_samples = 0; |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 116 | int target_skipped_samples = 0; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 117 | for (const auto& packet : packets) { |
| 118 | if (!packet.has_perf_sample()) |
| 119 | continue; |
| 120 | |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 121 | total_perf_packets++; |
| 122 | EXPECT_GT(packet.timestamp(), 0u) << "all packets should have a timestamp"; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 123 | const auto& sample = packet.perf_sample(); |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 124 | if (sample.has_kernel_records_lost()) { |
| 125 | lost_records_packets++; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 126 | continue; |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 127 | } |
| 128 | if (sample.has_sample_skipped_reason()) { |
| 129 | if (sample.pid() == target_pid) |
| 130 | target_skipped_samples++; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 131 | continue; |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 132 | } |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 133 | |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 134 | full_samples++; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 135 | EXPECT_GT(sample.tid(), 0u); |
| 136 | EXPECT_GT(sample.callstack_iid(), 0u); |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 137 | |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 138 | if (sample.pid() == target_pid) |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 139 | target_samples++; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 140 | } |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 141 | |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 142 | // log summary even if successful |
| 143 | base::StackString<512> log( |
| 144 | "target_pid: %d, packets.size(): %zu, total_perf_packets: %d, " |
| 145 | "full_samples: %d, lost_records_packets: %d, target_skipped_samples: %d", |
| 146 | target_pid, packets.size(), total_perf_packets, full_samples, |
| 147 | lost_records_packets, target_skipped_samples); |
| 148 | PERFETTO_LOG("%s", log.c_str()); |
| 149 | |
| 150 | EXPECT_GT(target_samples, 0) << log.c_str() << "\n"; |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | void AssertNoStacksForPid(std::vector<protos::gen::TracePacket> packets, |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 154 | int pid) { |
| 155 | uint32_t target_pid = static_cast<uint32_t>(pid); |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 156 | // The process can still be sampled, but the stacks should be discarded |
| 157 | // without unwinding. |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 158 | for (const auto& packet : packets) { |
Ryan Savitski | 3a174a5 | 2020-02-26 13:31:17 +0000 | [diff] [blame] | 159 | if (packet.perf_sample().pid() == target_pid) { |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 160 | EXPECT_EQ(packet.perf_sample().callstack_iid(), 0u); |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 161 | EXPECT_TRUE(packet.perf_sample().has_sample_skipped_reason()); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 162 | } |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | TEST(TracedPerfCtsTest, SystemWideDebuggableApp) { |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 167 | if (!HasPerfLsmHooks()) |
Ryan Savitski | aa9399a | 2020-02-24 22:45:04 +0000 | [diff] [blame] | 168 | GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks"; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 169 | |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 170 | std::string app_name = "android.perfetto.cts.app.debuggable"; |
| 171 | const auto& packets = ProfileSystemWide(app_name); |
| 172 | int app_pid = PidForProcessName(app_name); |
| 173 | ASSERT_GT(app_pid, 0) << "failed to find pid for target process"; |
| 174 | |
| 175 | AssertHasSampledStacksForPid(packets, app_pid); |
Florian Mayer | 3cb0424 | 2020-02-25 13:26:42 +0000 | [diff] [blame] | 176 | PERFETTO_CHECK(IsAppRunning(app_name)); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 177 | StopApp(app_name); |
| 178 | } |
| 179 | |
| 180 | TEST(TracedPerfCtsTest, SystemWideProfileableApp) { |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 181 | if (!HasPerfLsmHooks()) |
Ryan Savitski | aa9399a | 2020-02-24 22:45:04 +0000 | [diff] [blame] | 182 | GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks"; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 183 | |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 184 | std::string app_name = "android.perfetto.cts.app.profileable"; |
| 185 | const auto& packets = ProfileSystemWide(app_name); |
| 186 | int app_pid = PidForProcessName(app_name); |
| 187 | ASSERT_GT(app_pid, 0) << "failed to find pid for target process"; |
| 188 | |
| 189 | AssertHasSampledStacksForPid(packets, app_pid); |
Florian Mayer | 3cb0424 | 2020-02-25 13:26:42 +0000 | [diff] [blame] | 190 | PERFETTO_CHECK(IsAppRunning(app_name)); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 191 | StopApp(app_name); |
| 192 | } |
| 193 | |
Florian Mayer | dc9abfe | 2021-04-26 12:06:18 +0100 | [diff] [blame] | 194 | TEST(TracedPerfCtsTest, SystemWideNonProfileableApp) { |
| 195 | if (!HasPerfLsmHooks()) |
| 196 | GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks"; |
| 197 | |
| 198 | std::string app_name = "android.perfetto.cts.app.nonprofileable"; |
| 199 | const auto& packets = ProfileSystemWide(app_name); |
| 200 | int app_pid = PidForProcessName(app_name); |
| 201 | ASSERT_GT(app_pid, 0) << "failed to find pid for target process"; |
| 202 | |
| 203 | if (!IsUserBuild()) |
| 204 | AssertHasSampledStacksForPid(packets, app_pid); |
| 205 | else |
| 206 | AssertNoStacksForPid(packets, app_pid); |
| 207 | PERFETTO_CHECK(IsAppRunning(app_name)); |
| 208 | StopApp(app_name); |
| 209 | } |
| 210 | |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 211 | TEST(TracedPerfCtsTest, SystemWideReleaseApp) { |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 212 | if (!HasPerfLsmHooks()) |
Ryan Savitski | aa9399a | 2020-02-24 22:45:04 +0000 | [diff] [blame] | 213 | GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks"; |
Ryan Savitski | 86bd0e9 | 2020-02-24 16:42:33 +0000 | [diff] [blame] | 214 | |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 215 | std::string app_name = "android.perfetto.cts.app.release"; |
| 216 | const auto& packets = ProfileSystemWide(app_name); |
| 217 | int app_pid = PidForProcessName(app_name); |
| 218 | ASSERT_GT(app_pid, 0) << "failed to find pid for target process"; |
| 219 | |
Ryan Savitski | 4aff79a | 2021-02-19 14:03:31 +0000 | [diff] [blame] | 220 | if (!IsUserBuild()) |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 221 | AssertHasSampledStacksForPid(packets, app_pid); |
| 222 | else |
| 223 | AssertNoStacksForPid(packets, app_pid); |
| 224 | |
Florian Mayer | 3cb0424 | 2020-02-25 13:26:42 +0000 | [diff] [blame] | 225 | PERFETTO_CHECK(IsAppRunning(app_name)); |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 226 | StopApp(app_name); |
| 227 | } |
| 228 | |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 229 | // Loads a platform process with work (we use traced_probes which runs as |
| 230 | // AID_NOBODY), and profiles it. |
| 231 | TEST(TracedPerfCtsTest, ProfilePlatformProcess) { |
| 232 | if (!HasPerfLsmHooks()) |
| 233 | GTEST_SKIP() << "skipped due to lack of perf_event_open LSM hooks"; |
| 234 | |
| 235 | int target_pid = PidForProcessName("/system/bin/traced_probes"); |
| 236 | ASSERT_GT(target_pid, 0) << "failed to find pid for target process"; |
| 237 | |
| 238 | // Construct config. |
| 239 | TraceConfig trace_config; |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 240 | trace_config.add_buffers()->set_size_kb(64); |
| 241 | trace_config.add_buffers()->set_size_kb(1024); |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 242 | trace_config.set_duration_ms(3000); |
| 243 | trace_config.set_data_source_stop_timeout_ms(8000); |
| 244 | trace_config.set_unique_session_name(RandomSessionName().c_str()); |
| 245 | |
| 246 | // process.stats to cause work in traced_probes |
| 247 | protos::gen::ProcessStatsConfig ps_config; |
| 248 | ps_config.set_proc_stats_poll_ms(100); |
| 249 | ps_config.set_record_thread_names(true); |
| 250 | |
| 251 | auto* ds_config = trace_config.add_data_sources()->mutable_config(); |
| 252 | ds_config->set_name("linux.process_stats"); |
| 253 | ds_config->set_process_stats_config_raw(ps_config.SerializeAsString()); |
| 254 | |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 255 | // capture callstacks of traced_probes descheduling |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 256 | protos::gen::PerfEventConfig perf_config; |
| 257 | auto* timebase = perf_config.mutable_timebase(); |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 258 | timebase->set_counter(protos::gen::PerfEvents::SW_CONTEXT_SWITCHES); |
| 259 | timebase->set_period(1); |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 260 | auto* callstacks = perf_config.mutable_callstack_sampling(); |
| 261 | auto* scope = callstacks->mutable_scope(); |
| 262 | scope->add_target_pid(target_pid); |
| 263 | |
| 264 | ds_config = trace_config.add_data_sources()->mutable_config(); |
| 265 | ds_config->set_name("linux.perf"); |
Ryan Savitski | ab3ead5 | 2023-02-22 15:30:52 +0000 | [diff] [blame] | 266 | ds_config->set_target_buffer(1); |
Ryan Savitski | 08995e1 | 2023-02-21 13:48:57 +0000 | [diff] [blame] | 267 | ds_config->set_perf_event_config_raw(perf_config.SerializeAsString()); |
| 268 | |
| 269 | // Collect trace. |
| 270 | base::TestTaskRunner task_runner; |
| 271 | auto packets = CollectTrace(&task_runner, trace_config); |
| 272 | |
| 273 | int target_pid_after = PidForProcessName("/system/bin/traced_probes"); |
| 274 | ASSERT_EQ(target_pid, target_pid_after) << "traced_probes died during test"; |
| 275 | |
| 276 | if (!IsUserBuild()) |
| 277 | AssertHasSampledStacksForPid(packets, target_pid); |
| 278 | else |
| 279 | AssertNoStacksForPid(packets, target_pid); |
| 280 | } |
| 281 | |
Ryan Savitski | 9fa7200 | 2020-02-19 14:31:20 +0000 | [diff] [blame] | 282 | } // namespace |
| 283 | } // namespace perfetto |