1 /*
2 * Copyright (C) 2017 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/tracing/service/tracing_service_impl.h"
18
19 #include <atomic>
20 #include <cinttypes>
21 #include <cstdint>
22 #include <cstring>
23 #include <functional>
24 #include <map>
25 #include <memory>
26 #include <optional>
27 #include <set>
28 #include <string>
29 #include <thread>
30 #include <utility>
31 #include <vector>
32
33 #include "perfetto/base/build_config.h"
34 #include "perfetto/base/logging.h"
35 #include "perfetto/base/proc_utils.h"
36 #include "perfetto/base/time.h"
37 #include "perfetto/ext/base/file_utils.h"
38 #include "perfetto/ext/base/string_utils.h"
39 #include "perfetto/ext/base/sys_types.h"
40 #include "perfetto/ext/base/temp_file.h"
41 #include "perfetto/ext/base/utils.h"
42 #include "perfetto/ext/base/uuid.h"
43 #include "perfetto/ext/tracing/core/basic_types.h"
44 #include "perfetto/ext/tracing/core/client_identity.h"
45 #include "perfetto/ext/tracing/core/consumer.h"
46 #include "perfetto/ext/tracing/core/producer.h"
47 #include "perfetto/ext/tracing/core/shared_memory.h"
48 #include "perfetto/ext/tracing/core/shared_memory_abi.h"
49 #include "perfetto/ext/tracing/core/trace_writer.h"
50 #include "perfetto/ext/tracing/core/tracing_service.h"
51 #include "perfetto/protozero/contiguous_memory_range.h"
52 #include "perfetto/protozero/message_arena.h"
53 #include "perfetto/protozero/scattered_stream_writer.h"
54 #include "perfetto/tracing/buffer_exhausted_policy.h"
55 #include "perfetto/tracing/core/flush_flags.h"
56 #include "perfetto/tracing/core/forward_decls.h"
57 #include "protos/perfetto/common/builtin_clock.gen.h"
58 #include "protos/perfetto/trace/clock_snapshot.gen.h"
59 #include "protos/perfetto/trace/remote_clock_sync.gen.h"
60 #include "src/base/test/test_task_runner.h"
61 #include "src/protozero/filtering/filter_bytecode_generator.h"
62 #include "src/tracing/core/shared_memory_arbiter_impl.h"
63 #include "src/tracing/core/trace_writer_impl.h"
64 #include "src/tracing/test/mock_consumer.h"
65 #include "src/tracing/test/mock_producer.h"
66 #include "src/tracing/test/test_shared_memory.h"
67 #include "test/gtest_and_gmock.h"
68
69 #include "protos/perfetto/common/track_event_descriptor.gen.h"
70 #include "protos/perfetto/trace/perfetto/tracing_service_event.gen.h"
71 #include "protos/perfetto/trace/test_event.gen.h"
72 #include "protos/perfetto/trace/test_event.pbzero.h"
73 #include "protos/perfetto/trace/trace.gen.h"
74 #include "protos/perfetto/trace/trace_packet.gen.h"
75 #include "protos/perfetto/trace/trace_packet.pbzero.h"
76 #include "protos/perfetto/trace/trace_uuid.gen.h"
77 #include "protos/perfetto/trace/trigger.gen.h"
78
79 #if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
80 #include <zlib.h>
81 #include "src/tracing/service/zlib_compressor.h"
82 #endif
83
84 using ::testing::_;
85 using ::testing::AssertionFailure;
86 using ::testing::AssertionResult;
87 using ::testing::AssertionSuccess;
88 using ::testing::Contains;
89 using ::testing::ContainsRegex;
90 using ::testing::DoAll;
91 using ::testing::Each;
92 using ::testing::ElementsAreArray;
93 using ::testing::Eq;
94 using ::testing::ExplainMatchResult;
95 using ::testing::HasSubstr;
96 using ::testing::InSequence;
97 using ::testing::Invoke;
98 using ::testing::InvokeWithoutArgs;
99 using ::testing::IsEmpty;
100 using ::testing::Mock;
101 using ::testing::Ne;
102 using ::testing::Not;
103 using ::testing::Pointee;
104 using ::testing::Property;
105 using ::testing::SaveArg;
106 using ::testing::StrictMock;
107 using ::testing::StringMatchResultListener;
108 using ::testing::StrNe;
109 using ::testing::UnorderedElementsAre;
110
111 namespace perfetto {
112
113 namespace {
114 constexpr size_t kDefaultShmSizeKb = TracingServiceImpl::kDefaultShmSize / 1024;
115 constexpr size_t kDefaultShmPageSizeKb =
116 TracingServiceImpl::kDefaultShmPageSize / 1024;
117 constexpr size_t kMaxShmSizeKb = TracingServiceImpl::kMaxShmSize / 1024;
118
HasTriggerModeInternal(const std::vector<protos::gen::TracePacket> & packets,protos::gen::TraceConfig::TriggerConfig::TriggerMode mode)119 AssertionResult HasTriggerModeInternal(
120 const std::vector<protos::gen::TracePacket>& packets,
121 protos::gen::TraceConfig::TriggerConfig::TriggerMode mode) {
122 StringMatchResultListener matcher_result_string;
123 bool contains = ExplainMatchResult(
124 Contains(Property(
125 &protos::gen::TracePacket::trace_config,
126 Property(
127 &protos::gen::TraceConfig::trigger_config,
128 Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
129 Eq(mode))))),
130 packets, &matcher_result_string);
131 if (contains) {
132 return AssertionSuccess();
133 }
134 return AssertionFailure() << matcher_result_string.str();
135 }
136
137 MATCHER_P(HasTriggerMode, mode, "") {
138 return HasTriggerModeInternal(arg, mode);
139 }
140
141 MATCHER_P(LowerCase,
142 m,
143 "Lower case " + testing::DescribeMatcher<std::string>(m, negation)) {
144 return ExplainMatchResult(m, base::ToLower(arg), result_listener);
145 }
146
147 #if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
Decompress(const std::string & data)148 std::string Decompress(const std::string& data) {
149 uint8_t out[1024];
150
151 z_stream stream{};
152 stream.next_in = reinterpret_cast<uint8_t*>(const_cast<char*>(data.data()));
153 stream.avail_in = static_cast<unsigned int>(data.size());
154
155 EXPECT_EQ(inflateInit(&stream), Z_OK);
156 std::string s;
157
158 int ret;
159 do {
160 stream.next_out = out;
161 stream.avail_out = sizeof(out);
162 ret = inflate(&stream, Z_NO_FLUSH);
163 EXPECT_NE(ret, Z_STREAM_ERROR);
164 EXPECT_NE(ret, Z_NEED_DICT);
165 EXPECT_NE(ret, Z_DATA_ERROR);
166 EXPECT_NE(ret, Z_MEM_ERROR);
167 s.append(reinterpret_cast<char*>(out), sizeof(out) - stream.avail_out);
168 } while (ret != Z_STREAM_END);
169
170 inflateEnd(&stream);
171 return s;
172 }
173
DecompressTrace(const std::vector<protos::gen::TracePacket> compressed)174 std::vector<protos::gen::TracePacket> DecompressTrace(
175 const std::vector<protos::gen::TracePacket> compressed) {
176 std::vector<protos::gen::TracePacket> decompressed;
177
178 for (const protos::gen::TracePacket& c : compressed) {
179 if (c.compressed_packets().empty()) {
180 decompressed.push_back(c);
181 continue;
182 }
183
184 std::string s = Decompress(c.compressed_packets());
185 protos::gen::Trace t;
186 EXPECT_TRUE(t.ParseFromString(s));
187 decompressed.insert(decompressed.end(), t.packet().begin(),
188 t.packet().end());
189 }
190 return decompressed;
191 }
192 #endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
193
194 } // namespace
195
196 class TracingServiceImplTest : public testing::Test {
197 public:
198 using DataSourceInstanceState =
199 TracingServiceImpl::DataSourceInstance::DataSourceInstanceState;
200
TracingServiceImplTest()201 TracingServiceImplTest() { InitializeSvcWithOpts({}); }
202
InitializeSvcWithOpts(TracingService::InitOpts init_opts)203 void InitializeSvcWithOpts(TracingService::InitOpts init_opts) {
204 auto shm_factory =
205 std::unique_ptr<SharedMemory::Factory>(new TestSharedMemory::Factory());
206 svc.reset(static_cast<TracingServiceImpl*>(
207 TracingService::CreateInstance(std::move(shm_factory), &task_runner,
208 init_opts)
209 .release()));
210 svc->min_write_period_ms_ = 1;
211 }
212
CreateMockProducer()213 std::unique_ptr<MockProducer> CreateMockProducer() {
214 return std::unique_ptr<MockProducer>(
215 new StrictMock<MockProducer>(&task_runner));
216 }
217
CreateMockConsumer()218 std::unique_ptr<MockConsumer> CreateMockConsumer() {
219 return std::unique_ptr<MockConsumer>(
220 new StrictMock<MockConsumer>(&task_runner));
221 }
222
last_producer_id()223 ProducerID* last_producer_id() { return &svc->last_producer_id_; }
224
GetProducerUid(ProducerID producer_id)225 uid_t GetProducerUid(ProducerID producer_id) {
226 return svc->GetProducer(producer_id)->uid();
227 }
228
GetTracingSession(TracingSessionID tsid)229 TracingServiceImpl::TracingSession* GetTracingSession(TracingSessionID tsid) {
230 auto* session = svc->GetTracingSession(tsid);
231 EXPECT_NE(nullptr, session);
232 return session;
233 }
234
tracing_session()235 TracingServiceImpl::TracingSession* tracing_session() {
236 return GetTracingSession(GetTracingSessionID());
237 }
238
GetTracingSessionID()239 TracingSessionID GetTracingSessionID() {
240 return svc->last_tracing_session_id_;
241 }
242
GetAllowedTargetBuffers(ProducerID producer_id)243 const std::set<BufferID>& GetAllowedTargetBuffers(ProducerID producer_id) {
244 return svc->GetProducer(producer_id)->allowed_target_buffers_;
245 }
246
GetWriters(ProducerID producer_id)247 const std::map<WriterID, BufferID>& GetWriters(ProducerID producer_id) {
248 return svc->GetProducer(producer_id)->writers_;
249 }
250
GetShmemArbiterForProducer(ProducerID producer_id)251 SharedMemoryArbiterImpl* GetShmemArbiterForProducer(ProducerID producer_id) {
252 return svc->GetProducer(producer_id)->inproc_shmem_arbiter_.get();
253 }
254
StealShmemArbiterForProducer(ProducerID producer_id)255 std::unique_ptr<SharedMemoryArbiterImpl> StealShmemArbiterForProducer(
256 ProducerID producer_id) {
257 return std::move(svc->GetProducer(producer_id)->inproc_shmem_arbiter_);
258 }
259
GetNumPendingFlushes()260 size_t GetNumPendingFlushes() {
261 return tracing_session()->pending_flushes.size();
262 }
263
WaitForNextSyncMarker()264 void WaitForNextSyncMarker() {
265 tracing_session()->should_emit_sync_marker = true;
266 static int attempt = 0;
267 while (tracing_session()->should_emit_sync_marker) {
268 auto checkpoint_name = "wait_snapshot_" + std::to_string(attempt++);
269 auto timer_expired = task_runner.CreateCheckpoint(checkpoint_name);
270 task_runner.PostDelayedTask([timer_expired] { timer_expired(); }, 1);
271 task_runner.RunUntilCheckpoint(checkpoint_name);
272 }
273 }
274
WaitForTraceWritersChanged(ProducerID producer_id)275 void WaitForTraceWritersChanged(ProducerID producer_id) {
276 static int i = 0;
277 auto checkpoint_name = "writers_changed_" + std::to_string(producer_id) +
278 "_" + std::to_string(i++);
279 auto writers_changed = task_runner.CreateCheckpoint(checkpoint_name);
280 auto writers = GetWriters(producer_id);
281 std::function<void()> task;
282 task = [&task, writers, writers_changed, producer_id, this]() {
283 if (writers != GetWriters(producer_id)) {
284 writers_changed();
285 return;
286 }
287 task_runner.PostDelayedTask(task, 1);
288 };
289 task_runner.PostDelayedTask(task, 1);
290 task_runner.RunUntilCheckpoint(checkpoint_name);
291 }
292
GetDataSourceInstanceState(const std::string & name)293 DataSourceInstanceState GetDataSourceInstanceState(const std::string& name) {
294 for (const auto& kv : tracing_session()->data_source_instances) {
295 if (kv.second.data_source_name == name)
296 return kv.second.state;
297 }
298 PERFETTO_FATAL("Can't find data source instance with name %s",
299 name.c_str());
300 }
301
SetTriggerWindowNs(int64_t window_ns)302 void SetTriggerWindowNs(int64_t window_ns) {
303 svc->trigger_window_ns_ = window_ns;
304 }
305
OverrideNextTriggerRandomNumber(double number)306 void OverrideNextTriggerRandomNumber(double number) {
307 svc->trigger_rnd_override_for_testing_ = number;
308 }
309
310 base::TestTaskRunner task_runner;
311 std::unique_ptr<TracingServiceImpl> svc;
312 };
313
TEST_F(TracingServiceImplTest,AtMostOneConfig)314 TEST_F(TracingServiceImplTest, AtMostOneConfig) {
315 std::unique_ptr<MockConsumer> consumer_a = CreateMockConsumer();
316 std::unique_ptr<MockConsumer> consumer_b = CreateMockConsumer();
317
318 consumer_a->Connect(svc.get());
319 consumer_b->Connect(svc.get());
320
321 TraceConfig trace_config_a;
322 trace_config_a.add_buffers()->set_size_kb(128);
323 trace_config_a.set_duration_ms(0);
324 trace_config_a.set_unique_session_name("foo");
325
326 TraceConfig trace_config_b;
327 trace_config_b.add_buffers()->set_size_kb(128);
328 trace_config_b.set_duration_ms(0);
329 trace_config_b.set_unique_session_name("foo");
330
331 consumer_a->EnableTracing(trace_config_a);
332 consumer_b->EnableTracing(trace_config_b);
333
334 // This will stop immediately since it has the same unique session name.
335 consumer_b->WaitForTracingDisabled();
336
337 consumer_a->DisableTracing();
338 consumer_a->WaitForTracingDisabled();
339
340 EXPECT_THAT(consumer_b->ReadBuffers(), IsEmpty());
341 }
342
TEST_F(TracingServiceImplTest,CantBackToBackConfigsForWithExtraGuardrails)343 TEST_F(TracingServiceImplTest, CantBackToBackConfigsForWithExtraGuardrails) {
344 {
345 std::unique_ptr<MockConsumer> consumer_a = CreateMockConsumer();
346 consumer_a->Connect(svc.get());
347
348 TraceConfig trace_config_a;
349 trace_config_a.add_buffers()->set_size_kb(128);
350 trace_config_a.set_duration_ms(0);
351 trace_config_a.set_enable_extra_guardrails(true);
352 trace_config_a.set_unique_session_name("foo");
353
354 consumer_a->EnableTracing(trace_config_a);
355 consumer_a->DisableTracing();
356 consumer_a->WaitForTracingDisabled();
357 EXPECT_THAT(consumer_a->ReadBuffers(), Not(IsEmpty()));
358 }
359
360 {
361 std::unique_ptr<MockConsumer> consumer_b = CreateMockConsumer();
362 consumer_b->Connect(svc.get());
363
364 TraceConfig trace_config_b;
365 trace_config_b.add_buffers()->set_size_kb(128);
366 trace_config_b.set_duration_ms(10000);
367 trace_config_b.set_enable_extra_guardrails(true);
368 trace_config_b.set_unique_session_name("foo");
369
370 consumer_b->EnableTracing(trace_config_b);
371 consumer_b->WaitForTracingDisabled(2000);
372 EXPECT_THAT(consumer_b->ReadBuffers(), IsEmpty());
373 }
374 }
375
TEST_F(TracingServiceImplTest,RegisterAndUnregister)376 TEST_F(TracingServiceImplTest, RegisterAndUnregister) {
377 std::unique_ptr<MockProducer> mock_producer_1 = CreateMockProducer();
378 std::unique_ptr<MockProducer> mock_producer_2 = CreateMockProducer();
379
380 mock_producer_1->Connect(svc.get(), "mock_producer_1", 123u /* uid */);
381 mock_producer_2->Connect(svc.get(), "mock_producer_2", 456u /* uid */);
382
383 ASSERT_EQ(2u, svc->num_producers());
384 ASSERT_EQ(mock_producer_1->endpoint(), svc->GetProducer(1));
385 ASSERT_EQ(mock_producer_2->endpoint(), svc->GetProducer(2));
386 ASSERT_EQ(123u, GetProducerUid(1));
387 ASSERT_EQ(456u, GetProducerUid(2));
388
389 mock_producer_1->RegisterDataSource("foo");
390 mock_producer_2->RegisterDataSource("bar");
391
392 mock_producer_1->UnregisterDataSource("foo");
393 mock_producer_2->UnregisterDataSource("bar");
394
395 mock_producer_1.reset();
396 ASSERT_EQ(1u, svc->num_producers());
397 ASSERT_EQ(nullptr, svc->GetProducer(1));
398
399 mock_producer_2.reset();
400 ASSERT_EQ(nullptr, svc->GetProducer(2));
401
402 ASSERT_EQ(0u, svc->num_producers());
403 }
404
TEST_F(TracingServiceImplTest,EnableAndDisableTracing)405 TEST_F(TracingServiceImplTest, EnableAndDisableTracing) {
406 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
407 consumer->Connect(svc.get());
408
409 std::unique_ptr<MockProducer> producer = CreateMockProducer();
410 producer->Connect(svc.get(), "mock_producer");
411 producer->RegisterDataSource("data_source");
412
413 TraceConfig trace_config;
414 trace_config.add_buffers()->set_size_kb(128);
415 auto* ds = trace_config.add_data_sources();
416 *ds->add_producer_name_regex_filter() = "mock_[p]roducer";
417 auto* ds_config = ds->mutable_config();
418 ds_config->set_name("data_source");
419 consumer->EnableTracing(trace_config);
420
421 producer->WaitForTracingSetup();
422 producer->WaitForDataSourceSetup("data_source");
423 producer->WaitForDataSourceStart("data_source");
424
425 // Calling StartTracing() should be a noop (% a DLOG statement) because the
426 // trace config didn't have the |deferred_start| flag set.
427 consumer->StartTracing();
428
429 consumer->DisableTracing();
430 producer->WaitForDataSourceStop("data_source");
431 consumer->WaitForTracingDisabled();
432 }
433
434 // Creates a tracing session with a START_TRACING trigger and checks that data
435 // sources are started only after the service receives a trigger.
TEST_F(TracingServiceImplTest,StartTracingTriggerDeferredStart)436 TEST_F(TracingServiceImplTest, StartTracingTriggerDeferredStart) {
437 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
438 consumer->Connect(svc.get());
439
440 std::unique_ptr<MockProducer> producer = CreateMockProducer();
441 producer->Connect(svc.get(), "mock_producer");
442
443 // Create two data sources but enable only one of them.
444 producer->RegisterDataSource("ds_1");
445 producer->RegisterDataSource("ds_2");
446
447 TraceConfig trace_config;
448 trace_config.add_buffers()->set_size_kb(128);
449 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
450 auto* trigger_config = trace_config.mutable_trigger_config();
451 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
452 auto* trigger = trigger_config->add_triggers();
453 trigger->set_name("trigger_name");
454 trigger->set_stop_delay_ms(1);
455
456 trigger_config->set_trigger_timeout_ms(8.64e+7);
457
458 // Make sure we don't get unexpected DataSourceStart() notifications yet.
459 EXPECT_CALL(*producer, StartDataSource(_, _)).Times(0);
460
461 consumer->EnableTracing(trace_config);
462 producer->WaitForTracingSetup();
463
464 producer->WaitForDataSourceSetup("ds_1");
465
466 // The trace won't start until we send the trigger. since we have a
467 // START_TRACING trigger defined.
468 std::vector<std::string> req;
469 req.push_back("trigger_name");
470 producer->endpoint()->ActivateTriggers(req);
471
472 producer->WaitForDataSourceStart("ds_1");
473
474 auto writer1 = producer->CreateTraceWriter("ds_1");
475 producer->ExpectFlush(writer1.get());
476
477 producer->WaitForDataSourceStop("ds_1");
478 consumer->WaitForTracingDisabled();
479
480 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
481 EXPECT_EQ("trigger_name",
482 tracing_session()->received_triggers[0].trigger_name);
483
484 EXPECT_THAT(
485 consumer->ReadBuffers(),
486 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
487 }
488
489 // Creates a tracing session with a START_TRACING trigger and checks that the
490 // session is cleaned up when no trigger is received after |trigger_timeout_ms|.
TEST_F(TracingServiceImplTest,StartTracingTriggerTimeOut)491 TEST_F(TracingServiceImplTest, StartTracingTriggerTimeOut) {
492 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
493 consumer->Connect(svc.get());
494
495 std::unique_ptr<MockProducer> producer = CreateMockProducer();
496 producer->Connect(svc.get(), "mock_producer");
497
498 // Create two data sources but enable only one of them.
499 producer->RegisterDataSource("ds_1");
500 producer->RegisterDataSource("ds_2");
501
502 TraceConfig trace_config;
503 trace_config.add_buffers()->set_size_kb(128);
504 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
505 auto* trigger_config = trace_config.mutable_trigger_config();
506 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
507 auto* trigger = trigger_config->add_triggers();
508 trigger->set_name("trigger_name");
509 trigger->set_stop_delay_ms(8.64e+7);
510
511 trigger_config->set_trigger_timeout_ms(1);
512
513 // Make sure we don't get unexpected DataSourceStart() notifications yet.
514 EXPECT_CALL(*producer, StartDataSource(_, _)).Times(0);
515
516 consumer->EnableTracing(trace_config);
517 producer->WaitForTracingSetup();
518
519 producer->WaitForDataSourceSetup("ds_1");
520
521 // The trace won't start until we send the trigger. since we have a
522 // START_TRACING trigger defined. This is where we'd expect to have an
523 // ActivateTriggers call to the producer->endpoint().
524
525 producer->WaitForDataSourceStop("ds_1");
526 consumer->WaitForTracingDisabled();
527 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
528 }
529
530 // Regression test for b/274931668. An unkonwn trigger should not cause a trace
531 // that runs indefinitely.
TEST_F(TracingServiceImplTest,FailOnUnknownTrigger)532 TEST_F(TracingServiceImplTest, FailOnUnknownTrigger) {
533 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
534 consumer->Connect(svc.get());
535
536 std::unique_ptr<MockProducer> producer = CreateMockProducer();
537 producer->Connect(svc.get(), "mock_producer");
538 producer->RegisterDataSource("ds_1");
539
540 TraceConfig trace_config;
541 trace_config.add_buffers()->set_size_kb(128);
542 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
543 auto* trigger_config = trace_config.mutable_trigger_config();
544 trigger_config->set_trigger_mode(
545 static_cast<TraceConfig::TriggerConfig::TriggerMode>(
546 TraceConfig::TriggerConfig::TriggerMode_MAX + 1));
547 auto* trigger = trigger_config->add_triggers();
548 trigger->set_name("trigger_from_the_future");
549 trigger_config->set_trigger_timeout_ms(1);
550
551 consumer->EnableTracing(trace_config);
552 consumer->WaitForTracingDisabled();
553 }
554
555 // Creates a tracing session with a START_TRACING trigger and checks that
556 // the session is not started when the configured trigger producer is different
557 // than the producer that sent the trigger.
TEST_F(TracingServiceImplTest,StartTracingTriggerDifferentProducer)558 TEST_F(TracingServiceImplTest, StartTracingTriggerDifferentProducer) {
559 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
560 consumer->Connect(svc.get());
561
562 std::unique_ptr<MockProducer> producer = CreateMockProducer();
563 producer->Connect(svc.get(), "mock_producer");
564
565 // Create two data sources but enable only one of them.
566 producer->RegisterDataSource("ds_1");
567 producer->RegisterDataSource("ds_2");
568
569 TraceConfig trace_config;
570 trace_config.add_buffers()->set_size_kb(128);
571 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
572 auto* trigger_config = trace_config.mutable_trigger_config();
573 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
574 auto* trigger = trigger_config->add_triggers();
575 trigger->set_name("trigger_name");
576 trigger->set_stop_delay_ms(8.64e+7);
577 trigger->set_producer_name_regex("correct_name");
578
579 trigger_config->set_trigger_timeout_ms(1);
580
581 // Make sure we don't get unexpected DataSourceStart() notifications yet.
582 EXPECT_CALL(*producer, StartDataSource(_, _)).Times(0);
583
584 consumer->EnableTracing(trace_config);
585 producer->WaitForTracingSetup();
586
587 producer->WaitForDataSourceSetup("ds_1");
588
589 // The trace won't start until we send the trigger called "trigger_name"
590 // coming from a producer called "correct_name", since we have a
591 // START_TRACING trigger defined. This is where we'd expect to have an
592 // ActivateTriggers call to the producer->endpoint(), but we send the trigger
593 // from a different producer so it is ignored.
594 std::vector<std::string> req;
595 req.push_back("trigger_name");
596 producer->endpoint()->ActivateTriggers(req);
597
598 producer->WaitForDataSourceStop("ds_1");
599 consumer->WaitForTracingDisabled();
600 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
601 }
602
603 // Creates a tracing session with a START_TRACING trigger and checks that the
604 // session is started when the trigger is received from the correct producer.
TEST_F(TracingServiceImplTest,StartTracingTriggerCorrectProducer)605 TEST_F(TracingServiceImplTest, StartTracingTriggerCorrectProducer) {
606 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
607 consumer->Connect(svc.get());
608
609 std::unique_ptr<MockProducer> producer = CreateMockProducer();
610 producer->Connect(svc.get(), "mock_producer");
611
612 // Create two data sources but enable only one of them.
613 producer->RegisterDataSource("ds_1");
614 producer->RegisterDataSource("ds_2");
615
616 TraceConfig trace_config;
617 trace_config.add_buffers()->set_size_kb(128);
618 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
619 auto* trigger_config = trace_config.mutable_trigger_config();
620 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
621 auto* trigger = trigger_config->add_triggers();
622 trigger->set_name("trigger_name");
623 trigger->set_stop_delay_ms(1);
624 trigger->set_producer_name_regex("mock_produc[e-r]+");
625
626 trigger_config->set_trigger_timeout_ms(8.64e+7);
627
628 consumer->EnableTracing(trace_config);
629 producer->WaitForTracingSetup();
630
631 producer->WaitForDataSourceSetup("ds_1");
632
633 // Start the trace at this point with ActivateTriggers.
634 std::vector<std::string> req;
635 req.push_back("trigger_name");
636 producer->endpoint()->ActivateTriggers(req);
637
638 producer->WaitForDataSourceStart("ds_1");
639
640 auto writer = producer->CreateTraceWriter("ds_1");
641 producer->ExpectFlush(writer.get());
642
643 producer->WaitForDataSourceStop("ds_1");
644 consumer->WaitForTracingDisabled();
645 EXPECT_THAT(
646 consumer->ReadBuffers(),
647 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
648 }
649
650 // Creates a tracing session with a START_TRACING trigger and checks that the
651 // session is cleaned up even when a different trigger is received.
TEST_F(TracingServiceImplTest,StartTracingTriggerDifferentTrigger)652 TEST_F(TracingServiceImplTest, StartTracingTriggerDifferentTrigger) {
653 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
654 consumer->Connect(svc.get());
655
656 std::unique_ptr<MockProducer> producer = CreateMockProducer();
657 producer->Connect(svc.get(), "mock_producer");
658
659 // Create two data sources but enable only one of them.
660 producer->RegisterDataSource("ds_1");
661 producer->RegisterDataSource("ds_2");
662
663 TraceConfig trace_config;
664 trace_config.add_buffers()->set_size_kb(128);
665 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
666 auto* trigger_config = trace_config.mutable_trigger_config();
667 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
668 auto* trigger = trigger_config->add_triggers();
669 trigger->set_name("trigger_name");
670 trigger->set_stop_delay_ms(8.64e+7);
671
672 trigger_config->set_trigger_timeout_ms(1);
673
674 // Make sure we don't get unexpected DataSourceStart() notifications yet.
675 EXPECT_CALL(*producer, StartDataSource(_, _)).Times(0);
676
677 consumer->EnableTracing(trace_config);
678 producer->WaitForTracingSetup();
679
680 producer->WaitForDataSourceSetup("ds_1");
681
682 // The trace won't start until we send the trigger called "trigger_name",
683 // since we have a START_TRACING trigger defined. This is where we'd expect to
684 // have an ActivateTriggers call to the producer->endpoint(), but we send a
685 // different trigger.
686 std::vector<std::string> req;
687 req.push_back("not_correct_trigger");
688 producer->endpoint()->ActivateTriggers(req);
689
690 producer->WaitForDataSourceStop("ds_1");
691 consumer->WaitForTracingDisabled();
692 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
693 }
694
695 // Creates a tracing session with a START_TRACING trigger and checks that any
696 // trigger can start the TracingSession.
TEST_F(TracingServiceImplTest,StartTracingTriggerMultipleTriggers)697 TEST_F(TracingServiceImplTest, StartTracingTriggerMultipleTriggers) {
698 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
699 consumer->Connect(svc.get());
700
701 std::unique_ptr<MockProducer> producer = CreateMockProducer();
702 producer->Connect(svc.get(), "mock_producer");
703
704 // Create two data sources but enable only one of them.
705 producer->RegisterDataSource("ds_1");
706 producer->RegisterDataSource("ds_2");
707
708 TraceConfig trace_config;
709 trace_config.add_buffers()->set_size_kb(128);
710 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
711 auto* trigger_config = trace_config.mutable_trigger_config();
712 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
713 auto* trigger = trigger_config->add_triggers();
714 trigger->set_name("trigger_name");
715 trigger->set_stop_delay_ms(1);
716
717 trigger_config->set_trigger_timeout_ms(8.64e+7);
718
719 consumer->EnableTracing(trace_config);
720 producer->WaitForTracingSetup();
721
722 producer->WaitForDataSourceSetup("ds_1");
723
724 std::vector<std::string> req;
725 req.push_back("not_correct_trigger");
726 req.push_back("trigger_name");
727 producer->endpoint()->ActivateTriggers(req);
728
729 producer->WaitForDataSourceStart("ds_1");
730
731 auto writer = producer->CreateTraceWriter("ds_1");
732 producer->ExpectFlush(writer.get());
733
734 producer->WaitForDataSourceStop("ds_1");
735 consumer->WaitForTracingDisabled();
736 EXPECT_THAT(
737 consumer->ReadBuffers(),
738 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
739 }
740
741 // Creates two tracing sessions with a START_TRACING trigger and checks that
742 // both are able to be triggered simultaneously.
TEST_F(TracingServiceImplTest,StartTracingTriggerMultipleTraces)743 TEST_F(TracingServiceImplTest, StartTracingTriggerMultipleTraces) {
744 std::unique_ptr<MockConsumer> consumer_1 = CreateMockConsumer();
745 consumer_1->Connect(svc.get());
746 std::unique_ptr<MockConsumer> consumer_2 = CreateMockConsumer();
747 consumer_2->Connect(svc.get());
748
749 std::unique_ptr<MockProducer> producer = CreateMockProducer();
750 producer->Connect(svc.get(), "mock_producer");
751
752 // Create two data sources but each TracingSession will only enable one of
753 // them.
754 producer->RegisterDataSource("ds_1");
755 producer->RegisterDataSource("ds_2");
756
757 TraceConfig trace_config;
758 trace_config.add_buffers()->set_size_kb(128);
759 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
760 auto* trigger_config = trace_config.mutable_trigger_config();
761 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
762 auto* trigger = trigger_config->add_triggers();
763 trigger->set_name("trigger_name");
764 trigger->set_stop_delay_ms(1);
765
766 trigger_config->set_trigger_timeout_ms(8.64e+7);
767
768 consumer_1->EnableTracing(trace_config);
769 producer->WaitForTracingSetup();
770
771 producer->WaitForDataSourceSetup("ds_1");
772
773 auto tracing_session_1_id = GetTracingSessionID();
774
775 (*trace_config.mutable_data_sources())[0].mutable_config()->set_name("ds_2");
776 trigger = trace_config.mutable_trigger_config()->add_triggers();
777 trigger->set_name("trigger_name_2");
778 trigger->set_stop_delay_ms(8.64e+7);
779
780 consumer_2->EnableTracing(trace_config);
781
782 producer->WaitForDataSourceSetup("ds_2");
783
784 auto tracing_session_2_id = GetTracingSessionID();
785 EXPECT_NE(tracing_session_1_id, tracing_session_2_id);
786
787 const DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_1");
788 const DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_2");
789
790 std::vector<std::string> req;
791 req.push_back("not_correct_trigger");
792 req.push_back("trigger_name");
793 req.push_back("trigger_name_2");
794 producer->endpoint()->ActivateTriggers(req);
795
796 // The order has to be the same as the triggers or else we're incorrectly wait
797 // on the wrong checkpoint in the |task_runner|.
798 producer->WaitForDataSourceStart("ds_1");
799 producer->WaitForDataSourceStart("ds_2");
800
801 // Now that they've started we can check the triggers they've seen.
802 auto* tracing_session_1 = GetTracingSession(tracing_session_1_id);
803 ASSERT_EQ(1u, tracing_session_1->received_triggers.size());
804 EXPECT_EQ("trigger_name",
805 tracing_session_1->received_triggers[0].trigger_name);
806
807 // This is actually dependent on the order in which the triggers were received
808 // but there isn't really a better way than iteration order so probably not to
809 // brittle of a test. And this caught a real bug in implementation.
810 auto* tracing_session_2 = GetTracingSession(tracing_session_2_id);
811 ASSERT_EQ(2u, tracing_session_2->received_triggers.size());
812
813 EXPECT_EQ("trigger_name",
814 tracing_session_2->received_triggers[0].trigger_name);
815
816 EXPECT_EQ("trigger_name_2",
817 tracing_session_2->received_triggers[1].trigger_name);
818
819 auto writer1 = producer->CreateTraceWriter("ds_1");
820 auto writer2 = producer->CreateTraceWriter("ds_2");
821
822 // We can't use the standard WaitForX in the MockProducer and MockConsumer
823 // because they assume only a single trace is going on. So we perform our own
824 // expectations and wait at the end for the two consumers to receive
825 // OnTracingDisabled.
826 bool flushed_writer_1 = false;
827 bool flushed_writer_2 = false;
828 auto flush_correct_writer = [&](FlushRequestID flush_req_id,
829 const DataSourceInstanceID* id, size_t,
830 FlushFlags) {
831 if (*id == id1) {
832 flushed_writer_1 = true;
833 writer1->Flush();
834 producer->endpoint()->NotifyFlushComplete(flush_req_id);
835 } else if (*id == id2) {
836 flushed_writer_2 = true;
837 writer2->Flush();
838 producer->endpoint()->NotifyFlushComplete(flush_req_id);
839 }
840 };
841 FlushFlags flush_flags(FlushFlags::Initiator::kTraced,
842 FlushFlags::Reason::kTraceStop);
843 EXPECT_CALL(*producer, Flush(_, _, _, flush_flags))
844 .WillOnce(Invoke(flush_correct_writer))
845 .WillOnce(Invoke(flush_correct_writer));
846
847 auto checkpoint_name = "on_tracing_disabled_consumer_1_and_2";
848 auto on_tracing_disabled = task_runner.CreateCheckpoint(checkpoint_name);
849 std::atomic<size_t> counter(0);
850 EXPECT_CALL(*consumer_1, OnTracingDisabled(_))
851 .WillOnce(InvokeWithoutArgs([&]() {
852 if (++counter == 2u) {
853 on_tracing_disabled();
854 }
855 }));
856 EXPECT_CALL(*consumer_2, OnTracingDisabled(_))
857 .WillOnce(InvokeWithoutArgs([&]() {
858 if (++counter == 2u) {
859 on_tracing_disabled();
860 }
861 }));
862
863 EXPECT_CALL(*producer, StopDataSource(id1));
864 EXPECT_CALL(*producer, StopDataSource(id2));
865
866 task_runner.RunUntilCheckpoint(checkpoint_name, 1000);
867
868 EXPECT_TRUE(flushed_writer_1);
869 EXPECT_TRUE(flushed_writer_2);
870 EXPECT_THAT(
871 consumer_1->ReadBuffers(),
872 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
873 EXPECT_THAT(
874 consumer_2->ReadBuffers(),
875 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::START_TRACING));
876 }
877
878 // Creates a tracing session with a START_TRACING trigger and checks that the
879 // received_triggers are emitted as packets.
TEST_F(TracingServiceImplTest,EmitTriggersWithStartTracingTrigger)880 TEST_F(TracingServiceImplTest, EmitTriggersWithStartTracingTrigger) {
881 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
882 consumer->Connect(svc.get());
883
884 std::unique_ptr<MockProducer> producer = CreateMockProducer();
885 producer->Connect(svc.get(), "mock_producer", /* uid = */ 123u);
886
887 producer->RegisterDataSource("ds_1");
888
889 TraceConfig trace_config;
890 trace_config.add_buffers()->set_size_kb(128);
891 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
892 auto* trigger_config = trace_config.mutable_trigger_config();
893 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::START_TRACING);
894 auto* trigger = trigger_config->add_triggers();
895 trigger->set_name("trigger_name");
896 trigger->set_stop_delay_ms(1);
897 trigger->set_producer_name_regex("mock_produc[e-r]+");
898
899 trigger_config->set_trigger_timeout_ms(30000);
900
901 consumer->EnableTracing(trace_config);
902 producer->WaitForTracingSetup();
903 producer->WaitForDataSourceSetup("ds_1");
904
905 // The trace won't start until we send the trigger since we have a
906 // START_TRACING trigger defined.
907 std::vector<std::string> req;
908 req.push_back("trigger_name");
909 req.push_back("trigger_name_2");
910 req.push_back("trigger_name_3");
911 producer->endpoint()->ActivateTriggers(req);
912
913 producer->WaitForDataSourceStart("ds_1");
914 auto writer1 = producer->CreateTraceWriter("ds_1");
915 producer->ExpectFlush(writer1.get());
916 producer->WaitForDataSourceStop("ds_1");
917 consumer->WaitForTracingDisabled();
918
919 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
920 EXPECT_EQ("trigger_name",
921 tracing_session()->received_triggers[0].trigger_name);
922
923 auto packets = consumer->ReadBuffers();
924 EXPECT_THAT(
925 packets,
926 Contains(Property(
927 &protos::gen::TracePacket::trace_config,
928 Property(
929 &protos::gen::TraceConfig::trigger_config,
930 Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
931 Eq(protos::gen::TraceConfig::TriggerConfig::
932 START_TRACING))))));
933 auto expect_received_trigger = [&](const std::string& name) {
934 return Contains(AllOf(
935 Property(&protos::gen::TracePacket::trigger,
936 AllOf(Property(&protos::gen::Trigger::trigger_name, Eq(name)),
937 Property(&protos::gen::Trigger::trusted_producer_uid,
938 Eq(123)),
939 Property(&protos::gen::Trigger::producer_name,
940 Eq("mock_producer")))),
941 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
942 Eq(kServicePacketSequenceID))));
943 };
944 EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
945 EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
946 EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_3")));
947 }
948
949 // Creates a tracing session with a START_TRACING trigger and checks that the
950 // received_triggers are emitted as packets.
TEST_F(TracingServiceImplTest,EmitTriggersWithStopTracingTrigger)951 TEST_F(TracingServiceImplTest, EmitTriggersWithStopTracingTrigger) {
952 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
953 consumer->Connect(svc.get());
954
955 std::unique_ptr<MockProducer> producer = CreateMockProducer();
956 producer->Connect(svc.get(), "mock_producer", /* uid = */ 321u);
957
958 producer->RegisterDataSource("ds_1");
959
960 TraceConfig trace_config;
961 trace_config.add_buffers()->set_size_kb(128);
962 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
963 auto* trigger_config = trace_config.mutable_trigger_config();
964 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
965 auto* trigger = trigger_config->add_triggers();
966 trigger->set_name("trigger_name");
967 trigger->set_stop_delay_ms(1);
968 trigger = trigger_config->add_triggers();
969 trigger->set_name("trigger_name_3");
970 trigger->set_stop_delay_ms(30000);
971
972 trigger_config->set_trigger_timeout_ms(30000);
973
974 consumer->EnableTracing(trace_config);
975 producer->WaitForTracingSetup();
976 producer->WaitForDataSourceSetup("ds_1");
977 producer->WaitForDataSourceStart("ds_1");
978
979 // The trace won't start until we send the trigger since we have a
980 // START_TRACING trigger defined.
981 std::vector<std::string> req;
982 req.push_back("trigger_name");
983 req.push_back("trigger_name_2");
984 req.push_back("trigger_name_3");
985 producer->endpoint()->ActivateTriggers(req);
986
987 auto writer1 = producer->CreateTraceWriter("ds_1");
988 producer->ExpectFlush(writer1.get());
989 producer->WaitForDataSourceStop("ds_1");
990 consumer->WaitForTracingDisabled();
991
992 ASSERT_EQ(2u, tracing_session()->received_triggers.size());
993 EXPECT_EQ("trigger_name",
994 tracing_session()->received_triggers[0].trigger_name);
995 EXPECT_EQ("trigger_name_3",
996 tracing_session()->received_triggers[1].trigger_name);
997
998 auto packets = consumer->ReadBuffers();
999 EXPECT_THAT(
1000 packets,
1001 Contains(Property(
1002 &protos::gen::TracePacket::trace_config,
1003 Property(
1004 &protos::gen::TraceConfig::trigger_config,
1005 Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
1006 Eq(protos::gen::TraceConfig::TriggerConfig::
1007 STOP_TRACING))))));
1008
1009 auto expect_received_trigger = [&](const std::string& name) {
1010 return Contains(AllOf(
1011 Property(&protos::gen::TracePacket::trigger,
1012 AllOf(Property(&protos::gen::Trigger::trigger_name, Eq(name)),
1013 Property(&protos::gen::Trigger::trusted_producer_uid,
1014 Eq(321)),
1015 Property(&protos::gen::Trigger::producer_name,
1016 Eq("mock_producer")))),
1017 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
1018 Eq(kServicePacketSequenceID))));
1019 };
1020 EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
1021 EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
1022 EXPECT_THAT(packets, expect_received_trigger("trigger_name_3"));
1023 }
1024
1025 // Creates a tracing session with a START_TRACING trigger and checks that the
1026 // received_triggers are emitted as packets even ones after the initial
1027 // ReadBuffers() call.
TEST_F(TracingServiceImplTest,EmitTriggersRepeatedly)1028 TEST_F(TracingServiceImplTest, EmitTriggersRepeatedly) {
1029 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1030 consumer->Connect(svc.get());
1031
1032 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1033 producer->Connect(svc.get(), "mock_producer");
1034
1035 // Create two data sources but enable only one of them.
1036 producer->RegisterDataSource("ds_1");
1037 producer->RegisterDataSource("ds_2");
1038
1039 TraceConfig trace_config;
1040 trace_config.add_buffers()->set_size_kb(128);
1041 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
1042 auto* trigger_config = trace_config.mutable_trigger_config();
1043 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1044 auto* trigger = trigger_config->add_triggers();
1045 trigger->set_name("trigger_name");
1046 trigger->set_stop_delay_ms(1);
1047 trigger = trigger_config->add_triggers();
1048 trigger->set_name("trigger_name_2");
1049 trigger->set_stop_delay_ms(1);
1050
1051 trigger_config->set_trigger_timeout_ms(30000);
1052
1053 auto expect_received_trigger = [&](const std::string& name) {
1054 return Contains(AllOf(
1055 Property(&protos::gen::TracePacket::trigger,
1056 AllOf(Property(&protos::gen::Trigger::trigger_name, Eq(name)),
1057 Property(&protos::gen::Trigger::producer_name,
1058 Eq("mock_producer")))),
1059 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
1060 Eq(kServicePacketSequenceID))));
1061 };
1062
1063 consumer->EnableTracing(trace_config);
1064 producer->WaitForTracingSetup();
1065 producer->WaitForDataSourceSetup("ds_1");
1066 producer->WaitForDataSourceStart("ds_1");
1067
1068 // The trace won't start until we send the trigger. since we have a
1069 // START_TRACING trigger defined.
1070 producer->endpoint()->ActivateTriggers({"trigger_name"});
1071
1072 auto packets = consumer->ReadBuffers();
1073 EXPECT_THAT(
1074 packets,
1075 Contains(Property(
1076 &protos::gen::TracePacket::trace_config,
1077 Property(
1078 &protos::gen::TraceConfig::trigger_config,
1079 Property(&protos::gen::TraceConfig::TriggerConfig::trigger_mode,
1080 Eq(protos::gen::TraceConfig::TriggerConfig::
1081 STOP_TRACING))))));
1082 EXPECT_THAT(packets, expect_received_trigger("trigger_name"));
1083 EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name_2")));
1084
1085 // Send a new trigger.
1086 producer->endpoint()->ActivateTriggers({"trigger_name_2"});
1087
1088 auto writer1 = producer->CreateTraceWriter("ds_1");
1089 producer->ExpectFlush(writer1.get());
1090 producer->WaitForDataSourceStop("ds_1");
1091 consumer->WaitForTracingDisabled();
1092
1093 ASSERT_EQ(2u, tracing_session()->received_triggers.size());
1094 EXPECT_EQ("trigger_name",
1095 tracing_session()->received_triggers[0].trigger_name);
1096 EXPECT_EQ("trigger_name_2",
1097 tracing_session()->received_triggers[1].trigger_name);
1098
1099 packets = consumer->ReadBuffers();
1100 // We don't rewrite the old trigger.
1101 EXPECT_THAT(packets, Not(expect_received_trigger("trigger_name")));
1102 EXPECT_THAT(packets, expect_received_trigger("trigger_name_2"));
1103 }
1104
1105 // Creates a tracing session with a STOP_TRACING trigger and checks that the
1106 // session is cleaned up after |trigger_timeout_ms|.
TEST_F(TracingServiceImplTest,StopTracingTriggerTimeout)1107 TEST_F(TracingServiceImplTest, StopTracingTriggerTimeout) {
1108 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1109 consumer->Connect(svc.get());
1110
1111 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1112 producer->Connect(svc.get(), "mock_producer");
1113
1114 // Create two data sources but enable only one of them.
1115 producer->RegisterDataSource("ds_1");
1116 producer->RegisterDataSource("ds_2");
1117
1118 TraceConfig trace_config;
1119 trace_config.add_buffers()->set_size_kb(128);
1120 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
1121 auto* trigger_config = trace_config.mutable_trigger_config();
1122 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1123 auto* trigger = trigger_config->add_triggers();
1124 trigger->set_name("trigger_name");
1125 trigger->set_stop_delay_ms(8.64e+7);
1126
1127 trigger_config->set_trigger_timeout_ms(1);
1128
1129 // Make sure we don't get unexpected DataSourceStart() notifications yet.
1130 EXPECT_CALL(*producer, StartDataSource(_, _)).Times(0);
1131
1132 consumer->EnableTracing(trace_config);
1133 producer->WaitForTracingSetup();
1134
1135 producer->WaitForDataSourceSetup("ds_1");
1136 producer->WaitForDataSourceStart("ds_1");
1137
1138 // The trace won't return data until unless we send a trigger at this point.
1139 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
1140
1141 auto writer = producer->CreateTraceWriter("ds_1");
1142 producer->ExpectFlush(writer.get());
1143
1144 ASSERT_EQ(0u, tracing_session()->received_triggers.size());
1145
1146 producer->WaitForDataSourceStop("ds_1");
1147 consumer->WaitForTracingDisabled();
1148 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
1149 }
1150
1151 // Creates a tracing session with a STOP_TRACING trigger and checks that the
1152 // session returns data after a trigger is received, but only what is currently
1153 // in the buffer.
TEST_F(TracingServiceImplTest,StopTracingTriggerRingBuffer)1154 TEST_F(TracingServiceImplTest, StopTracingTriggerRingBuffer) {
1155 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1156 consumer->Connect(svc.get());
1157
1158 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1159 producer->Connect(svc.get(), "mock_producer");
1160
1161 // Create two data sources but enable only one of them.
1162 producer->RegisterDataSource("ds_1");
1163 producer->RegisterDataSource("ds_2");
1164
1165 TraceConfig trace_config;
1166 trace_config.add_buffers()->set_size_kb(128);
1167 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
1168 auto* trigger_config = trace_config.mutable_trigger_config();
1169 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1170 auto* trigger = trigger_config->add_triggers();
1171 trigger->set_name("trigger_name");
1172 trigger->set_stop_delay_ms(1);
1173
1174 trigger_config->set_trigger_timeout_ms(8.64e+7);
1175
1176 consumer->EnableTracing(trace_config);
1177 producer->WaitForTracingSetup();
1178
1179 producer->WaitForDataSourceSetup("ds_1");
1180 producer->WaitForDataSourceStart("ds_1");
1181
1182 // The trace won't return data until unless we send a trigger at this point.
1183 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
1184
1185 // We write into the buffer a large packet which takes up the whole buffer. We
1186 // then add a bunch of smaller ones which causes the larger packet to be
1187 // dropped. After we activate the session we should only see a bunch of the
1188 // smaller ones.
1189 static const size_t kNumTestPackets = 10;
1190 static const char kPayload[] = "1234567890abcdef-";
1191
1192 auto writer = producer->CreateTraceWriter("ds_1");
1193 // Buffer is 1kb so we write a packet which is slightly smaller so it fits in
1194 // the buffer.
1195 const std::string large_payload(1024 * 128 - 20, 'a');
1196 {
1197 auto tp = writer->NewTracePacket();
1198 tp->set_for_testing()->set_str(large_payload.c_str(), large_payload.size());
1199 }
1200
1201 // Now we add a bunch of data before the trigger and after.
1202 for (size_t i = 0; i < kNumTestPackets; i++) {
1203 if (i == kNumTestPackets / 2) {
1204 std::vector<std::string> req;
1205 req.push_back("trigger_name");
1206 producer->endpoint()->ActivateTriggers(req);
1207 }
1208 auto tp = writer->NewTracePacket();
1209 std::string payload(kPayload);
1210 payload.append(std::to_string(i));
1211 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
1212 }
1213 producer->ExpectFlush(writer.get());
1214
1215 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
1216 EXPECT_EQ("trigger_name",
1217 tracing_session()->received_triggers[0].trigger_name);
1218
1219 producer->WaitForDataSourceStop("ds_1");
1220 consumer->WaitForTracingDisabled();
1221
1222 auto packets = consumer->ReadBuffers();
1223 EXPECT_LT(kNumTestPackets, packets.size());
1224 // We expect for the TraceConfig preamble packet to be there correctly and
1225 // then we expect each payload to be there, but not the |large_payload|
1226 // packet.
1227 EXPECT_THAT(
1228 packets,
1229 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
1230 for (size_t i = 0; i < kNumTestPackets; i++) {
1231 std::string payload = kPayload;
1232 payload += std::to_string(i);
1233 EXPECT_THAT(packets,
1234 Contains(Property(
1235 &protos::gen::TracePacket::for_testing,
1236 Property(&protos::gen::TestEvent::str, Eq(payload)))));
1237 }
1238
1239 // The large payload was overwritten before we trigger and ReadBuffers so it
1240 // should not be in the returned data.
1241 EXPECT_THAT(packets,
1242 Not(Contains(Property(
1243 &protos::gen::TracePacket::for_testing,
1244 Property(&protos::gen::TestEvent::str, Eq(large_payload))))));
1245 }
1246
1247 // Creates a tracing session with a STOP_TRACING trigger and checks that the
1248 // session only cleans up once even with multiple triggers.
TEST_F(TracingServiceImplTest,StopTracingTriggerMultipleTriggers)1249 TEST_F(TracingServiceImplTest, StopTracingTriggerMultipleTriggers) {
1250 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1251 consumer->Connect(svc.get());
1252
1253 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1254 producer->Connect(svc.get(), "mock_producer");
1255
1256 // Create two data sources but enable only one of them.
1257 producer->RegisterDataSource("ds_1");
1258 producer->RegisterDataSource("ds_2");
1259
1260 TraceConfig trace_config;
1261 trace_config.add_buffers()->set_size_kb(128);
1262 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
1263 auto* trigger_config = trace_config.mutable_trigger_config();
1264 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1265 auto* trigger = trigger_config->add_triggers();
1266 trigger->set_name("trigger_name");
1267 trigger->set_stop_delay_ms(1);
1268 trigger = trigger_config->add_triggers();
1269 trigger->set_name("trigger_name_2");
1270 trigger->set_stop_delay_ms(8.64e+7);
1271
1272 trigger_config->set_trigger_timeout_ms(8.64e+7);
1273
1274 consumer->EnableTracing(trace_config);
1275 producer->WaitForTracingSetup();
1276
1277 producer->WaitForDataSourceSetup("ds_1");
1278 producer->WaitForDataSourceStart("ds_1");
1279
1280 // The trace won't return data until unless we send a trigger at this point.
1281 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
1282
1283 std::vector<std::string> req;
1284 req.push_back("trigger_name");
1285 req.push_back("trigger_name_3");
1286 req.push_back("trigger_name_2");
1287 producer->endpoint()->ActivateTriggers(req);
1288
1289 auto writer = producer->CreateTraceWriter("ds_1");
1290 producer->ExpectFlush(writer.get());
1291
1292 ASSERT_EQ(2u, tracing_session()->received_triggers.size());
1293 EXPECT_EQ("trigger_name",
1294 tracing_session()->received_triggers[0].trigger_name);
1295 EXPECT_EQ("trigger_name_2",
1296 tracing_session()->received_triggers[1].trigger_name);
1297
1298 producer->WaitForDataSourceStop("ds_1");
1299 consumer->WaitForTracingDisabled();
1300 EXPECT_THAT(
1301 consumer->ReadBuffers(),
1302 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
1303 }
1304
TEST_F(TracingServiceImplTest,SecondTriggerHitsLimit)1305 TEST_F(TracingServiceImplTest, SecondTriggerHitsLimit) {
1306 TraceConfig trace_config;
1307 trace_config.add_buffers()->set_size_kb(128);
1308
1309 auto* trigger_config = trace_config.mutable_trigger_config();
1310 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1311 trigger_config->set_trigger_timeout_ms(8.64e+7);
1312
1313 auto* trigger = trigger_config->add_triggers();
1314 trigger->set_name("trigger_name");
1315 trigger->set_stop_delay_ms(1);
1316 trigger->set_max_per_24_h(1);
1317
1318 auto* ds = trace_config.add_data_sources()->mutable_config();
1319
1320 // First session.
1321 {
1322 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1323 producer->Connect(svc.get(), "mock_producer_a");
1324 producer->RegisterDataSource("data_source_a");
1325
1326 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1327 consumer->Connect(svc.get());
1328
1329 ds->set_name("data_source_a");
1330 consumer->EnableTracing(trace_config);
1331 producer->WaitForTracingSetup();
1332
1333 producer->WaitForDataSourceSetup("data_source_a");
1334 producer->WaitForDataSourceStart("data_source_a");
1335
1336 std::vector<std::string> req;
1337 req.push_back("trigger_name");
1338 producer->endpoint()->ActivateTriggers(req);
1339
1340 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
1341 EXPECT_EQ("trigger_name",
1342 tracing_session()->received_triggers[0].trigger_name);
1343
1344 auto writer = producer->CreateTraceWriter("data_source_a");
1345 producer->ExpectFlush(writer.get());
1346
1347 producer->WaitForDataSourceStop("data_source_a");
1348 consumer->WaitForTracingDisabled();
1349 EXPECT_THAT(
1350 consumer->ReadBuffers(),
1351 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
1352 }
1353
1354 // Second session.
1355 {
1356 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1357 producer->Connect(svc.get(), "mock_producer_b");
1358 producer->RegisterDataSource("data_source_b");
1359
1360 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1361 consumer->Connect(svc.get());
1362
1363 ds->set_name("data_source_b");
1364 consumer->EnableTracing(trace_config);
1365 producer->WaitForTracingSetup();
1366
1367 producer->WaitForDataSourceSetup("data_source_b");
1368 producer->WaitForDataSourceStart("data_source_b");
1369
1370 std::vector<std::string> req;
1371 req.push_back("trigger_name");
1372 producer->endpoint()->ActivateTriggers(req);
1373
1374 ASSERT_EQ(0u, tracing_session()->received_triggers.size());
1375
1376 consumer->DisableTracing();
1377 consumer->FreeBuffers();
1378
1379 producer->WaitForDataSourceStop("data_source_b");
1380 consumer->WaitForTracingDisabled();
1381 }
1382 }
1383
TEST_F(TracingServiceImplTest,SecondTriggerDoesntHitLimit)1384 TEST_F(TracingServiceImplTest, SecondTriggerDoesntHitLimit) {
1385 TraceConfig trace_config;
1386 trace_config.add_buffers()->set_size_kb(128);
1387
1388 auto* trigger_config = trace_config.mutable_trigger_config();
1389 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1390 trigger_config->set_trigger_timeout_ms(8.64e+7);
1391
1392 auto* trigger = trigger_config->add_triggers();
1393 trigger->set_name("trigger_name");
1394 trigger->set_stop_delay_ms(1);
1395 trigger->set_max_per_24_h(1);
1396
1397 auto* ds = trace_config.add_data_sources()->mutable_config();
1398
1399 // Set the trigger window size to something really small so the second
1400 // session is still allowed through.
1401 SetTriggerWindowNs(1);
1402
1403 // First session.
1404 {
1405 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1406 producer->Connect(svc.get(), "mock_producer_a");
1407 producer->RegisterDataSource("data_source_a");
1408
1409 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1410 consumer->Connect(svc.get());
1411
1412 ds->set_name("data_source_a");
1413 consumer->EnableTracing(trace_config);
1414 producer->WaitForTracingSetup();
1415
1416 producer->WaitForDataSourceSetup("data_source_a");
1417 producer->WaitForDataSourceStart("data_source_a");
1418
1419 std::vector<std::string> req;
1420 req.push_back("trigger_name");
1421 producer->endpoint()->ActivateTriggers(req);
1422
1423 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
1424 EXPECT_EQ("trigger_name",
1425 tracing_session()->received_triggers[0].trigger_name);
1426
1427 auto writer = producer->CreateTraceWriter("data_source_a");
1428 producer->ExpectFlush(writer.get());
1429
1430 producer->WaitForDataSourceStop("data_source_a");
1431 consumer->WaitForTracingDisabled();
1432 EXPECT_THAT(
1433 consumer->ReadBuffers(),
1434 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
1435 }
1436
1437 // Sleep 1 micro so that we're sure that the window time would have elapsed.
1438 base::SleepMicroseconds(1);
1439
1440 // Second session.
1441 {
1442 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1443 producer->Connect(svc.get(), "mock_producer_b");
1444 producer->RegisterDataSource("data_source_b");
1445
1446 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1447 consumer->Connect(svc.get());
1448
1449 ds->set_name("data_source_b");
1450 consumer->EnableTracing(trace_config);
1451 producer->WaitForTracingSetup();
1452
1453 producer->WaitForDataSourceSetup("data_source_b");
1454 producer->WaitForDataSourceStart("data_source_b");
1455
1456 std::vector<std::string> req;
1457 req.push_back("trigger_name");
1458 producer->endpoint()->ActivateTriggers(req);
1459
1460 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
1461 EXPECT_EQ("trigger_name",
1462 tracing_session()->received_triggers[0].trigger_name);
1463
1464 auto writer = producer->CreateTraceWriter("data_source_b");
1465 producer->ExpectFlush(writer.get());
1466
1467 producer->WaitForDataSourceStop("data_source_b");
1468 consumer->WaitForTracingDisabled();
1469 EXPECT_THAT(
1470 consumer->ReadBuffers(),
1471 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
1472 }
1473 }
1474
TEST_F(TracingServiceImplTest,SkipProbability)1475 TEST_F(TracingServiceImplTest, SkipProbability) {
1476 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1477 consumer->Connect(svc.get());
1478
1479 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1480 producer->Connect(svc.get(), "mock_producer");
1481
1482 producer->RegisterDataSource("data_source");
1483
1484 TraceConfig trace_config;
1485 trace_config.add_buffers()->set_size_kb(128);
1486 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
1487 auto* trigger_config = trace_config.mutable_trigger_config();
1488 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
1489 auto* trigger = trigger_config->add_triggers();
1490 trigger->set_name("trigger_name");
1491 trigger->set_stop_delay_ms(1);
1492 trigger->set_skip_probability(0.15);
1493
1494 trigger_config->set_trigger_timeout_ms(8.64e+7);
1495
1496 consumer->EnableTracing(trace_config);
1497 producer->WaitForTracingSetup();
1498
1499 producer->WaitForDataSourceSetup("data_source");
1500 producer->WaitForDataSourceStart("data_source");
1501
1502 std::vector<std::string> req;
1503 req.push_back("trigger_name");
1504
1505 // This is below the probability of 0.15 so should be skipped.
1506 OverrideNextTriggerRandomNumber(0.14);
1507 producer->endpoint()->ActivateTriggers(req);
1508
1509 ASSERT_EQ(0u, tracing_session()->received_triggers.size());
1510
1511 // This is above the probaility of 0.15 so should be allowed.
1512 OverrideNextTriggerRandomNumber(0.16);
1513 producer->endpoint()->ActivateTriggers(req);
1514
1515 auto writer = producer->CreateTraceWriter("data_source");
1516 producer->ExpectFlush(writer.get());
1517
1518 ASSERT_EQ(1u, tracing_session()->received_triggers.size());
1519 EXPECT_EQ("trigger_name",
1520 tracing_session()->received_triggers[0].trigger_name);
1521
1522 producer->WaitForDataSourceStop("data_source");
1523 consumer->WaitForTracingDisabled();
1524 EXPECT_THAT(
1525 consumer->ReadBuffers(),
1526 HasTriggerMode(protos::gen::TraceConfig::TriggerConfig::STOP_TRACING));
1527 }
1528
1529 // Creates a tracing session with a CLONE_SNAPSHOT trigger and checks that
1530 // ReadBuffer calls on it return consistently no data (as in the case of
1531 // STOP_TRACING with no triggers hit) to avoid double uploads (b/290799105 and
1532 // b/290798988).
TEST_F(TracingServiceImplTest,CloneSnapshotTriggers)1533 TEST_F(TracingServiceImplTest, CloneSnapshotTriggers) {
1534 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1535 consumer->Connect(svc.get());
1536
1537 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1538 producer->Connect(svc.get(), "mock_producer");
1539 producer->RegisterDataSource("ds_1");
1540
1541 TraceConfig trace_config;
1542 trace_config.add_buffers()->set_size_kb(128);
1543 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
1544 auto* trigger_config = trace_config.mutable_trigger_config();
1545 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::CLONE_SNAPSHOT);
1546 trigger_config->set_trigger_timeout_ms(8.64e+7);
1547 for (int i = 0; i < 3; i++) {
1548 auto* trigger = trigger_config->add_triggers();
1549 trigger->set_name("trigger_" + std::to_string(i));
1550 trigger->set_stop_delay_ms(1);
1551 }
1552
1553 consumer->EnableTracing(trace_config);
1554 producer->WaitForTracingSetup();
1555
1556 producer->WaitForDataSourceSetup("ds_1");
1557 producer->WaitForDataSourceStart("ds_1");
1558
1559 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
1560
1561 auto writer = producer->CreateTraceWriter("ds_1");
1562
1563 TracingSessionID orig_tsid = GetTracingSessionID();
1564
1565 // Iterate over a sequence of trigger + CloneSession, to emulate a long trace
1566 // receiving different triggers and being cloned several times.
1567 for (int iter = 0; iter < 3; iter++) {
1568 std::string trigger_name = "trigger_" + std::to_string(iter);
1569 producer->endpoint()->ActivateTriggers({trigger_name});
1570
1571 auto* orig_session = GetTracingSession(orig_tsid);
1572 ASSERT_EQ(orig_session->received_triggers.size(), 1u);
1573 EXPECT_EQ(trigger_name, orig_session->received_triggers[0].trigger_name);
1574
1575 // Reading the original trace session should always return nothing. Only the
1576 // cloned sessions should return data.
1577 EXPECT_THAT(consumer->ReadBuffers(), IsEmpty());
1578
1579 // Now clone the session and check that the cloned session has the triggers.
1580 std::unique_ptr<MockConsumer> clone_cons = CreateMockConsumer();
1581 clone_cons->Connect(svc.get());
1582
1583 std::string checkpoint_name = "clone_done_" + std::to_string(iter);
1584 auto clone_done = task_runner.CreateCheckpoint(checkpoint_name);
1585 EXPECT_CALL(*clone_cons, OnSessionCloned(_))
1586 .WillOnce(InvokeWithoutArgs(clone_done));
1587 clone_cons->CloneSession(orig_tsid);
1588 // CloneSession() will implicitly issue a flush. Linearize with that.
1589 producer->ExpectFlush(writer.get());
1590 task_runner.RunUntilCheckpoint(checkpoint_name);
1591
1592 // Read the cloned session and ensure it only contains the last trigger
1593 // (i.e. check that the trigger history is reset after each clone and
1594 // doesn't pile up).
1595 auto packets = clone_cons->ReadBuffers();
1596 auto expect_received_trigger = [](const std::string& name) {
1597 return Contains(
1598 Property(&protos::gen::TracePacket::trigger,
1599 Property(&protos::gen::Trigger::trigger_name, Eq(name))));
1600 };
1601 EXPECT_THAT(packets, expect_received_trigger(trigger_name));
1602 EXPECT_THAT(
1603 packets,
1604 Not(expect_received_trigger("trigger_" + std::to_string(iter - 1))));
1605 } // for (iter)
1606
1607 consumer->DisableTracing();
1608 producer->WaitForDataSourceStop("ds_1");
1609 consumer->WaitForTracingDisabled();
1610 }
1611
TEST_F(TracingServiceImplTest,LockdownMode)1612 TEST_F(TracingServiceImplTest, LockdownMode) {
1613 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1614 consumer->Connect(svc.get());
1615
1616 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1617 producer->Connect(svc.get(), "mock_producer_sameuid",
1618 base::GetCurrentUserId());
1619 producer->RegisterDataSource("data_source");
1620
1621 TraceConfig trace_config;
1622 trace_config.add_buffers()->set_size_kb(128);
1623 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1624 ds_config->set_name("data_source");
1625 trace_config.set_lockdown_mode(TraceConfig::LOCKDOWN_SET);
1626 consumer->EnableTracing(trace_config);
1627
1628 producer->WaitForTracingSetup();
1629 producer->WaitForDataSourceSetup("data_source");
1630 producer->WaitForDataSourceStart("data_source");
1631
1632 std::unique_ptr<MockProducer> producer_otheruid = CreateMockProducer();
1633 auto x = svc->ConnectProducer(
1634 producer_otheruid.get(),
1635 ClientIdentity(base::GetCurrentUserId() + 1, base::GetProcessId()),
1636 "mock_producer_ouid");
1637 EXPECT_CALL(*producer_otheruid, OnConnect()).Times(0);
1638 task_runner.RunUntilIdle();
1639 Mock::VerifyAndClearExpectations(producer_otheruid.get());
1640
1641 consumer->DisableTracing();
1642 consumer->FreeBuffers();
1643 producer->WaitForDataSourceStop("data_source");
1644 consumer->WaitForTracingDisabled();
1645
1646 trace_config.set_lockdown_mode(TraceConfig::LOCKDOWN_CLEAR);
1647 consumer->EnableTracing(trace_config);
1648 producer->WaitForDataSourceSetup("data_source");
1649 producer->WaitForDataSourceStart("data_source");
1650
1651 std::unique_ptr<MockProducer> producer_otheruid2 = CreateMockProducer();
1652 producer_otheruid->Connect(svc.get(), "mock_producer_ouid2",
1653 base::GetCurrentUserId() + 1);
1654
1655 consumer->DisableTracing();
1656 producer->WaitForDataSourceStop("data_source");
1657 consumer->WaitForTracingDisabled();
1658 }
1659
TEST_F(TracingServiceImplTest,ProducerNameFilterChange)1660 TEST_F(TracingServiceImplTest, ProducerNameFilterChange) {
1661 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1662 consumer->Connect(svc.get());
1663
1664 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
1665 producer1->Connect(svc.get(), "mock_producer_1");
1666 producer1->RegisterDataSource("data_source");
1667
1668 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
1669 producer2->Connect(svc.get(), "mock_producer_2");
1670 producer2->RegisterDataSource("data_source");
1671
1672 std::unique_ptr<MockProducer> producer3 = CreateMockProducer();
1673 producer3->Connect(svc.get(), "mock_producer_3");
1674 producer3->RegisterDataSource("data_source");
1675 producer3->RegisterDataSource("unused_data_source");
1676
1677 TraceConfig trace_config;
1678 trace_config.add_buffers()->set_size_kb(128);
1679 auto* data_source = trace_config.add_data_sources();
1680 data_source->mutable_config()->set_name("data_source");
1681 *data_source->add_producer_name_filter() = "mock_producer_1";
1682
1683 // Enable tracing with only mock_producer_1 enabled;
1684 // the rest should not start up.
1685 consumer->EnableTracing(trace_config);
1686
1687 producer1->WaitForTracingSetup();
1688 producer1->WaitForDataSourceSetup("data_source");
1689 producer1->WaitForDataSourceStart("data_source");
1690
1691 EXPECT_CALL(*producer2, OnConnect()).Times(0);
1692 EXPECT_CALL(*producer3, OnConnect()).Times(0);
1693 task_runner.RunUntilIdle();
1694 Mock::VerifyAndClearExpectations(producer2.get());
1695 Mock::VerifyAndClearExpectations(producer3.get());
1696
1697 // Enable mock_producer_2, the third one should still
1698 // not get connected.
1699 *data_source->add_producer_name_regex_filter() = ".*_producer_[2]";
1700 consumer->ChangeTraceConfig(trace_config);
1701
1702 producer2->WaitForTracingSetup();
1703 producer2->WaitForDataSourceSetup("data_source");
1704 producer2->WaitForDataSourceStart("data_source");
1705
1706 // Enable mock_producer_3 but also try to do an
1707 // unsupported change (adding a new data source);
1708 // mock_producer_3 should get enabled but not
1709 // for the new data source.
1710 *data_source->add_producer_name_filter() = "mock_producer_3";
1711 auto* dummy_data_source = trace_config.add_data_sources();
1712 dummy_data_source->mutable_config()->set_name("unused_data_source");
1713 *dummy_data_source->add_producer_name_filter() = "mock_producer_3";
1714
1715 consumer->ChangeTraceConfig(trace_config);
1716
1717 producer3->WaitForTracingSetup();
1718 EXPECT_CALL(*producer3, SetupDataSource(_, _)).Times(1);
1719 EXPECT_CALL(*producer3, StartDataSource(_, _)).Times(1);
1720 task_runner.RunUntilIdle();
1721 Mock::VerifyAndClearExpectations(producer3.get());
1722
1723 consumer->DisableTracing();
1724 consumer->FreeBuffers();
1725 producer1->WaitForDataSourceStop("data_source");
1726 producer2->WaitForDataSourceStop("data_source");
1727
1728 EXPECT_CALL(*producer3, StopDataSource(_)).Times(1);
1729
1730 consumer->WaitForTracingDisabled();
1731
1732 task_runner.RunUntilIdle();
1733 Mock::VerifyAndClearExpectations(producer3.get());
1734 }
1735
TEST_F(TracingServiceImplTest,ProducerNameFilterChangeTwoDataSources)1736 TEST_F(TracingServiceImplTest, ProducerNameFilterChangeTwoDataSources) {
1737 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1738 consumer->Connect(svc.get());
1739
1740 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
1741 producer1->Connect(svc.get(), "mock_producer_1");
1742 producer1->RegisterDataSource("data_source");
1743
1744 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
1745 producer2->Connect(svc.get(), "mock_producer_2");
1746 producer2->RegisterDataSource("data_source");
1747 producer2->RegisterDataSource("data_source");
1748
1749 TraceConfig trace_config;
1750 trace_config.add_buffers()->set_size_kb(128);
1751 auto* data_source = trace_config.add_data_sources();
1752 data_source->mutable_config()->set_name("data_source");
1753 *data_source->add_producer_name_filter() = "mock_producer_1";
1754
1755 // Enable tracing with only mock_producer_1 enabled;
1756 // the rest should not start up.
1757 consumer->EnableTracing(trace_config);
1758
1759 producer1->WaitForTracingSetup();
1760 EXPECT_CALL(*producer1, SetupDataSource(_, _)).Times(1);
1761 EXPECT_CALL(*producer1, StartDataSource(_, _)).Times(1);
1762
1763 task_runner.RunUntilIdle();
1764 Mock::VerifyAndClearExpectations(producer1.get());
1765 Mock::VerifyAndClearExpectations(producer2.get());
1766
1767 // Enable mock_producer_2, both instances of "data_source" should start
1768 *data_source->add_producer_name_regex_filter() = ".*_producer_[2]";
1769 consumer->ChangeTraceConfig(trace_config);
1770
1771 producer2->WaitForTracingSetup();
1772 EXPECT_CALL(*producer2, SetupDataSource(_, _)).Times(2);
1773 EXPECT_CALL(*producer2, StartDataSource(_, _)).Times(2);
1774
1775 task_runner.RunUntilIdle();
1776 Mock::VerifyAndClearExpectations(producer1.get());
1777 Mock::VerifyAndClearExpectations(producer2.get());
1778
1779 consumer->DisableTracing();
1780 consumer->FreeBuffers();
1781
1782 EXPECT_CALL(*producer1, StopDataSource(_)).Times(1);
1783 EXPECT_CALL(*producer2, StopDataSource(_)).Times(2);
1784
1785 consumer->WaitForTracingDisabled();
1786
1787 task_runner.RunUntilIdle();
1788 Mock::VerifyAndClearExpectations(producer1.get());
1789 Mock::VerifyAndClearExpectations(producer2.get());
1790 }
1791
TEST_F(TracingServiceImplTest,DisconnectConsumerWhileTracing)1792 TEST_F(TracingServiceImplTest, DisconnectConsumerWhileTracing) {
1793 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1794 consumer->Connect(svc.get());
1795
1796 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1797 producer->Connect(svc.get(), "mock_producer");
1798 producer->RegisterDataSource("data_source");
1799
1800 TraceConfig trace_config;
1801 trace_config.add_buffers()->set_size_kb(128);
1802 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1803 ds_config->set_name("data_source");
1804 consumer->EnableTracing(trace_config);
1805
1806 producer->WaitForTracingSetup();
1807 producer->WaitForDataSourceSetup("data_source");
1808 producer->WaitForDataSourceStart("data_source");
1809
1810 // Disconnecting the consumer while tracing should trigger data source
1811 // teardown.
1812 consumer.reset();
1813 producer->WaitForDataSourceStop("data_source");
1814 }
1815
TEST_F(TracingServiceImplTest,ReconnectProducerWhileTracing)1816 TEST_F(TracingServiceImplTest, ReconnectProducerWhileTracing) {
1817 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1818 consumer->Connect(svc.get());
1819
1820 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1821 producer->Connect(svc.get(), "mock_producer");
1822 producer->RegisterDataSource("data_source");
1823
1824 TraceConfig trace_config;
1825 trace_config.add_buffers()->set_size_kb(128);
1826 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1827 ds_config->set_name("data_source");
1828 consumer->EnableTracing(trace_config);
1829
1830 producer->WaitForTracingSetup();
1831 producer->WaitForDataSourceSetup("data_source");
1832 producer->WaitForDataSourceStart("data_source");
1833
1834 // Disconnecting and reconnecting a producer with a matching data source.
1835 // The Producer should see that data source getting enabled again.
1836 producer.reset();
1837 producer = CreateMockProducer();
1838 producer->Connect(svc.get(), "mock_producer_2");
1839 producer->RegisterDataSource("data_source");
1840 producer->WaitForTracingSetup();
1841 producer->WaitForDataSourceSetup("data_source");
1842 producer->WaitForDataSourceStart("data_source");
1843 }
1844
TEST_F(TracingServiceImplTest,ProducerIDWrapping)1845 TEST_F(TracingServiceImplTest, ProducerIDWrapping) {
1846 std::vector<std::unique_ptr<MockProducer>> producers;
1847 producers.push_back(nullptr);
1848
1849 auto connect_producer_and_get_id = [&producers,
1850 this](const std::string& name) {
1851 producers.emplace_back(CreateMockProducer());
1852 producers.back()->Connect(svc.get(), "mock_producer_" + name);
1853 return *last_producer_id();
1854 };
1855
1856 // Connect producers 1-4.
1857 for (ProducerID i = 1; i <= 4; i++)
1858 ASSERT_EQ(i, connect_producer_and_get_id(std::to_string(i)));
1859
1860 // Disconnect producers 1,3.
1861 producers[1].reset();
1862 producers[3].reset();
1863
1864 *last_producer_id() = kMaxProducerID - 1;
1865 ASSERT_EQ(kMaxProducerID, connect_producer_and_get_id("maxid"));
1866 ASSERT_EQ(1u, connect_producer_and_get_id("1_again"));
1867 ASSERT_EQ(3u, connect_producer_and_get_id("3_again"));
1868 ASSERT_EQ(5u, connect_producer_and_get_id("5"));
1869 ASSERT_EQ(6u, connect_producer_and_get_id("6"));
1870 }
1871
TEST_F(TracingServiceImplTest,CompressionConfiguredButUnsupported)1872 TEST_F(TracingServiceImplTest, CompressionConfiguredButUnsupported) {
1873 // Initialize the service without support for compression.
1874 TracingService::InitOpts init_opts;
1875 init_opts.compressor_fn = nullptr;
1876 InitializeSvcWithOpts(init_opts);
1877
1878 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1879 consumer->Connect(svc.get());
1880
1881 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1882 producer->Connect(svc.get(), "mock_producer");
1883 producer->RegisterDataSource("data_source");
1884
1885 TraceConfig trace_config;
1886 trace_config.add_buffers()->set_size_kb(4096);
1887 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1888 ds_config->set_name("data_source");
1889 ds_config->set_target_buffer(0);
1890 // Ask for compression in the config.
1891 trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
1892 consumer->EnableTracing(trace_config);
1893
1894 producer->WaitForTracingSetup();
1895 producer->WaitForDataSourceSetup("data_source");
1896 producer->WaitForDataSourceStart("data_source");
1897
1898 std::unique_ptr<TraceWriter> writer =
1899 producer->CreateTraceWriter("data_source");
1900 {
1901 auto tp = writer->NewTracePacket();
1902 tp->set_for_testing()->set_str("payload-1");
1903 }
1904 {
1905 auto tp = writer->NewTracePacket();
1906 tp->set_for_testing()->set_str("payload-2");
1907 }
1908
1909 writer->Flush();
1910 writer.reset();
1911
1912 consumer->DisableTracing();
1913 producer->WaitForDataSourceStop("data_source");
1914 consumer->WaitForTracingDisabled();
1915
1916 // The packets should NOT be compressed.
1917 std::vector<protos::gen::TracePacket> packets = consumer->ReadBuffers();
1918 EXPECT_THAT(packets, Not(IsEmpty()));
1919 EXPECT_THAT(
1920 packets,
1921 Each(Property(&protos::gen::TracePacket::has_compressed_packets, false)));
1922 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
1923 Property(&protos::gen::TestEvent::str,
1924 Eq("payload-1")))));
1925 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
1926 Property(&protos::gen::TestEvent::str,
1927 Eq("payload-2")))));
1928 }
1929
1930 #if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
TEST_F(TracingServiceImplTest,CompressionReadIpc)1931 TEST_F(TracingServiceImplTest, CompressionReadIpc) {
1932 TracingService::InitOpts init_opts;
1933 init_opts.compressor_fn = ZlibCompressFn;
1934 InitializeSvcWithOpts(init_opts);
1935
1936 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1937 consumer->Connect(svc.get());
1938
1939 std::unique_ptr<MockProducer> producer = CreateMockProducer();
1940 producer->Connect(svc.get(), "mock_producer");
1941 producer->RegisterDataSource("data_source");
1942
1943 TraceConfig trace_config;
1944 trace_config.add_buffers()->set_size_kb(4096);
1945 auto* ds_config = trace_config.add_data_sources()->mutable_config();
1946 ds_config->set_name("data_source");
1947 ds_config->set_target_buffer(0);
1948 trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
1949 consumer->EnableTracing(trace_config);
1950
1951 producer->WaitForTracingSetup();
1952 producer->WaitForDataSourceSetup("data_source");
1953 producer->WaitForDataSourceStart("data_source");
1954
1955 std::unique_ptr<TraceWriter> writer =
1956 producer->CreateTraceWriter("data_source");
1957 {
1958 auto tp = writer->NewTracePacket();
1959 tp->set_for_testing()->set_str("payload-1");
1960 }
1961 {
1962 auto tp = writer->NewTracePacket();
1963 tp->set_for_testing()->set_str("payload-2");
1964 }
1965
1966 writer->Flush();
1967 writer.reset();
1968
1969 consumer->DisableTracing();
1970 producer->WaitForDataSourceStop("data_source");
1971 consumer->WaitForTracingDisabled();
1972
1973 std::vector<protos::gen::TracePacket> compressed_packets =
1974 consumer->ReadBuffers();
1975 EXPECT_THAT(compressed_packets, Not(IsEmpty()));
1976 EXPECT_THAT(compressed_packets,
1977 Each(Property(&protos::gen::TracePacket::compressed_packets,
1978 Not(IsEmpty()))));
1979 std::vector<protos::gen::TracePacket> decompressed_packets =
1980 DecompressTrace(compressed_packets);
1981 EXPECT_THAT(decompressed_packets,
1982 Contains(Property(
1983 &protos::gen::TracePacket::for_testing,
1984 Property(&protos::gen::TestEvent::str, Eq("payload-1")))));
1985 EXPECT_THAT(decompressed_packets,
1986 Contains(Property(
1987 &protos::gen::TracePacket::for_testing,
1988 Property(&protos::gen::TestEvent::str, Eq("payload-2")))));
1989 }
1990
TEST_F(TracingServiceImplTest,CompressionWriteIntoFile)1991 TEST_F(TracingServiceImplTest, CompressionWriteIntoFile) {
1992 TracingService::InitOpts init_opts;
1993 init_opts.compressor_fn = ZlibCompressFn;
1994 InitializeSvcWithOpts(init_opts);
1995
1996 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
1997 consumer->Connect(svc.get());
1998
1999 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2000 producer->Connect(svc.get(), "mock_producer");
2001 producer->RegisterDataSource("data_source");
2002
2003 TraceConfig trace_config;
2004 trace_config.add_buffers()->set_size_kb(4096);
2005 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2006 ds_config->set_name("data_source");
2007 ds_config->set_target_buffer(0);
2008 trace_config.set_write_into_file(true);
2009 trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
2010 base::TempFile tmp_file = base::TempFile::Create();
2011 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
2012
2013 producer->WaitForTracingSetup();
2014 producer->WaitForDataSourceSetup("data_source");
2015 producer->WaitForDataSourceStart("data_source");
2016
2017 std::unique_ptr<TraceWriter> writer =
2018 producer->CreateTraceWriter("data_source");
2019 {
2020 auto tp = writer->NewTracePacket();
2021 tp->set_for_testing()->set_str("payload-1");
2022 }
2023 {
2024 auto tp = writer->NewTracePacket();
2025 tp->set_for_testing()->set_str("payload-2");
2026 }
2027
2028 writer->Flush();
2029 writer.reset();
2030
2031 consumer->DisableTracing();
2032 producer->WaitForDataSourceStop("data_source");
2033 consumer->WaitForTracingDisabled();
2034
2035 // Verify the contents of the file.
2036 std::string trace_raw;
2037 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
2038 protos::gen::Trace trace;
2039 ASSERT_TRUE(trace.ParseFromString(trace_raw));
2040 EXPECT_THAT(trace.packet(), Not(IsEmpty()));
2041 EXPECT_THAT(trace.packet(),
2042 Each(Property(&protos::gen::TracePacket::compressed_packets,
2043 Not(IsEmpty()))));
2044 std::vector<protos::gen::TracePacket> decompressed_packets =
2045 DecompressTrace(trace.packet());
2046 EXPECT_THAT(decompressed_packets,
2047 Contains(Property(
2048 &protos::gen::TracePacket::for_testing,
2049 Property(&protos::gen::TestEvent::str, Eq("payload-1")))));
2050 EXPECT_THAT(decompressed_packets,
2051 Contains(Property(
2052 &protos::gen::TracePacket::for_testing,
2053 Property(&protos::gen::TestEvent::str, Eq("payload-2")))));
2054 }
2055
TEST_F(TracingServiceImplTest,CloneSessionWithCompression)2056 TEST_F(TracingServiceImplTest, CloneSessionWithCompression) {
2057 TracingService::InitOpts init_opts;
2058 init_opts.compressor_fn = ZlibCompressFn;
2059 InitializeSvcWithOpts(init_opts);
2060
2061 // The consumer the creates the initial tracing session.
2062 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2063 consumer->Connect(svc.get());
2064
2065 // The consumer that clones it and reads back the data.
2066 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
2067 consumer2->Connect(svc.get());
2068
2069 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2070 producer->Connect(svc.get(), "mock_producer");
2071
2072 producer->RegisterDataSource("ds_1");
2073
2074 TraceConfig trace_config;
2075 trace_config.add_buffers()->set_size_kb(32);
2076 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
2077 ds_cfg->set_name("ds_1");
2078 trace_config.set_compression_type(TraceConfig::COMPRESSION_TYPE_DEFLATE);
2079
2080 consumer->EnableTracing(trace_config);
2081 producer->WaitForTracingSetup();
2082
2083 producer->WaitForDataSourceSetup("ds_1");
2084
2085 producer->WaitForDataSourceStart("ds_1");
2086
2087 std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
2088
2089 // Add some data.
2090 static constexpr size_t kNumTestPackets = 20;
2091 for (size_t i = 0; i < kNumTestPackets; i++) {
2092 auto tp = writer->NewTracePacket();
2093 std::string payload("payload" + std::to_string(i));
2094 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
2095 tp->set_timestamp(static_cast<uint64_t>(i));
2096 }
2097
2098 auto clone_done = task_runner.CreateCheckpoint("clone_done");
2099 EXPECT_CALL(*consumer2, OnSessionCloned(_))
2100 .WillOnce(Invoke([clone_done](const Consumer::OnSessionClonedArgs&) {
2101 clone_done();
2102 }));
2103 consumer2->CloneSession(1);
2104 // CloneSession() will implicitly issue a flush. Linearize with that.
2105 FlushFlags expected_flags(FlushFlags::Initiator::kTraced,
2106 FlushFlags::Reason::kTraceClone);
2107 producer->ExpectFlush(writer.get(), /*reply=*/true, expected_flags);
2108 task_runner.RunUntilCheckpoint("clone_done");
2109
2110 // Delete the initial tracing session.
2111 consumer->DisableTracing();
2112 consumer->FreeBuffers();
2113 producer->WaitForDataSourceStop("ds_1");
2114 consumer->WaitForTracingDisabled();
2115
2116 // Read back the cloned trace and check that it's compressed
2117 std::vector<protos::gen::TracePacket> compressed_packets =
2118 consumer2->ReadBuffers();
2119 EXPECT_THAT(compressed_packets, Not(IsEmpty()));
2120 EXPECT_THAT(compressed_packets,
2121 Each(Property(&protos::gen::TracePacket::compressed_packets,
2122 Not(IsEmpty()))));
2123 }
2124
2125 #endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
2126
2127 // Note: file_write_period_ms is set to a large enough to have exactly one flush
2128 // of the tracing buffers (and therefore at most one synchronization section),
2129 // unless the test runs unrealistically slowly, or the implementation of the
2130 // tracing snapshot packets changes.
TEST_F(TracingServiceImplTest,WriteIntoFileAndStopOnMaxSize)2131 TEST_F(TracingServiceImplTest, WriteIntoFileAndStopOnMaxSize) {
2132 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2133 consumer->Connect(svc.get());
2134
2135 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2136 producer->Connect(svc.get(), "mock_producer");
2137 producer->RegisterDataSource("data_source");
2138
2139 TraceConfig trace_config;
2140 trace_config.add_buffers()->set_size_kb(4096);
2141 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2142 ds_config->set_name("data_source");
2143 ds_config->set_target_buffer(0);
2144 trace_config.set_write_into_file(true);
2145 trace_config.set_file_write_period_ms(100000); // 100s
2146 const uint64_t kMaxFileSize = 1024;
2147 trace_config.set_max_file_size_bytes(kMaxFileSize);
2148 base::TempFile tmp_file = base::TempFile::Create();
2149 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
2150
2151 producer->WaitForTracingSetup();
2152 producer->WaitForDataSourceSetup("data_source");
2153 producer->WaitForDataSourceStart("data_source");
2154
2155 // The preamble packets are:
2156 // Trace start clock snapshot
2157 // Trace most recent clock snapshot
2158 // Trace synchronisation
2159 // TraceUuid
2160 // Config
2161 // SystemInfo
2162 // Tracing started (TracingServiceEvent)
2163 // All data source started (TracingServiceEvent)
2164 // Tracing disabled (TracingServiceEvent)
2165 static const int kNumPreamblePackets = 9;
2166 static const int kNumTestPackets = 9;
2167 static const char kPayload[] = "1234567890abcdef-";
2168
2169 std::unique_ptr<TraceWriter> writer =
2170 producer->CreateTraceWriter("data_source");
2171 // Tracing service will emit a preamble of packets (a synchronization section,
2172 // followed by a tracing config packet). The preamble and these test packets
2173 // should fit within kMaxFileSize.
2174 for (int i = 0; i < kNumTestPackets; i++) {
2175 auto tp = writer->NewTracePacket();
2176 std::string payload(kPayload);
2177 payload.append(std::to_string(i));
2178 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
2179 }
2180
2181 // Finally add a packet that overflows kMaxFileSize. This should cause the
2182 // implicit stop of the trace and should *not* be written in the trace.
2183 {
2184 auto tp = writer->NewTracePacket();
2185 char big_payload[kMaxFileSize] = "BIG!";
2186 tp->set_for_testing()->set_str(big_payload, sizeof(big_payload));
2187 }
2188 writer->Flush();
2189 writer.reset();
2190
2191 consumer->DisableTracing();
2192 producer->WaitForDataSourceStop("data_source");
2193 consumer->WaitForTracingDisabled();
2194
2195 // Verify the contents of the file.
2196 std::string trace_raw;
2197 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
2198 protos::gen::Trace trace;
2199 ASSERT_TRUE(trace.ParseFromString(trace_raw));
2200
2201 ASSERT_EQ(trace.packet_size(), kNumPreamblePackets + kNumTestPackets);
2202 for (size_t i = 0; i < kNumTestPackets; i++) {
2203 const protos::gen::TracePacket& tp =
2204 trace.packet()[kNumPreamblePackets + i];
2205 ASSERT_EQ(kPayload + std::to_string(i++), tp.for_testing().str());
2206 }
2207 }
2208
TEST_F(TracingServiceImplTest,WriteIntoFileWithPath)2209 TEST_F(TracingServiceImplTest, WriteIntoFileWithPath) {
2210 auto tmp_file = base::TempFile::Create();
2211 // Deletes the file (the service would refuse to overwrite an existing file)
2212 // without telling it to the underlying TempFile, so that its dtor will
2213 // unlink the file created by the service.
2214 unlink(tmp_file.path().c_str());
2215
2216 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2217 consumer->Connect(svc.get());
2218
2219 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2220 producer->Connect(svc.get(), "mock_producer");
2221 producer->RegisterDataSource("data_source");
2222
2223 TraceConfig trace_config;
2224 trace_config.add_buffers()->set_size_kb(4096);
2225 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2226 ds_config->set_name("data_source");
2227 ds_config->set_target_buffer(0);
2228 trace_config.set_write_into_file(true);
2229 trace_config.set_output_path(tmp_file.path());
2230 consumer->EnableTracing(trace_config);
2231
2232 producer->WaitForTracingSetup();
2233 producer->WaitForDataSourceSetup("data_source");
2234 producer->WaitForDataSourceStart("data_source");
2235 std::unique_ptr<TraceWriter> writer =
2236 producer->CreateTraceWriter("data_source");
2237
2238 {
2239 auto tp = writer->NewTracePacket();
2240 tp->set_for_testing()->set_str("payload");
2241 }
2242 writer->Flush();
2243 writer.reset();
2244
2245 consumer->DisableTracing();
2246 producer->WaitForDataSourceStop("data_source");
2247 consumer->WaitForTracingDisabled();
2248
2249 // Verify the contents of the file.
2250 std::string trace_raw;
2251 ASSERT_TRUE(base::ReadFile(tmp_file.path(), &trace_raw));
2252 protos::gen::Trace trace;
2253 ASSERT_TRUE(trace.ParseFromString(trace_raw));
2254 // ASSERT_EQ(trace.packet_size(), 33);
2255 EXPECT_THAT(trace.packet(),
2256 Contains(Property(
2257 &protos::gen::TracePacket::for_testing,
2258 Property(&protos::gen::TestEvent::str, Eq("payload")))));
2259 }
2260
TEST_F(TracingServiceImplTest,WriteIntoFileFilterMultipleChunks)2261 TEST_F(TracingServiceImplTest, WriteIntoFileFilterMultipleChunks) {
2262 static const size_t kNumTestPackets = 5;
2263 static const size_t kPayloadSize = 500 * 1024UL;
2264 static_assert(kNumTestPackets * kPayloadSize >
2265 TracingServiceImpl::kWriteIntoFileChunkSize,
2266 "This test covers filtering multiple chunks");
2267
2268 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2269 consumer->Connect(svc.get());
2270
2271 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2272 producer->Connect(svc.get(), "mock_producer");
2273 producer->RegisterDataSource("data_source");
2274
2275 TraceConfig trace_config;
2276 trace_config.add_buffers()->set_size_kb(4096);
2277 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2278 ds_config->set_name("data_source");
2279 ds_config->set_target_buffer(0);
2280 trace_config.set_write_into_file(true);
2281 trace_config.set_file_write_period_ms(100000); // 100s
2282
2283 protozero::FilterBytecodeGenerator filt;
2284 // Message 0: root Trace proto.
2285 filt.AddNestedField(1 /* root trace.packet*/, 1);
2286 filt.EndMessage();
2287 // Message 1: TracePacket proto. Allow all fields.
2288 filt.AddSimpleFieldRange(1, 1000);
2289 filt.EndMessage();
2290 trace_config.mutable_trace_filter()->set_bytecode(filt.Serialize());
2291
2292 base::TempFile tmp_file = base::TempFile::Create();
2293 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
2294
2295 producer->WaitForTracingSetup();
2296 producer->WaitForDataSourceSetup("data_source");
2297 producer->WaitForDataSourceStart("data_source");
2298
2299 std::unique_ptr<TraceWriter> writer =
2300 producer->CreateTraceWriter("data_source");
2301 for (size_t i = 0; i < kNumTestPackets; i++) {
2302 auto tp = writer->NewTracePacket();
2303 std::string payload(kPayloadSize, 'c');
2304 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
2305 }
2306
2307 writer->Flush();
2308 writer.reset();
2309
2310 consumer->DisableTracing();
2311 producer->WaitForDataSourceStop("data_source");
2312 consumer->WaitForTracingDisabled();
2313
2314 consumer->GetTraceStats();
2315 TraceStats stats = consumer->WaitForTraceStats(true);
2316
2317 std::string trace_raw;
2318 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
2319 protozero::ProtoDecoder dec(trace_raw.data(), trace_raw.size());
2320 size_t total_size = 0;
2321 for (auto field = dec.ReadField(); field.valid(); field = dec.ReadField()) {
2322 total_size += field.size();
2323 }
2324 EXPECT_EQ(total_size, stats.filter_stats().output_bytes());
2325 EXPECT_GT(total_size, kNumTestPackets * kPayloadSize);
2326 }
2327
2328 // Test the logic that allows the trace config to set the shm total size and
2329 // page size from the trace config. Also check that, if the config doesn't
2330 // specify a value we fall back on the hint provided by the producer.
TEST_F(TracingServiceImplTest,ProducerShmAndPageSizeOverriddenByTraceConfig)2331 TEST_F(TracingServiceImplTest, ProducerShmAndPageSizeOverriddenByTraceConfig) {
2332 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2333 consumer->Connect(svc.get());
2334 const size_t kMaxPageSizeKb = 32;
2335
2336 struct ConfiguredAndExpectedSizes {
2337 size_t config_page_size_kb;
2338 size_t hint_page_size_kb;
2339 size_t expected_page_size_kb;
2340
2341 size_t config_size_kb;
2342 size_t hint_size_kb;
2343 size_t expected_size_kb;
2344 };
2345
2346 ConfiguredAndExpectedSizes kSizes[] = {
2347 // Config and hint are 0, fallback to default values.
2348 {0, 0, kDefaultShmPageSizeKb, 0, 0, kDefaultShmSizeKb},
2349 // Use configured sizes.
2350 {16, 0, 16, 16, 0, 16},
2351 // Config is 0, use hint.
2352 {0, 4, 4, 0, 16, 16},
2353 // Config takes precendence over hint.
2354 {4, 8, 4, 16, 32, 16},
2355 // Config takes precendence over hint, even if it's larger.
2356 {8, 4, 8, 32, 16, 32},
2357 // Config page size % 4 != 0, fallback to defaults.
2358 {3, 0, kDefaultShmPageSizeKb, 0, 0, kDefaultShmSizeKb},
2359 // Config page size less than system page size, fallback to defaults.
2360 {2, 0, kDefaultShmPageSizeKb, 0, 0, kDefaultShmSizeKb},
2361 // Config sizes too large, use max.
2362 {4096, 0, kMaxPageSizeKb, 4096000, 0, kMaxShmSizeKb},
2363 // Hint sizes too large, use max.
2364 {0, 4096, kMaxPageSizeKb, 0, 4096000, kMaxShmSizeKb},
2365 // Config buffer size isn't a multiple of 4KB, fallback to defaults.
2366 {0, 0, kDefaultShmPageSizeKb, 18, 0, kDefaultShmSizeKb},
2367 // Invalid page size -> also ignore buffer size config.
2368 {2, 0, kDefaultShmPageSizeKb, 32, 0, kDefaultShmSizeKb},
2369 // Invalid buffer size -> also ignore page size config.
2370 {16, 0, kDefaultShmPageSizeKb, 18, 0, kDefaultShmSizeKb},
2371 // Config page size % buffer size != 0, fallback to defaults.
2372 {8, 0, kDefaultShmPageSizeKb, 20, 0, kDefaultShmSizeKb},
2373 // Config page size % default buffer size != 0, fallback to defaults.
2374 {28, 0, kDefaultShmPageSizeKb, 0, 0, kDefaultShmSizeKb},
2375 };
2376
2377 const size_t kNumProducers = base::ArraySize(kSizes);
2378 std::unique_ptr<MockProducer> producer[kNumProducers];
2379 for (size_t i = 0; i < kNumProducers; i++) {
2380 auto name = "mock_producer_" + std::to_string(i);
2381 producer[i] = CreateMockProducer();
2382 producer[i]->Connect(svc.get(), name, base::GetCurrentUserId(),
2383 base::GetProcessId(), kSizes[i].hint_size_kb * 1024,
2384 kSizes[i].hint_page_size_kb * 1024);
2385 producer[i]->RegisterDataSource("data_source");
2386 }
2387
2388 TraceConfig trace_config;
2389 trace_config.add_buffers()->set_size_kb(128);
2390 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2391 ds_config->set_name("data_source");
2392 for (size_t i = 0; i < kNumProducers; i++) {
2393 auto* producer_config = trace_config.add_producers();
2394 producer_config->set_producer_name("mock_producer_" + std::to_string(i));
2395 producer_config->set_shm_size_kb(
2396 static_cast<uint32_t>(kSizes[i].config_size_kb));
2397 producer_config->set_page_size_kb(
2398 static_cast<uint32_t>(kSizes[i].config_page_size_kb));
2399 }
2400
2401 consumer->EnableTracing(trace_config);
2402 size_t expected_shm_sizes_kb[kNumProducers]{};
2403 size_t expected_page_sizes_kb[kNumProducers]{};
2404 size_t actual_shm_sizes_kb[kNumProducers]{};
2405 size_t actual_page_sizes_kb[kNumProducers]{};
2406 for (size_t i = 0; i < kNumProducers; i++) {
2407 expected_shm_sizes_kb[i] = kSizes[i].expected_size_kb;
2408 expected_page_sizes_kb[i] = kSizes[i].expected_page_size_kb;
2409
2410 producer[i]->WaitForTracingSetup();
2411 producer[i]->WaitForDataSourceSetup("data_source");
2412 actual_shm_sizes_kb[i] =
2413 producer[i]->endpoint()->shared_memory()->size() / 1024;
2414 actual_page_sizes_kb[i] =
2415 producer[i]->endpoint()->shared_buffer_page_size_kb();
2416 }
2417 for (size_t i = 0; i < kNumProducers; i++) {
2418 producer[i]->WaitForDataSourceStart("data_source");
2419 }
2420 ASSERT_THAT(actual_page_sizes_kb, ElementsAreArray(expected_page_sizes_kb));
2421 ASSERT_THAT(actual_shm_sizes_kb, ElementsAreArray(expected_shm_sizes_kb));
2422 }
2423
TEST_F(TracingServiceImplTest,ExplicitFlush)2424 TEST_F(TracingServiceImplTest, ExplicitFlush) {
2425 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2426 consumer->Connect(svc.get());
2427
2428 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2429 producer->Connect(svc.get(), "mock_producer");
2430 producer->RegisterDataSource("data_source");
2431
2432 TraceConfig trace_config;
2433 trace_config.add_buffers()->set_size_kb(128);
2434 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2435 ds_config->set_name("data_source");
2436
2437 consumer->EnableTracing(trace_config);
2438 producer->WaitForTracingSetup();
2439 producer->WaitForDataSourceSetup("data_source");
2440 producer->WaitForDataSourceStart("data_source");
2441
2442 std::unique_ptr<TraceWriter> writer =
2443 producer->CreateTraceWriter("data_source");
2444 {
2445 auto tp = writer->NewTracePacket();
2446 tp->set_for_testing()->set_str("payload");
2447 }
2448
2449 auto flush_request = consumer->Flush();
2450 FlushFlags expected_flags(FlushFlags::Initiator::kConsumerSdk,
2451 FlushFlags::Reason::kExplicit);
2452 producer->ExpectFlush(writer.get(), /*reply=*/true, expected_flags);
2453 ASSERT_TRUE(flush_request.WaitForReply());
2454
2455 consumer->DisableTracing();
2456 producer->WaitForDataSourceStop("data_source");
2457 consumer->WaitForTracingDisabled();
2458 EXPECT_THAT(consumer->ReadBuffers(),
2459 Contains(Property(
2460 &protos::gen::TracePacket::for_testing,
2461 Property(&protos::gen::TestEvent::str, Eq("payload")))));
2462 }
2463
TEST_F(TracingServiceImplTest,ImplicitFlushOnTimedTraces)2464 TEST_F(TracingServiceImplTest, ImplicitFlushOnTimedTraces) {
2465 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2466 consumer->Connect(svc.get());
2467
2468 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2469 producer->Connect(svc.get(), "mock_producer");
2470 producer->RegisterDataSource("data_source");
2471
2472 TraceConfig trace_config;
2473 trace_config.add_buffers()->set_size_kb(128);
2474 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2475 ds_config->set_name("data_source");
2476 trace_config.set_duration_ms(1);
2477
2478 consumer->EnableTracing(trace_config);
2479 producer->WaitForTracingSetup();
2480 producer->WaitForDataSourceSetup("data_source");
2481 producer->WaitForDataSourceStart("data_source");
2482
2483 std::unique_ptr<TraceWriter> writer =
2484 producer->CreateTraceWriter("data_source");
2485 {
2486 auto tp = writer->NewTracePacket();
2487 tp->set_for_testing()->set_str("payload");
2488 }
2489
2490 FlushFlags expected_flags(FlushFlags::Initiator::kTraced,
2491 FlushFlags::Reason::kTraceStop);
2492 producer->ExpectFlush(writer.get(), /*reply=*/true, expected_flags);
2493
2494 producer->WaitForDataSourceStop("data_source");
2495 consumer->WaitForTracingDisabled();
2496
2497 EXPECT_THAT(consumer->ReadBuffers(),
2498 Contains(Property(
2499 &protos::gen::TracePacket::for_testing,
2500 Property(&protos::gen::TestEvent::str, Eq("payload")))));
2501 }
2502
2503 // Tests the monotonic semantic of flush request IDs, i.e., once a producer
2504 // acks flush request N, all flush requests <= N are considered successful and
2505 // acked to the consumer.
TEST_F(TracingServiceImplTest,BatchFlushes)2506 TEST_F(TracingServiceImplTest, BatchFlushes) {
2507 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2508 consumer->Connect(svc.get());
2509
2510 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2511 producer->Connect(svc.get(), "mock_producer");
2512 producer->RegisterDataSource("data_source");
2513
2514 TraceConfig trace_config;
2515 trace_config.add_buffers()->set_size_kb(128);
2516 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2517 ds_config->set_name("data_source");
2518
2519 consumer->EnableTracing(trace_config);
2520 producer->WaitForTracingSetup();
2521 producer->WaitForDataSourceSetup("data_source");
2522 producer->WaitForDataSourceStart("data_source");
2523
2524 std::unique_ptr<TraceWriter> writer =
2525 producer->CreateTraceWriter("data_source");
2526 {
2527 auto tp = writer->NewTracePacket();
2528 tp->set_for_testing()->set_str("payload");
2529 }
2530
2531 auto flush_req_1 = consumer->Flush();
2532 auto flush_req_2 = consumer->Flush();
2533 auto flush_req_3 = consumer->Flush();
2534
2535 // We'll deliberately let the 4th flush request timeout. Use a lower timeout
2536 // to keep test time short.
2537 auto flush_req_4 = consumer->Flush(/*timeout_ms=*/10);
2538 ASSERT_EQ(4u, GetNumPendingFlushes());
2539
2540 // Make the producer reply only to the 3rd flush request.
2541 InSequence seq;
2542 producer->ExpectFlush(nullptr, /*reply=*/false); // Do NOT reply to flush 1.
2543 producer->ExpectFlush(nullptr, /*reply=*/false); // Do NOT reply to flush 2.
2544 producer->ExpectFlush(writer.get()); // Reply only to flush 3.
2545 producer->ExpectFlush(nullptr, /*reply=*/false); // Do NOT reply to flush 4.
2546
2547 // Even if the producer explicily replied only to flush ID == 3, all the
2548 // previous flushed < 3 should be implicitly acked.
2549 ASSERT_TRUE(flush_req_1.WaitForReply());
2550 ASSERT_TRUE(flush_req_2.WaitForReply());
2551 ASSERT_TRUE(flush_req_3.WaitForReply());
2552
2553 // At this point flush id == 4 should still be pending and should fail because
2554 // of reaching its timeout.
2555 ASSERT_FALSE(flush_req_4.WaitForReply());
2556
2557 consumer->DisableTracing();
2558 producer->WaitForDataSourceStop("data_source");
2559 consumer->WaitForTracingDisabled();
2560 EXPECT_THAT(consumer->ReadBuffers(),
2561 Contains(Property(
2562 &protos::gen::TracePacket::for_testing,
2563 Property(&protos::gen::TestEvent::str, Eq("payload")))));
2564 }
2565
TEST_F(TracingServiceImplTest,PeriodicFlush)2566 TEST_F(TracingServiceImplTest, PeriodicFlush) {
2567 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2568 consumer->Connect(svc.get());
2569
2570 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2571 producer->Connect(svc.get(), "mock_producer");
2572 producer->RegisterDataSource("data_source");
2573
2574 TraceConfig trace_config;
2575 trace_config.add_buffers()->set_size_kb(128);
2576 trace_config.set_flush_period_ms(1);
2577 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2578 ds_config->set_name("data_source");
2579
2580 consumer->EnableTracing(trace_config);
2581 producer->WaitForTracingSetup();
2582 producer->WaitForDataSourceSetup("data_source");
2583 producer->WaitForDataSourceStart("data_source");
2584
2585 std::unique_ptr<TraceWriter> writer =
2586 producer->CreateTraceWriter("data_source");
2587
2588 const int kNumFlushes = 3;
2589 auto checkpoint = task_runner.CreateCheckpoint("all_flushes_done");
2590 int flushes_seen = 0;
2591 FlushFlags flush_flags(FlushFlags::Initiator::kTraced,
2592 FlushFlags::Reason::kPeriodic);
2593 EXPECT_CALL(*producer, Flush(_, _, _, flush_flags))
2594 .WillRepeatedly(Invoke([&producer, &writer, &flushes_seen, checkpoint](
2595 FlushRequestID flush_req_id,
2596 const DataSourceInstanceID*, size_t,
2597 FlushFlags) {
2598 {
2599 auto tp = writer->NewTracePacket();
2600 char payload[32];
2601 base::SprintfTrunc(payload, sizeof(payload), "f_%d", flushes_seen);
2602 tp->set_for_testing()->set_str(payload);
2603 }
2604 writer->Flush();
2605 producer->endpoint()->NotifyFlushComplete(flush_req_id);
2606 if (++flushes_seen == kNumFlushes)
2607 checkpoint();
2608 }));
2609 task_runner.RunUntilCheckpoint("all_flushes_done");
2610
2611 consumer->DisableTracing();
2612 producer->WaitForDataSourceStop("data_source");
2613 consumer->WaitForTracingDisabled();
2614 auto trace_packets = consumer->ReadBuffers();
2615 for (int i = 0; i < kNumFlushes; i++) {
2616 EXPECT_THAT(trace_packets,
2617 Contains(Property(&protos::gen::TracePacket::for_testing,
2618 Property(&protos::gen::TestEvent::str,
2619 Eq("f_" + std::to_string(i))))));
2620 }
2621 }
2622
TEST_F(TracingServiceImplTest,NoFlush)2623 TEST_F(TracingServiceImplTest, NoFlush) {
2624 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2625 consumer->Connect(svc.get());
2626
2627 std::unique_ptr<MockProducer> producer_1 = CreateMockProducer();
2628 producer_1->Connect(svc.get(), "mock_producer_1");
2629 producer_1->RegisterDataSource("ds_flush");
2630 producer_1->RegisterDataSource("ds_noflush", false, false, false, true);
2631
2632 TraceConfig trace_config;
2633 trace_config.add_buffers()->set_size_kb(128);
2634 trace_config.add_data_sources()->mutable_config()->set_name("ds_flush");
2635 trace_config.add_data_sources()->mutable_config()->set_name("ds_noflush");
2636
2637 consumer->EnableTracing(trace_config);
2638 producer_1->WaitForTracingSetup();
2639 producer_1->WaitForDataSourceSetup("ds_flush");
2640 producer_1->WaitForDataSourceSetup("ds_noflush");
2641 producer_1->WaitForDataSourceStart("ds_flush");
2642 producer_1->WaitForDataSourceStart("ds_noflush");
2643
2644 std::unique_ptr<MockProducer> producer_2 = CreateMockProducer();
2645 producer_2->Connect(svc.get(), "mock_producer_2");
2646 producer_2->RegisterDataSource("ds_noflush", false, false, false,
2647 /*no_flush=*/true);
2648 producer_2->WaitForTracingSetup();
2649 producer_2->WaitForDataSourceSetup("ds_noflush");
2650 producer_2->WaitForDataSourceStart("ds_noflush");
2651
2652 auto wr_p1_ds1 = producer_1->CreateTraceWriter("ds_flush");
2653 producer_1->ExpectFlush(wr_p1_ds1.get());
2654
2655 EXPECT_CALL(*producer_2, Flush(_, _, _, _)).Times(0);
2656
2657 auto flush_request = consumer->Flush();
2658 ASSERT_TRUE(flush_request.WaitForReply());
2659
2660 consumer->DisableTracing();
2661 }
2662
TEST_F(TracingServiceImplTest,PeriodicClearIncrementalState)2663 TEST_F(TracingServiceImplTest, PeriodicClearIncrementalState) {
2664 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2665 consumer->Connect(svc.get());
2666 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2667 producer->Connect(svc.get(), "mock_producer");
2668
2669 // Incremental data source that expects to receive the clear.
2670 producer->RegisterDataSource("ds_incremental1", false, false,
2671 /*handles_incremental_state_clear=*/true);
2672
2673 // Incremental data source that expects to receive the clear.
2674 producer->RegisterDataSource("ds_incremental2", false, false,
2675 /*handles_incremental_state_clear=*/true);
2676
2677 // Data source that does *not* advertise itself as supporting incremental
2678 // state clears.
2679 producer->RegisterDataSource("ds_selfcontained", false, false,
2680 /*handles_incremental_state_clear=*/false);
2681
2682 // Incremental data source that is registered, but won't be active within the
2683 // test's tracing session.
2684 producer->RegisterDataSource("ds_inactive", false, false,
2685 /*handles_incremental_state_clear=*/true);
2686
2687 TraceConfig trace_config;
2688 trace_config.add_buffers()->set_size_kb(128);
2689 trace_config.mutable_incremental_state_config()->set_clear_period_ms(1);
2690 trace_config.add_data_sources()->mutable_config()->set_name(
2691 "ds_selfcontained");
2692 trace_config.add_data_sources()->mutable_config()->set_name(
2693 "ds_incremental1");
2694 trace_config.add_data_sources()->mutable_config()->set_name(
2695 "ds_incremental2");
2696
2697 // note: the mocking is very brittle, and has to assume a specific order of
2698 // the data sources' setup/start.
2699 consumer->EnableTracing(trace_config);
2700 producer->WaitForTracingSetup();
2701 producer->WaitForDataSourceSetup("ds_selfcontained");
2702 producer->WaitForDataSourceSetup("ds_incremental1");
2703 producer->WaitForDataSourceSetup("ds_incremental2");
2704 producer->WaitForDataSourceStart("ds_selfcontained");
2705 producer->WaitForDataSourceStart("ds_incremental1");
2706 producer->WaitForDataSourceStart("ds_incremental2");
2707
2708 DataSourceInstanceID ds_incremental1 =
2709 producer->GetDataSourceInstanceId("ds_incremental1");
2710 DataSourceInstanceID ds_incremental2 =
2711 producer->GetDataSourceInstanceId("ds_incremental2");
2712
2713 const size_t kNumClears = 3;
2714 std::function<void()> checkpoint =
2715 task_runner.CreateCheckpoint("clears_received");
2716 std::vector<std::vector<DataSourceInstanceID>> clears_seen;
2717 EXPECT_CALL(*producer, ClearIncrementalState(_, _))
2718 .WillRepeatedly(Invoke([&clears_seen, &checkpoint](
2719 const DataSourceInstanceID* data_source_ids,
2720 size_t num_data_sources) {
2721 std::vector<DataSourceInstanceID> ds_ids;
2722 for (size_t i = 0; i < num_data_sources; i++) {
2723 ds_ids.push_back(*data_source_ids++);
2724 }
2725 clears_seen.push_back(ds_ids);
2726 if (clears_seen.size() >= kNumClears)
2727 checkpoint();
2728 }));
2729 task_runner.RunUntilCheckpoint("clears_received");
2730
2731 consumer->DisableTracing();
2732
2733 // Assert that the clears were only for the active incremental data sources.
2734 ASSERT_EQ(clears_seen.size(), kNumClears);
2735 for (const std::vector<DataSourceInstanceID>& ds_ids : clears_seen) {
2736 ASSERT_THAT(ds_ids, ElementsAreArray({ds_incremental1, ds_incremental2}));
2737 }
2738 }
2739
2740 // Creates a tracing session where some of the data sources set the
2741 // |will_notify_on_stop| flag and checks that the OnTracingDisabled notification
2742 // to the consumer is delayed until the acks are received.
TEST_F(TracingServiceImplTest,OnTracingDisabledWaitsForDataSourceStopAcks)2743 TEST_F(TracingServiceImplTest, OnTracingDisabledWaitsForDataSourceStopAcks) {
2744 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2745 consumer->Connect(svc.get());
2746
2747 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2748 producer->Connect(svc.get(), "mock_producer");
2749 producer->RegisterDataSource("ds_will_ack_1", /*ack_stop=*/true,
2750 /*ack_start=*/true);
2751 producer->RegisterDataSource("ds_wont_ack");
2752 producer->RegisterDataSource("ds_will_ack_2", /*ack_stop=*/true,
2753 /*ack_start=*/false);
2754
2755 TraceConfig trace_config;
2756 trace_config.add_buffers()->set_size_kb(128);
2757 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_1");
2758 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
2759 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack_2");
2760 trace_config.set_duration_ms(1);
2761 trace_config.set_deferred_start(true);
2762
2763 consumer->EnableTracing(trace_config);
2764
2765 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_1"),
2766 DataSourceInstanceState::CONFIGURED);
2767 EXPECT_EQ(GetDataSourceInstanceState("ds_wont_ack"),
2768 DataSourceInstanceState::CONFIGURED);
2769 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_2"),
2770 DataSourceInstanceState::CONFIGURED);
2771
2772 producer->WaitForTracingSetup();
2773
2774 producer->WaitForDataSourceSetup("ds_will_ack_1");
2775 producer->WaitForDataSourceSetup("ds_wont_ack");
2776 producer->WaitForDataSourceSetup("ds_will_ack_2");
2777
2778 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_will_ack_1");
2779 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds_will_ack_2");
2780
2781 consumer->StartTracing();
2782
2783 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_1"),
2784 DataSourceInstanceState::STARTING);
2785 EXPECT_EQ(GetDataSourceInstanceState("ds_wont_ack"),
2786 DataSourceInstanceState::STARTED);
2787 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_2"),
2788 DataSourceInstanceState::STARTED);
2789
2790 producer->WaitForDataSourceStart("ds_will_ack_1");
2791 producer->WaitForDataSourceStart("ds_wont_ack");
2792 producer->WaitForDataSourceStart("ds_will_ack_2");
2793
2794 producer->endpoint()->NotifyDataSourceStarted(id1);
2795
2796 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_1"),
2797 DataSourceInstanceState::STARTED);
2798
2799 std::unique_ptr<TraceWriter> writer =
2800 producer->CreateTraceWriter("ds_wont_ack");
2801 producer->ExpectFlush(writer.get());
2802
2803 producer->WaitForDataSourceStop("ds_will_ack_1");
2804 producer->WaitForDataSourceStop("ds_wont_ack");
2805 producer->WaitForDataSourceStop("ds_will_ack_2");
2806
2807 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_1"),
2808 DataSourceInstanceState::STOPPING);
2809 EXPECT_EQ(GetDataSourceInstanceState("ds_wont_ack"),
2810 DataSourceInstanceState::STOPPED);
2811 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_2"),
2812 DataSourceInstanceState::STOPPING);
2813
2814 producer->endpoint()->NotifyDataSourceStopped(id1);
2815 producer->endpoint()->NotifyDataSourceStopped(id2);
2816
2817 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_1"),
2818 DataSourceInstanceState::STOPPED);
2819 EXPECT_EQ(GetDataSourceInstanceState("ds_will_ack_2"),
2820 DataSourceInstanceState::STOPPED);
2821
2822 // Wait for at most half of the service timeout, so that this test fails if
2823 // the service falls back on calling the OnTracingDisabled() because some of
2824 // the expected acks weren't received.
2825 consumer->WaitForTracingDisabled(
2826 TracingServiceImpl::kDataSourceStopTimeoutMs / 2);
2827 }
2828
2829 // Creates a tracing session where a second data source
2830 // is added while the service is waiting for DisableTracing
2831 // acks; the service should not enable the new datasource
2832 // and should not hit any asserts when the consumer is
2833 // subsequently destroyed.
TEST_F(TracingServiceImplTest,OnDataSourceAddedWhilePendingDisableAcks)2834 TEST_F(TracingServiceImplTest, OnDataSourceAddedWhilePendingDisableAcks) {
2835 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2836 consumer->Connect(svc.get());
2837
2838 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2839 producer->Connect(svc.get(), "mock_producer");
2840 producer->RegisterDataSource("ds_will_ack", /*ack_stop=*/true);
2841
2842 TraceConfig trace_config;
2843 trace_config.add_buffers()->set_size_kb(128);
2844 trace_config.add_data_sources()->mutable_config()->set_name("ds_will_ack");
2845 trace_config.add_data_sources()->mutable_config()->set_name("ds_wont_ack");
2846
2847 consumer->EnableTracing(trace_config);
2848 producer->WaitForTracingSetup();
2849
2850 consumer->DisableTracing();
2851
2852 producer->RegisterDataSource("ds_wont_ack");
2853
2854 consumer.reset();
2855 }
2856
2857 // Similar to OnTracingDisabledWaitsForDataSourceStopAcks, but deliberately
2858 // skips the ack and checks that the service invokes the OnTracingDisabled()
2859 // after the timeout.
TEST_F(TracingServiceImplTest,OnTracingDisabledCalledAnywaysInCaseOfTimeout)2860 TEST_F(TracingServiceImplTest, OnTracingDisabledCalledAnywaysInCaseOfTimeout) {
2861 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2862 consumer->Connect(svc.get());
2863
2864 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2865 producer->Connect(svc.get(), "mock_producer");
2866 producer->RegisterDataSource("data_source", /*ack_stop=*/true);
2867
2868 TraceConfig trace_config;
2869 trace_config.add_buffers()->set_size_kb(128);
2870 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
2871 trace_config.set_duration_ms(1);
2872 trace_config.set_data_source_stop_timeout_ms(1);
2873
2874 consumer->EnableTracing(trace_config);
2875 producer->WaitForTracingSetup();
2876 producer->WaitForDataSourceSetup("data_source");
2877 producer->WaitForDataSourceStart("data_source");
2878
2879 std::unique_ptr<TraceWriter> writer =
2880 producer->CreateTraceWriter("data_source");
2881 producer->ExpectFlush(writer.get());
2882
2883 producer->WaitForDataSourceStop("data_source");
2884 consumer->WaitForTracingDisabled();
2885 }
2886
2887 // Tests the session_id logic. Two data sources in the same tracing session
2888 // should see the same session id.
TEST_F(TracingServiceImplTest,SessionId)2889 TEST_F(TracingServiceImplTest, SessionId) {
2890 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2891 consumer->Connect(svc.get());
2892
2893 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
2894 producer1->Connect(svc.get(), "mock_producer1");
2895 producer1->RegisterDataSource("ds_1A");
2896 producer1->RegisterDataSource("ds_1B");
2897
2898 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
2899 producer2->Connect(svc.get(), "mock_producer2");
2900 producer2->RegisterDataSource("ds_2A");
2901
2902 InSequence seq;
2903 TracingSessionID last_session_id = 0;
2904 for (int i = 0; i < 3; i++) {
2905 TraceConfig trace_config;
2906 trace_config.add_buffers()->set_size_kb(128);
2907 trace_config.add_data_sources()->mutable_config()->set_name("ds_1A");
2908 trace_config.add_data_sources()->mutable_config()->set_name("ds_1B");
2909 trace_config.add_data_sources()->mutable_config()->set_name("ds_2A");
2910 trace_config.set_duration_ms(1);
2911
2912 consumer->EnableTracing(trace_config);
2913
2914 if (i == 0)
2915 producer1->WaitForTracingSetup();
2916
2917 producer1->WaitForDataSourceSetup("ds_1A");
2918 producer1->WaitForDataSourceSetup("ds_1B");
2919 if (i == 0)
2920 producer2->WaitForTracingSetup();
2921 producer2->WaitForDataSourceSetup("ds_2A");
2922
2923 producer1->WaitForDataSourceStart("ds_1A");
2924 producer1->WaitForDataSourceStart("ds_1B");
2925 producer2->WaitForDataSourceStart("ds_2A");
2926
2927 auto* ds1 = producer1->GetDataSourceInstance("ds_1A");
2928 auto* ds2 = producer1->GetDataSourceInstance("ds_1B");
2929 auto* ds3 = producer2->GetDataSourceInstance("ds_2A");
2930 ASSERT_EQ(ds1->session_id, ds2->session_id);
2931 ASSERT_EQ(ds1->session_id, ds3->session_id);
2932 ASSERT_NE(ds1->session_id, last_session_id);
2933 last_session_id = ds1->session_id;
2934
2935 auto writer1 = producer1->CreateTraceWriter("ds_1A");
2936 producer1->ExpectFlush(writer1.get());
2937
2938 auto writer2 = producer2->CreateTraceWriter("ds_2A");
2939 producer2->ExpectFlush(writer2.get());
2940
2941 producer1->WaitForDataSourceStop("ds_1A");
2942 producer1->WaitForDataSourceStop("ds_1B");
2943 producer2->WaitForDataSourceStop("ds_2A");
2944 consumer->WaitForTracingDisabled();
2945 consumer->FreeBuffers();
2946 }
2947 }
2948
2949 // Writes a long trace and then tests that the trace parsed in partitions
2950 // derived by the synchronization markers is identical to the whole trace parsed
2951 // in one go.
TEST_F(TracingServiceImplTest,ResynchronizeTraceStreamUsingSyncMarker)2952 TEST_F(TracingServiceImplTest, ResynchronizeTraceStreamUsingSyncMarker) {
2953 // Setup tracing.
2954 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
2955 consumer->Connect(svc.get());
2956 std::unique_ptr<MockProducer> producer = CreateMockProducer();
2957 producer->Connect(svc.get(), "mock_producer");
2958 producer->RegisterDataSource("data_source");
2959 TraceConfig trace_config;
2960 trace_config.add_buffers()->set_size_kb(4096);
2961 auto* ds_config = trace_config.add_data_sources()->mutable_config();
2962 ds_config->set_name("data_source");
2963 trace_config.set_write_into_file(true);
2964 trace_config.set_file_write_period_ms(1);
2965 base::TempFile tmp_file = base::TempFile::Create();
2966 consumer->EnableTracing(trace_config, base::ScopedFile(dup(tmp_file.fd())));
2967 producer->WaitForTracingSetup();
2968 producer->WaitForDataSourceSetup("data_source");
2969 producer->WaitForDataSourceStart("data_source");
2970
2971 // Write some variable length payload, waiting for sync markers every now
2972 // and then.
2973 const int kNumMarkers = 5;
2974 auto writer = producer->CreateTraceWriter("data_source");
2975 for (int i = 1; i <= 100; i++) {
2976 std::string payload(static_cast<size_t>(i),
2977 'A' + static_cast<char>(i % 25));
2978 writer->NewTracePacket()->set_for_testing()->set_str(payload.c_str());
2979 if (i % (100 / kNumMarkers) == 0) {
2980 writer->Flush();
2981 WaitForNextSyncMarker();
2982 }
2983 }
2984 writer->Flush();
2985 writer.reset();
2986 consumer->DisableTracing();
2987 producer->WaitForDataSourceStop("data_source");
2988 consumer->WaitForTracingDisabled();
2989
2990 std::string trace_raw;
2991 ASSERT_TRUE(base::ReadFile(tmp_file.path().c_str(), &trace_raw));
2992
2993 const auto kMarkerSize = sizeof(TracingServiceImpl::kSyncMarker);
2994 const std::string kSyncMarkerStr(
2995 reinterpret_cast<const char*>(TracingServiceImpl::kSyncMarker),
2996 kMarkerSize);
2997
2998 // Read back the trace in partitions derived from the marker.
2999 // The trace should look like this:
3000 // [uid, marker] [event] [event] [uid, marker] [event] [event]
3001 size_t num_markers = 0;
3002 size_t start = 0;
3003 size_t end = 0;
3004 std::string merged_trace_raw;
3005 for (size_t pos = 0; pos != std::string::npos; start = end) {
3006 pos = trace_raw.find(kSyncMarkerStr, pos + 1);
3007 num_markers++;
3008 end = (pos == std::string::npos) ? trace_raw.size() : pos + kMarkerSize;
3009 size_t size = end - start;
3010 ASSERT_GT(size, 0u);
3011 std::string trace_partition_raw = trace_raw.substr(start, size);
3012 protos::gen::Trace trace_partition;
3013 ASSERT_TRUE(trace_partition.ParseFromString(trace_partition_raw));
3014 merged_trace_raw += trace_partition_raw;
3015 }
3016 EXPECT_GE(num_markers, static_cast<size_t>(kNumMarkers));
3017
3018 protos::gen::Trace whole_trace;
3019 ASSERT_TRUE(whole_trace.ParseFromString(trace_raw));
3020
3021 protos::gen::Trace merged_trace;
3022 merged_trace.ParseFromString(merged_trace_raw);
3023
3024 ASSERT_EQ(whole_trace.packet_size(), merged_trace.packet_size());
3025 EXPECT_EQ(whole_trace.SerializeAsString(), merged_trace.SerializeAsString());
3026 }
3027
3028 // Creates a tracing session with |deferred_start| and checks that data sources
3029 // are started only after calling StartTracing().
TEST_F(TracingServiceImplTest,DeferredStart)3030 TEST_F(TracingServiceImplTest, DeferredStart) {
3031 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3032 consumer->Connect(svc.get());
3033
3034 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3035 producer->Connect(svc.get(), "mock_producer");
3036
3037 // Create two data sources but enable only one of them.
3038 producer->RegisterDataSource("ds_1");
3039 producer->RegisterDataSource("ds_2");
3040
3041 TraceConfig trace_config;
3042 trace_config.add_buffers()->set_size_kb(128);
3043 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
3044 trace_config.set_deferred_start(true);
3045 trace_config.set_duration_ms(1);
3046
3047 consumer->EnableTracing(trace_config);
3048 producer->WaitForTracingSetup();
3049
3050 producer->WaitForDataSourceSetup("ds_1");
3051
3052 // Make sure we don't get unexpected DataSourceStart() notifications yet.
3053 task_runner.RunUntilIdle();
3054
3055 consumer->StartTracing();
3056
3057 producer->WaitForDataSourceStart("ds_1");
3058
3059 auto writer = producer->CreateTraceWriter("ds_1");
3060 producer->ExpectFlush(writer.get());
3061
3062 producer->WaitForDataSourceStop("ds_1");
3063 consumer->WaitForTracingDisabled();
3064 }
3065
TEST_F(TracingServiceImplTest,ProducerUIDsAndPacketSequenceIDs)3066 TEST_F(TracingServiceImplTest, ProducerUIDsAndPacketSequenceIDs) {
3067 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3068 consumer->Connect(svc.get());
3069
3070 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
3071 producer1->Connect(svc.get(), "mock_producer1", 123u /* uid */,
3072 1001 /* pid */);
3073 producer1->RegisterDataSource("data_source");
3074
3075 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
3076 producer2->Connect(svc.get(), "mock_producer2", 456u /* uid */,
3077 2002 /* pid */);
3078 producer2->RegisterDataSource("data_source");
3079
3080 TraceConfig trace_config;
3081 trace_config.add_buffers()->set_size_kb(128);
3082 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3083 ds_config->set_name("data_source");
3084
3085 consumer->EnableTracing(trace_config);
3086 producer1->WaitForTracingSetup();
3087 producer1->WaitForDataSourceSetup("data_source");
3088 producer2->WaitForTracingSetup();
3089 producer2->WaitForDataSourceSetup("data_source");
3090 producer1->WaitForDataSourceStart("data_source");
3091 producer2->WaitForDataSourceStart("data_source");
3092
3093 std::unique_ptr<TraceWriter> writer1a =
3094 producer1->CreateTraceWriter("data_source");
3095 std::unique_ptr<TraceWriter> writer1b =
3096 producer1->CreateTraceWriter("data_source");
3097 std::unique_ptr<TraceWriter> writer2a =
3098 producer2->CreateTraceWriter("data_source");
3099 {
3100 auto tp = writer1a->NewTracePacket();
3101 tp->set_for_testing()->set_str("payload1a1");
3102 tp = writer1b->NewTracePacket();
3103 tp->set_for_testing()->set_str("payload1b1");
3104 tp = writer1a->NewTracePacket();
3105 tp->set_for_testing()->set_str("payload1a2");
3106 tp = writer2a->NewTracePacket();
3107 tp->set_for_testing()->set_str("payload2a1");
3108 tp = writer1b->NewTracePacket();
3109 tp->set_for_testing()->set_str("payload1b2");
3110 }
3111
3112 auto flush_request = consumer->Flush();
3113 producer1->ExpectFlush({writer1a.get(), writer1b.get()});
3114 producer2->ExpectFlush(writer2a.get());
3115 ASSERT_TRUE(flush_request.WaitForReply());
3116
3117 consumer->DisableTracing();
3118 producer1->WaitForDataSourceStop("data_source");
3119 producer2->WaitForDataSourceStop("data_source");
3120 consumer->WaitForTracingDisabled();
3121 auto packets = consumer->ReadBuffers();
3122 EXPECT_THAT(
3123 packets,
3124 Contains(AllOf(
3125 Property(&protos::gen::TracePacket::for_testing,
3126 Property(&protos::gen::TestEvent::str, Eq("payload1a1"))),
3127 Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
3128 Property(&protos::gen::TracePacket::trusted_pid, Eq(1001)),
3129 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
3130 Eq(2u)))));
3131 EXPECT_THAT(
3132 packets,
3133 Contains(AllOf(
3134 Property(&protos::gen::TracePacket::for_testing,
3135 Property(&protos::gen::TestEvent::str, Eq("payload1a2"))),
3136 Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
3137 Property(&protos::gen::TracePacket::trusted_pid, Eq(1001)),
3138 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
3139 Eq(2u)))));
3140 EXPECT_THAT(
3141 packets,
3142 Contains(AllOf(
3143 Property(&protos::gen::TracePacket::for_testing,
3144 Property(&protos::gen::TestEvent::str, Eq("payload1b1"))),
3145 Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
3146 Property(&protos::gen::TracePacket::trusted_pid, Eq(1001)),
3147 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
3148 Eq(3u)))));
3149 EXPECT_THAT(
3150 packets,
3151 Contains(AllOf(
3152 Property(&protos::gen::TracePacket::for_testing,
3153 Property(&protos::gen::TestEvent::str, Eq("payload1b2"))),
3154 Property(&protos::gen::TracePacket::trusted_uid, Eq(123)),
3155 Property(&protos::gen::TracePacket::trusted_pid, Eq(1001)),
3156 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
3157 Eq(3u)))));
3158 EXPECT_THAT(
3159 packets,
3160 Contains(AllOf(
3161 Property(&protos::gen::TracePacket::for_testing,
3162 Property(&protos::gen::TestEvent::str, Eq("payload2a1"))),
3163 Property(&protos::gen::TracePacket::trusted_uid, Eq(456)),
3164 Property(&protos::gen::TracePacket::trusted_pid, Eq(2002)),
3165 Property(&protos::gen::TracePacket::trusted_packet_sequence_id,
3166 Eq(4u)))));
3167 }
3168
TEST_F(TracingServiceImplTest,AllowedBuffers)3169 TEST_F(TracingServiceImplTest, AllowedBuffers) {
3170 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3171 consumer->Connect(svc.get());
3172
3173 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
3174 producer1->Connect(svc.get(), "mock_producer1");
3175 ProducerID producer1_id = *last_producer_id();
3176 producer1->RegisterDataSource("data_source1");
3177 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
3178 producer2->Connect(svc.get(), "mock_producer2");
3179 ProducerID producer2_id = *last_producer_id();
3180 producer2->RegisterDataSource("data_source2.1");
3181 producer2->RegisterDataSource("data_source2.2");
3182 producer2->RegisterDataSource("data_source2.3");
3183
3184 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
3185 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
3186
3187 TraceConfig trace_config;
3188 trace_config.add_buffers()->set_size_kb(128);
3189 trace_config.add_buffers()->set_size_kb(128);
3190 trace_config.add_buffers()->set_size_kb(128);
3191 auto* ds_config1 = trace_config.add_data_sources()->mutable_config();
3192 ds_config1->set_name("data_source1");
3193 ds_config1->set_target_buffer(0);
3194 auto* ds_config21 = trace_config.add_data_sources()->mutable_config();
3195 ds_config21->set_name("data_source2.1");
3196 ds_config21->set_target_buffer(1);
3197 auto* ds_config22 = trace_config.add_data_sources()->mutable_config();
3198 ds_config22->set_name("data_source2.2");
3199 ds_config22->set_target_buffer(2);
3200 auto* ds_config23 = trace_config.add_data_sources()->mutable_config();
3201 ds_config23->set_name("data_source2.3");
3202 ds_config23->set_target_buffer(2); // same buffer as data_source2.2.
3203 consumer->EnableTracing(trace_config);
3204
3205 ASSERT_EQ(3u, tracing_session()->num_buffers());
3206 std::set<BufferID> expected_buffers_producer1 = {
3207 tracing_session()->buffers_index[0]};
3208 std::set<BufferID> expected_buffers_producer2 = {
3209 tracing_session()->buffers_index[1], tracing_session()->buffers_index[2]};
3210 EXPECT_EQ(expected_buffers_producer1, GetAllowedTargetBuffers(producer1_id));
3211 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
3212
3213 producer1->WaitForTracingSetup();
3214 producer1->WaitForDataSourceSetup("data_source1");
3215
3216 producer2->WaitForTracingSetup();
3217 producer2->WaitForDataSourceSetup("data_source2.1");
3218 producer2->WaitForDataSourceSetup("data_source2.2");
3219 producer2->WaitForDataSourceSetup("data_source2.3");
3220
3221 producer1->WaitForDataSourceStart("data_source1");
3222 producer2->WaitForDataSourceStart("data_source2.1");
3223 producer2->WaitForDataSourceStart("data_source2.2");
3224 producer2->WaitForDataSourceStart("data_source2.3");
3225
3226 producer2->UnregisterDataSource("data_source2.3");
3227 producer2->WaitForDataSourceStop("data_source2.3");
3228
3229 // Should still be allowed to write to buffers 1 (data_source2.1) and 2
3230 // (data_source2.2).
3231 EXPECT_EQ(expected_buffers_producer2, GetAllowedTargetBuffers(producer2_id));
3232
3233 // Calling StartTracing() should be a noop (% a DLOG statement) because the
3234 // trace config didn't have the |deferred_start| flag set.
3235 consumer->StartTracing();
3236
3237 consumer->DisableTracing();
3238 producer1->WaitForDataSourceStop("data_source1");
3239 producer2->WaitForDataSourceStop("data_source2.1");
3240 producer2->WaitForDataSourceStop("data_source2.2");
3241 consumer->WaitForTracingDisabled();
3242
3243 consumer->FreeBuffers();
3244 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer1_id));
3245 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer2_id));
3246 }
3247
3248 #if !PERFETTO_DCHECK_IS_ON()
TEST_F(TracingServiceImplTest,CommitToForbiddenBufferIsDiscarded)3249 TEST_F(TracingServiceImplTest, CommitToForbiddenBufferIsDiscarded) {
3250 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3251 consumer->Connect(svc.get());
3252
3253 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3254 producer->Connect(svc.get(), "mock_producer");
3255 ProducerID producer_id = *last_producer_id();
3256 producer->RegisterDataSource("data_source");
3257
3258 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
3259
3260 TraceConfig trace_config;
3261 trace_config.add_buffers()->set_size_kb(128);
3262 trace_config.add_buffers()->set_size_kb(128);
3263 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3264 ds_config->set_name("data_source");
3265 ds_config->set_target_buffer(0);
3266 consumer->EnableTracing(trace_config);
3267
3268 ASSERT_EQ(2u, tracing_session()->num_buffers());
3269 std::set<BufferID> expected_buffers = {tracing_session()->buffers_index[0]};
3270 EXPECT_EQ(expected_buffers, GetAllowedTargetBuffers(producer_id));
3271
3272 producer->WaitForTracingSetup();
3273 producer->WaitForDataSourceSetup("data_source");
3274 producer->WaitForDataSourceStart("data_source");
3275
3276 // Calling StartTracing() should be a noop (% a DLOG statement) because the
3277 // trace config didn't have the |deferred_start| flag set.
3278 consumer->StartTracing();
3279
3280 // Try to write to the correct buffer.
3281 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
3282 tracing_session()->buffers_index[0]);
3283 {
3284 auto tp = writer->NewTracePacket();
3285 tp->set_for_testing()->set_str("good_payload");
3286 }
3287
3288 auto flush_request = consumer->Flush();
3289 producer->ExpectFlush(writer.get());
3290 ASSERT_TRUE(flush_request.WaitForReply());
3291
3292 // Try to write to the wrong buffer.
3293 writer = producer->endpoint()->CreateTraceWriter(
3294 tracing_session()->buffers_index[1]);
3295 {
3296 auto tp = writer->NewTracePacket();
3297 tp->set_for_testing()->set_str("bad_payload");
3298 }
3299
3300 flush_request = consumer->Flush();
3301 producer->ExpectFlush(writer.get());
3302 ASSERT_TRUE(flush_request.WaitForReply());
3303
3304 consumer->DisableTracing();
3305 producer->WaitForDataSourceStop("data_source");
3306 consumer->WaitForTracingDisabled();
3307
3308 auto packets = consumer->ReadBuffers();
3309 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3310 Property(&protos::gen::TestEvent::str,
3311 Eq("good_payload")))));
3312 EXPECT_THAT(packets,
3313 Not(Contains(Property(
3314 &protos::gen::TracePacket::for_testing,
3315 Property(&protos::gen::TestEvent::str, Eq("bad_payload"))))));
3316
3317 consumer->FreeBuffers();
3318 EXPECT_EQ(std::set<BufferID>(), GetAllowedTargetBuffers(producer_id));
3319 }
3320 #endif // !PERFETTO_DCHECK_IS_ON()
3321
TEST_F(TracingServiceImplTest,RegisterAndUnregisterTraceWriter)3322 TEST_F(TracingServiceImplTest, RegisterAndUnregisterTraceWriter) {
3323 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3324 consumer->Connect(svc.get());
3325
3326 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3327 producer->Connect(svc.get(), "mock_producer");
3328 ProducerID producer_id = *last_producer_id();
3329 producer->RegisterDataSource("data_source");
3330
3331 EXPECT_TRUE(GetWriters(producer_id).empty());
3332
3333 TraceConfig trace_config;
3334 trace_config.add_buffers()->set_size_kb(128);
3335 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3336 ds_config->set_name("data_source");
3337 ds_config->set_target_buffer(0);
3338 consumer->EnableTracing(trace_config);
3339
3340 producer->WaitForTracingSetup();
3341 producer->WaitForDataSourceSetup("data_source");
3342 producer->WaitForDataSourceStart("data_source");
3343
3344 // Calling StartTracing() should be a noop (% a DLOG statement) because the
3345 // trace config didn't have the |deferred_start| flag set.
3346 consumer->StartTracing();
3347
3348 // Creating the trace writer should register it with the service.
3349 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
3350 tracing_session()->buffers_index[0]);
3351
3352 WaitForTraceWritersChanged(producer_id);
3353
3354 std::map<WriterID, BufferID> expected_writers;
3355 expected_writers[writer->writer_id()] = tracing_session()->buffers_index[0];
3356 EXPECT_EQ(expected_writers, GetWriters(producer_id));
3357
3358 // Verify writing works.
3359 {
3360 auto tp = writer->NewTracePacket();
3361 tp->set_for_testing()->set_str("payload");
3362 }
3363
3364 auto flush_request = consumer->Flush();
3365 producer->ExpectFlush(writer.get());
3366 ASSERT_TRUE(flush_request.WaitForReply());
3367
3368 // Destroying the writer should unregister it.
3369 writer.reset();
3370 WaitForTraceWritersChanged(producer_id);
3371 EXPECT_TRUE(GetWriters(producer_id).empty());
3372
3373 consumer->DisableTracing();
3374 producer->WaitForDataSourceStop("data_source");
3375 consumer->WaitForTracingDisabled();
3376
3377 auto packets = consumer->ReadBuffers();
3378 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3379 Property(&protos::gen::TestEvent::str,
3380 Eq("payload")))));
3381 }
3382
TEST_F(TracingServiceImplTest,ScrapeBuffersOnFlush)3383 TEST_F(TracingServiceImplTest, ScrapeBuffersOnFlush) {
3384 svc->SetSMBScrapingEnabled(true);
3385
3386 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3387 consumer->Connect(svc.get());
3388
3389 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3390 producer->Connect(svc.get(), "mock_producer");
3391 ProducerID producer_id = *last_producer_id();
3392 producer->RegisterDataSource("data_source");
3393
3394 TraceConfig trace_config;
3395 trace_config.add_buffers()->set_size_kb(128);
3396 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3397 ds_config->set_name("data_source");
3398 ds_config->set_target_buffer(0);
3399 consumer->EnableTracing(trace_config);
3400
3401 producer->WaitForTracingSetup();
3402 producer->WaitForDataSourceSetup("data_source");
3403 producer->WaitForDataSourceStart("data_source");
3404
3405 // Calling StartTracing() should be a noop (% a DLOG statement) because the
3406 // trace config didn't have the |deferred_start| flag set.
3407 consumer->StartTracing();
3408
3409 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
3410 tracing_session()->buffers_index[0]);
3411 WaitForTraceWritersChanged(producer_id);
3412
3413 // Write a few trace packets.
3414 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
3415 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
3416 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
3417
3418 // Flush but don't actually flush the chunk from TraceWriter.
3419 auto flush_request = consumer->Flush();
3420 producer->ExpectFlush(nullptr, /*reply=*/true);
3421 ASSERT_TRUE(flush_request.WaitForReply());
3422
3423 // Chunk with the packets should have been scraped.
3424 auto packets = consumer->ReadBuffers();
3425 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3426 Property(&protos::gen::TestEvent::str,
3427 Eq("payload1")))));
3428 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3429 Property(&protos::gen::TestEvent::str,
3430 Eq("payload2")))));
3431 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3432 Property(&protos::gen::TestEvent::str,
3433 Eq("payload3")))));
3434
3435 // Write some more packets.
3436 writer->NewTracePacket()->set_for_testing()->set_str("payload4");
3437 writer->NewTracePacket()->set_for_testing()->set_str("payload5");
3438
3439 // Don't reply to flush, causing a timeout. This should scrape again.
3440 flush_request = consumer->Flush(/*timeout=*/100);
3441 producer->ExpectFlush(nullptr, /*reply=*/false);
3442 ASSERT_FALSE(flush_request.WaitForReply());
3443
3444 // Chunk with the packets should have been scraped again, overriding the
3445 // original one. The first three should not be read twice.
3446 packets = consumer->ReadBuffers();
3447 EXPECT_THAT(packets,
3448 Not(Contains(Property(
3449 &protos::gen::TracePacket::for_testing,
3450 Property(&protos::gen::TestEvent::str, Eq("payload1"))))));
3451 EXPECT_THAT(packets,
3452 Not(Contains(Property(
3453 &protos::gen::TracePacket::for_testing,
3454 Property(&protos::gen::TestEvent::str, Eq("payload2"))))));
3455 EXPECT_THAT(packets,
3456 Not(Contains(Property(
3457 &protos::gen::TracePacket::for_testing,
3458 Property(&protos::gen::TestEvent::str, Eq("payload3"))))));
3459 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3460 Property(&protos::gen::TestEvent::str,
3461 Eq("payload4")))));
3462 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3463 Property(&protos::gen::TestEvent::str,
3464 Eq("payload5")))));
3465
3466 consumer->DisableTracing();
3467 producer->WaitForDataSourceStop("data_source");
3468 consumer->WaitForTracingDisabled();
3469 }
3470
TEST_F(TracingServiceImplTest,ScrapeBuffersFromAnotherThread)3471 TEST_F(TracingServiceImplTest, ScrapeBuffersFromAnotherThread) {
3472 // This test verifies that there are no reported TSAN races while scraping
3473 // buffers from a producer which is actively writing more trace data
3474 // concurrently.
3475 svc->SetSMBScrapingEnabled(true);
3476
3477 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3478 consumer->Connect(svc.get());
3479
3480 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3481 producer->Connect(svc.get(), "mock_producer");
3482 ProducerID producer_id = *last_producer_id();
3483 producer->RegisterDataSource("data_source");
3484
3485 TraceConfig trace_config;
3486 trace_config.add_buffers()->set_size_kb(128);
3487 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3488 ds_config->set_name("data_source");
3489 ds_config->set_target_buffer(0);
3490 consumer->EnableTracing(trace_config);
3491
3492 producer->WaitForTracingSetup();
3493 producer->WaitForDataSourceSetup("data_source");
3494 producer->WaitForDataSourceStart("data_source");
3495 consumer->StartTracing();
3496
3497 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
3498 tracing_session()->buffers_index[0]);
3499 WaitForTraceWritersChanged(producer_id);
3500
3501 constexpr int kPacketCount = 10;
3502 std::atomic<int> packets_written{};
3503 std::thread writer_thread([&] {
3504 for (int i = 0; i < kPacketCount; i++) {
3505 writer->NewTracePacket()->set_for_testing()->set_str("payload");
3506 packets_written.store(i, std::memory_order_relaxed);
3507 }
3508 });
3509
3510 // Wait until the thread has had some time to write some packets.
3511 while (packets_written.load(std::memory_order_relaxed) < kPacketCount / 2)
3512 base::SleepMicroseconds(5000);
3513
3514 // Disabling tracing will trigger scraping.
3515 consumer->DisableTracing();
3516 writer_thread.join();
3517
3518 // Because we don't synchronize with the producer thread, we can't make any
3519 // guarantees about the number of packets we will successfully read. We just
3520 // verify that no TSAN races are reported.
3521 consumer->ReadBuffers();
3522
3523 producer->WaitForDataSourceStop("data_source");
3524 consumer->WaitForTracingDisabled();
3525 }
3526
3527 // Test scraping on producer disconnect.
TEST_F(TracingServiceImplTest,ScrapeBuffersOnProducerDisconnect)3528 TEST_F(TracingServiceImplTest, ScrapeBuffersOnProducerDisconnect) {
3529 svc->SetSMBScrapingEnabled(true);
3530
3531 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3532 consumer->Connect(svc.get());
3533
3534 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3535 producer->Connect(svc.get(), "mock_producer");
3536 ProducerID producer_id = *last_producer_id();
3537 producer->RegisterDataSource("data_source");
3538
3539 TraceConfig trace_config;
3540 trace_config.add_buffers()->set_size_kb(128);
3541 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3542 ds_config->set_name("data_source");
3543 ds_config->set_target_buffer(0);
3544 consumer->EnableTracing(trace_config);
3545
3546 producer->WaitForTracingSetup();
3547 producer->WaitForDataSourceSetup("data_source");
3548 producer->WaitForDataSourceStart("data_source");
3549
3550 // Calling StartTracing() should be a noop (% a DLOG statement) because the
3551 // trace config didn't have the |deferred_start| flag set.
3552 consumer->StartTracing();
3553
3554 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
3555 tracing_session()->buffers_index[0]);
3556 WaitForTraceWritersChanged(producer_id);
3557
3558 // Write a few trace packets.
3559 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
3560 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
3561 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
3562
3563 // Disconnect the producer without committing the chunk. This should cause a
3564 // scrape of the SMB. Avoid destroying the ShmemArbiter until writer is
3565 // destroyed.
3566 auto shmem_arbiter = StealShmemArbiterForProducer(producer_id);
3567 producer.reset();
3568
3569 // Chunk with the packets should have been scraped.
3570 auto packets = consumer->ReadBuffers();
3571 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3572 Property(&protos::gen::TestEvent::str,
3573 Eq("payload1")))));
3574 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3575 Property(&protos::gen::TestEvent::str,
3576 Eq("payload2")))));
3577 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3578 Property(&protos::gen::TestEvent::str,
3579 Eq("payload3")))));
3580
3581 // Cleanup writer without causing a crash because the producer already went
3582 // away.
3583 static_cast<TraceWriterImpl*>(writer.get())->ResetChunkForTesting();
3584 writer.reset();
3585 shmem_arbiter.reset();
3586
3587 consumer->DisableTracing();
3588 consumer->WaitForTracingDisabled();
3589 }
3590
TEST_F(TracingServiceImplTest,ScrapeBuffersOnDisable)3591 TEST_F(TracingServiceImplTest, ScrapeBuffersOnDisable) {
3592 svc->SetSMBScrapingEnabled(true);
3593
3594 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3595 consumer->Connect(svc.get());
3596
3597 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3598 producer->Connect(svc.get(), "mock_producer");
3599 ProducerID producer_id = *last_producer_id();
3600 producer->RegisterDataSource("data_source");
3601
3602 TraceConfig trace_config;
3603 trace_config.add_buffers()->set_size_kb(128);
3604 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3605 ds_config->set_name("data_source");
3606 ds_config->set_target_buffer(0);
3607 consumer->EnableTracing(trace_config);
3608
3609 producer->WaitForTracingSetup();
3610 producer->WaitForDataSourceSetup("data_source");
3611 producer->WaitForDataSourceStart("data_source");
3612
3613 // Calling StartTracing() should be a noop (% a DLOG statement) because the
3614 // trace config didn't have the |deferred_start| flag set.
3615 consumer->StartTracing();
3616
3617 std::unique_ptr<TraceWriter> writer = producer->endpoint()->CreateTraceWriter(
3618 tracing_session()->buffers_index[0]);
3619 WaitForTraceWritersChanged(producer_id);
3620
3621 // Write a few trace packets.
3622 writer->NewTracePacket()->set_for_testing()->set_str("payload1");
3623 writer->NewTracePacket()->set_for_testing()->set_str("payload2");
3624 writer->NewTracePacket()->set_for_testing()->set_str("payload3");
3625
3626 consumer->DisableTracing();
3627 producer->WaitForDataSourceStop("data_source");
3628 consumer->WaitForTracingDisabled();
3629
3630 // Chunk with the packets should have been scraped.
3631 auto packets = consumer->ReadBuffers();
3632 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3633 Property(&protos::gen::TestEvent::str,
3634 Eq("payload1")))));
3635 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3636 Property(&protos::gen::TestEvent::str,
3637 Eq("payload2")))));
3638 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
3639 Property(&protos::gen::TestEvent::str,
3640 Eq("payload3")))));
3641 }
3642
3643 // Fixture for testing scraping from a single data source that writes directly
3644 // to the shared memory, to cover all cases.
3645 class TracingServiceImplScrapingWithSmbTest : public TracingServiceImplTest {
3646 public:
SetUp()3647 void SetUp() override {
3648 TracingServiceImplTest::SetUp();
3649 svc->SetSMBScrapingEnabled(true);
3650
3651 consumer_ = CreateMockConsumer();
3652 consumer_->Connect(svc.get());
3653 producer_ = CreateMockProducer();
3654 producer_->Connect(svc.get(), "mock_producer");
3655 ProducerID producer_id = *last_producer_id();
3656 producer_->RegisterDataSource("data_source");
3657
3658 TraceConfig trace_config;
3659 trace_config.add_buffers()->set_size_kb(128);
3660 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3661 ds_config->set_name("data_source");
3662 ds_config->set_target_buffer(0);
3663 consumer_->EnableTracing(trace_config);
3664
3665 producer_->WaitForTracingSetup();
3666 producer_->WaitForDataSourceSetup("data_source");
3667 producer_->WaitForDataSourceStart("data_source");
3668
3669 writer_ = producer_->endpoint()->CreateTraceWriter(
3670 tracing_session()->buffers_index[0]);
3671 WaitForTraceWritersChanged(producer_id);
3672
3673 arbiter_ = GetShmemArbiterForProducer(producer_id);
3674 }
3675
TearDown()3676 void TearDown() override {
3677 TracingServiceImplTest::TearDown();
3678
3679 consumer_->DisableTracing();
3680 producer_->WaitForDataSourceStop("data_source");
3681 consumer_->WaitForTracingDisabled();
3682 }
3683
3684 protected:
FlushAndRead()3685 std::optional<std::vector<protos::gen::TracePacket>> FlushAndRead() {
3686 // Scrape: ask the service to flush but don't flush the chunk.
3687 auto flush_request = consumer_->Flush();
3688 producer_->ExpectFlush(nullptr, /*reply=*/true);
3689 if (flush_request.WaitForReply()) {
3690 return consumer_->ReadBuffers();
3691 }
3692 return std::nullopt;
3693 }
3694 std::unique_ptr<MockConsumer> consumer_;
3695 std::unique_ptr<MockProducer> producer_;
3696 std::unique_ptr<TraceWriter> writer_;
3697 // Owned by `svc`.
3698 SharedMemoryArbiterImpl* arbiter_;
3699
3700 struct : public protozero::ScatteredStreamWriter::Delegate {
GetNewBufferperfetto::TracingServiceImplScrapingWithSmbTest::__anon204cd52710083701 protozero::ContiguousMemoryRange GetNewBuffer() override {
3702 PERFETTO_FATAL("Unreachable");
3703 }
3704
AnnotatePatchperfetto::TracingServiceImplScrapingWithSmbTest::__anon204cd52710083705 uint8_t* AnnotatePatch(uint8_t*) override { PERFETTO_FATAL("Unreachable"); }
3706 } empty_delegate_;
3707 PatchList empty_patch_list_;
3708 };
3709
TEST_F(TracingServiceImplScrapingWithSmbTest,ScrapeAfterInflatedCount)3710 TEST_F(TracingServiceImplScrapingWithSmbTest, ScrapeAfterInflatedCount) {
3711 SharedMemoryABI::ChunkHeader header = {};
3712 header.writer_id.store(writer_->writer_id(), std::memory_order_relaxed);
3713 header.chunk_id.store(0, std::memory_order_relaxed);
3714 header.packets.store({}, std::memory_order_relaxed);
3715
3716 SharedMemoryABI::Chunk chunk =
3717 arbiter_->GetNewChunk(header, BufferExhaustedPolicy::kDrop);
3718 ASSERT_TRUE(chunk.is_valid());
3719
3720 protozero::ScatteredStreamWriter stream_writer(&empty_delegate_);
3721 stream_writer.Reset({chunk.payload_begin(), chunk.end()});
3722
3723 chunk.IncrementPacketCount();
3724
3725 perfetto::protos::pbzero::TracePacket trace_packet;
3726 protozero::MessageArena arena;
3727 trace_packet.Reset(&stream_writer, &arena);
3728 trace_packet.set_size_field(stream_writer.ReserveBytes(4));
3729
3730 trace_packet.set_for_testing()->set_str("payload1");
3731
3732 trace_packet.Finalize();
3733
3734 auto packets = FlushAndRead();
3735 ASSERT_TRUE(packets.has_value());
3736 // The scraping should not have seen the packet.
3737 EXPECT_THAT(*packets,
3738 Not(Contains(Property(
3739 &protos::gen::TracePacket::for_testing,
3740 Property(&protos::gen::TestEvent::str, Eq("payload1"))))));
3741
3742 // Inflate the packet count: this is what
3743 // TraceWriterImpl::FinishTracePacket() does.
3744 chunk.IncrementPacketCount();
3745
3746 packets = FlushAndRead();
3747 ASSERT_TRUE(packets.has_value());
3748 // The scraping now should see the packet.
3749 EXPECT_THAT(*packets,
3750 Contains(Property(
3751 &protos::gen::TracePacket::for_testing,
3752 Property(&protos::gen::TestEvent::str, Eq("payload1")))));
3753
3754 // Before marking the chunk as complete, the trace writer writes an empty
3755 // trace packet (a single byte with zero size), to account for the inflated
3756 // trace count.
3757 ASSERT_GT(stream_writer.bytes_available(), 0u);
3758 uint8_t zero_size = 0;
3759 stream_writer.WriteBytesUnsafe(&zero_size, sizeof zero_size);
3760
3761 packets = FlushAndRead();
3762 ASSERT_TRUE(packets.has_value());
3763 // The past scraping has already seen the packet.
3764 EXPECT_THAT(*packets,
3765 Not(Contains(Property(
3766 &protos::gen::TracePacket::for_testing,
3767 Property(&protos::gen::TestEvent::str, Eq("payload1"))))));
3768
3769 arbiter_->ReturnCompletedChunk(std::move(chunk),
3770 tracing_session()->buffers_index[0],
3771 &empty_patch_list_);
3772
3773 packets = FlushAndRead();
3774 ASSERT_TRUE(packets.has_value());
3775 // The past scraping has already seen the packet.
3776 EXPECT_THAT(*packets,
3777 Not(Contains(Property(
3778 &protos::gen::TracePacket::for_testing,
3779 Property(&protos::gen::TestEvent::str, Eq("payload1"))))));
3780 }
3781
TEST_F(TracingServiceImplScrapingWithSmbTest,ScrapeAfterCompleteChunk)3782 TEST_F(TracingServiceImplScrapingWithSmbTest, ScrapeAfterCompleteChunk) {
3783 SharedMemoryABI::ChunkHeader header = {};
3784 header.writer_id.store(writer_->writer_id(), std::memory_order_relaxed);
3785 header.chunk_id.store(0, std::memory_order_relaxed);
3786 header.packets.store({}, std::memory_order_relaxed);
3787
3788 SharedMemoryABI::Chunk chunk =
3789 arbiter_->GetNewChunk(header, BufferExhaustedPolicy::kDrop);
3790 ASSERT_TRUE(chunk.is_valid());
3791
3792 protozero::ScatteredStreamWriter stream_writer(&empty_delegate_);
3793 stream_writer.Reset({chunk.payload_begin(), chunk.end()});
3794
3795 chunk.IncrementPacketCount();
3796
3797 perfetto::protos::pbzero::TracePacket trace_packet;
3798 protozero::MessageArena arena;
3799 trace_packet.Reset(&stream_writer, &arena);
3800 trace_packet.set_size_field(stream_writer.ReserveBytes(4));
3801
3802 trace_packet.set_for_testing()->set_str("payload1");
3803
3804 trace_packet.Finalize();
3805
3806 auto packets = FlushAndRead();
3807 ASSERT_TRUE(packets.has_value());
3808 // The scraping should not have seen the packet.
3809 EXPECT_THAT(*packets,
3810 Not(Contains(Property(
3811 &protos::gen::TracePacket::for_testing,
3812 Property(&protos::gen::TestEvent::str, Eq("payload1"))))));
3813
3814 // Inflate the packet count: this is what
3815 // TraceWriterImpl::FinishTracePacket() does.
3816 chunk.IncrementPacketCount();
3817
3818 // Before marking the chunk as complete, the trace writer writes an empty
3819 // trace packet (a single byte with zero size), to account for the inflated
3820 // trace count.
3821 ASSERT_GT(stream_writer.bytes_available(), 0u);
3822 uint8_t zero_size = 0;
3823 stream_writer.WriteBytesUnsafe(&zero_size, sizeof zero_size);
3824
3825 arbiter_->ReturnCompletedChunk(std::move(chunk),
3826 tracing_session()->buffers_index[0],
3827 &empty_patch_list_);
3828
3829 packets = FlushAndRead();
3830 ASSERT_TRUE(packets.has_value());
3831 // The chunk has been marked as completed. Flushing should see the packet.
3832 EXPECT_THAT(*packets,
3833 Contains(Property(
3834 &protos::gen::TracePacket::for_testing,
3835 Property(&protos::gen::TestEvent::str, Eq("payload1")))));
3836 }
3837
TEST_F(TracingServiceImplTest,AbortIfTraceDurationIsTooLong)3838 TEST_F(TracingServiceImplTest, AbortIfTraceDurationIsTooLong) {
3839 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3840 consumer->Connect(svc.get());
3841
3842 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3843 producer->Connect(svc.get(), "mock_producer");
3844 producer->RegisterDataSource("datasource");
3845
3846 TraceConfig trace_config;
3847 trace_config.add_buffers()->set_size_kb(128);
3848 trace_config.add_data_sources()->mutable_config()->set_name("datasource");
3849 trace_config.set_duration_ms(0x7fffffff);
3850
3851 EXPECT_CALL(*producer, SetupDataSource(_, _)).Times(0);
3852 consumer->EnableTracing(trace_config);
3853
3854 // The trace is aborted immediately, the default timeout here is just some
3855 // slack for the thread ping-pongs for slow devices.
3856 consumer->WaitForTracingDisabled();
3857 }
3858
TEST_F(TracingServiceImplTest,GetTraceStats)3859 TEST_F(TracingServiceImplTest, GetTraceStats) {
3860 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3861 consumer->Connect(svc.get());
3862
3863 consumer->GetTraceStats();
3864 consumer->WaitForTraceStats(false);
3865
3866 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3867 producer->Connect(svc.get(), "mock_producer");
3868 producer->RegisterDataSource("data_source");
3869
3870 TraceConfig trace_config;
3871 trace_config.add_buffers()->set_size_kb(128);
3872 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3873 ds_config->set_name("data_source");
3874
3875 consumer->EnableTracing(trace_config);
3876 producer->WaitForTracingSetup();
3877 producer->WaitForDataSourceSetup("data_source");
3878 producer->WaitForDataSourceStart("data_source");
3879
3880 consumer->GetTraceStats();
3881 consumer->WaitForTraceStats(true);
3882
3883 consumer->DisableTracing();
3884 producer->WaitForDataSourceStop("data_source");
3885 consumer->WaitForTracingDisabled();
3886 }
3887
TEST_F(TracingServiceImplTest,TraceWriterStats)3888 TEST_F(TracingServiceImplTest, TraceWriterStats) {
3889 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3890 consumer->Connect(svc.get());
3891
3892 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3893 producer->Connect(svc.get(), "mock_producer");
3894 producer->RegisterDataSource("data_source_1");
3895 producer->RegisterDataSource("data_source_2");
3896
3897 TraceConfig trace_config;
3898 for (uint32_t i = 0; i < 3; i++)
3899 trace_config.add_buffers()->set_size_kb(512);
3900 for (uint32_t i = 1; i <= 2; i++) {
3901 auto* ds_config = trace_config.add_data_sources()->mutable_config();
3902 ds_config->set_name("data_source_" + std::to_string(i));
3903 ds_config->set_target_buffer(i); // DS1 : buf[1], DS2: buf[2].
3904 // buf[0] is deliberately unused, to check we get the buffer_idx right.
3905 }
3906
3907 consumer->EnableTracing(trace_config);
3908 producer->WaitForTracingSetup();
3909 producer->WaitForDataSourceSetup("data_source_1");
3910 producer->WaitForDataSourceSetup("data_source_2");
3911 producer->WaitForDataSourceStart("data_source_1");
3912 producer->WaitForDataSourceStart("data_source_2");
3913
3914 const std::string payload_128(128 - 32, 'a');
3915 const std::string payload_512(512 - 32, 'b');
3916 const std::string payload_1k(1024 - 32, 'c');
3917 const std::string payload_2k(2048 - 32, 'd');
3918
3919 auto writer1 = producer->CreateTraceWriter("data_source_1");
3920 auto writer2 = producer->CreateTraceWriter("data_source_2");
3921
3922 // Flush after each packet to create chunks that match packets.
3923 writer1->NewTracePacket()->set_for_testing()->set_str(payload_128);
3924 writer1->Flush();
3925
3926 writer1->NewTracePacket()->set_for_testing()->set_str(payload_1k);
3927 writer1->Flush();
3928
3929 writer2->NewTracePacket()->set_for_testing()->set_str(payload_512);
3930 writer2->Flush();
3931
3932 writer2->NewTracePacket()->set_for_testing()->set_str(payload_2k);
3933 writer2->Flush();
3934
3935 writer2->NewTracePacket()->set_for_testing()->set_str(payload_2k);
3936 writer2->Flush();
3937
3938 auto flush_request = consumer->Flush();
3939 producer->ExpectFlush({writer1.get(), writer2.get()});
3940 ASSERT_TRUE(flush_request.WaitForReply());
3941
3942 writer1.reset();
3943 writer2.reset();
3944
3945 consumer->DisableTracing();
3946 producer->WaitForDataSourceStop("data_source_1");
3947 producer->WaitForDataSourceStop("data_source_2");
3948 consumer->WaitForTracingDisabled();
3949
3950 auto packets = consumer->ReadBuffers();
3951 EXPECT_THAT(
3952 packets,
3953 Contains(Property(&protos::gen::TracePacket::has_trace_stats, Eq(true))));
3954 for (const auto& packet : packets) {
3955 if (!packet.has_trace_stats())
3956 continue;
3957
3958 EXPECT_GT(packet.trace_stats().writer_stats().size(), 0u);
3959 for (const auto& wri : packet.trace_stats().writer_stats()) {
3960 for (size_t i = 0; i < wri.chunk_payload_histogram_counts().size() - 1;
3961 i++) {
3962 PERFETTO_DLOG("Seq=%" PRIu64 ", %" PRIu64 " : %" PRIu64,
3963 wri.sequence_id(),
3964 packet.trace_stats().chunk_payload_histogram_def()[i],
3965 wri.chunk_payload_histogram_counts()[i]);
3966 }
3967
3968 switch (wri.sequence_id()) {
3969 case 1: // Ignore service-generated packets.
3970 continue;
3971 case 2: // writer1
3972 EXPECT_EQ(wri.buffer(), 1u);
3973 EXPECT_THAT(wri.chunk_payload_histogram_counts(),
3974 ElementsAreArray({0 /*8*/, 0 /*32*/, 1 /*128*/, 0 /*512*/,
3975 1 /*1K*/, 0 /*2K*/, 0 /*4K*/, 0 /*8K*/,
3976 0 /*12K*/, 0 /*16K*/, 0 /*>16K*/}));
3977 continue;
3978 case 3: // writer2
3979 EXPECT_EQ(wri.buffer(), 2u);
3980 EXPECT_THAT(wri.chunk_payload_histogram_counts(),
3981 ElementsAreArray({0 /*8*/, 0 /*32*/, 0 /*128*/, 1 /*512*/,
3982 0 /*1K*/, 2 /*2K*/, 0 /*4K*/, 0 /*8K*/,
3983 0 /*12K*/, 0 /*16K*/, 0 /*>16K*/}));
3984 continue;
3985 default:
3986 ASSERT_TRUE(false) << "Unexpected sequence " << wri.sequence_id();
3987 }
3988 }
3989 }
3990 }
3991
TEST_F(TracingServiceImplTest,ObserveEventsDataSourceInstances)3992 TEST_F(TracingServiceImplTest, ObserveEventsDataSourceInstances) {
3993 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
3994 consumer->Connect(svc.get());
3995
3996 std::unique_ptr<MockProducer> producer = CreateMockProducer();
3997 producer->Connect(svc.get(), "mock_producer");
3998 producer->RegisterDataSource("data_source");
3999
4000 TraceConfig trace_config;
4001 trace_config.add_buffers()->set_size_kb(128);
4002 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4003 ds_config->set_name("data_source");
4004
4005 // Start tracing before the consumer is interested in events. The consumer's
4006 // OnObservableEvents() should not be called yet.
4007 consumer->EnableTracing(trace_config);
4008 producer->WaitForTracingSetup();
4009 producer->WaitForDataSourceSetup("data_source");
4010 producer->WaitForDataSourceStart("data_source");
4011
4012 // Calling ObserveEvents should cause an event for the initial instance state.
4013 consumer->ObserveEvents(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
4014 {
4015 auto events = consumer->WaitForObservableEvents();
4016
4017 ObservableEvents::DataSourceInstanceStateChange change;
4018 change.set_producer_name("mock_producer");
4019 change.set_data_source_name("data_source");
4020 change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
4021 EXPECT_EQ(events.instance_state_changes_size(), 1);
4022 EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
4023 }
4024
4025 // Disabling should cause an instance state change to STOPPED.
4026 consumer->DisableTracing();
4027
4028 {
4029 auto events = consumer->WaitForObservableEvents();
4030
4031 ObservableEvents::DataSourceInstanceStateChange change;
4032 change.set_producer_name("mock_producer");
4033 change.set_data_source_name("data_source");
4034 change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
4035 EXPECT_EQ(events.instance_state_changes_size(), 1);
4036 EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
4037 }
4038
4039 producer->WaitForDataSourceStop("data_source");
4040 consumer->WaitForTracingDisabled();
4041 consumer->FreeBuffers();
4042
4043 // Enable again, this should cause a state change for a new instance to
4044 // its initial state STOPPED.
4045 trace_config.set_deferred_start(true);
4046 consumer->EnableTracing(trace_config);
4047
4048 {
4049 auto events = consumer->WaitForObservableEvents();
4050
4051 ObservableEvents::DataSourceInstanceStateChange change;
4052 change.set_producer_name("mock_producer");
4053 change.set_data_source_name("data_source");
4054 change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
4055 EXPECT_EQ(events.instance_state_changes_size(), 1);
4056 EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
4057 }
4058
4059 producer->WaitForDataSourceSetup("data_source");
4060
4061 // Should move the instance into STARTED state and thus cause an event.
4062 consumer->StartTracing();
4063
4064 {
4065 auto events = consumer->WaitForObservableEvents();
4066
4067 ObservableEvents::DataSourceInstanceStateChange change;
4068 change.set_producer_name("mock_producer");
4069 change.set_data_source_name("data_source");
4070 change.set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
4071 EXPECT_EQ(events.instance_state_changes_size(), 1);
4072 EXPECT_THAT(events.instance_state_changes(), Contains(Eq(change)));
4073 }
4074
4075 producer->WaitForDataSourceStart("data_source");
4076
4077 // Stop observing events.
4078 consumer->ObserveEvents(0);
4079
4080 // Disabling should now no longer cause events to be sent to the consumer.
4081 consumer->DisableTracing();
4082 producer->WaitForDataSourceStop("data_source");
4083 consumer->WaitForTracingDisabled();
4084 }
4085
TEST_F(TracingServiceImplTest,ObserveEventsDataSourceInstancesUnregister)4086 TEST_F(TracingServiceImplTest, ObserveEventsDataSourceInstancesUnregister) {
4087 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4088 consumer->Connect(svc.get());
4089
4090 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4091 producer->Connect(svc.get(), "mock_producer");
4092 producer->RegisterDataSource("data_source");
4093
4094 TraceConfig trace_config;
4095 trace_config.add_buffers()->set_size_kb(128);
4096 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4097 ds_config->set_name("data_source");
4098
4099 // Start tracing before the consumer is interested in events. The consumer's
4100 // OnObservableEvents() should not be called yet.
4101 consumer->EnableTracing(trace_config);
4102 producer->WaitForTracingSetup();
4103 producer->WaitForDataSourceSetup("data_source");
4104 producer->WaitForDataSourceStart("data_source");
4105
4106 // Calling ObserveEvents should cause an event for the initial instance state.
4107 consumer->ObserveEvents(ObservableEvents::TYPE_DATA_SOURCES_INSTANCES);
4108 {
4109 ObservableEvents event;
4110 ObservableEvents::DataSourceInstanceStateChange* change =
4111 event.add_instance_state_changes();
4112 change->set_producer_name("mock_producer");
4113 change->set_data_source_name("data_source");
4114 change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
4115 EXPECT_CALL(*consumer, OnObservableEvents(Eq(event)))
4116 .WillOnce(InvokeWithoutArgs(
4117 task_runner.CreateCheckpoint("data_source_started")));
4118
4119 task_runner.RunUntilCheckpoint("data_source_started");
4120 }
4121 {
4122 ObservableEvents event;
4123 ObservableEvents::DataSourceInstanceStateChange* change =
4124 event.add_instance_state_changes();
4125 change->set_producer_name("mock_producer");
4126 change->set_data_source_name("data_source");
4127 change->set_state(ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
4128 EXPECT_CALL(*consumer, OnObservableEvents(Eq(event)))
4129 .WillOnce(InvokeWithoutArgs(
4130 task_runner.CreateCheckpoint("data_source_stopped")));
4131 }
4132 producer->UnregisterDataSource("data_source");
4133 producer->WaitForDataSourceStop("data_source");
4134 task_runner.RunUntilCheckpoint("data_source_stopped");
4135
4136 consumer->DisableTracing();
4137 consumer->WaitForTracingDisabled();
4138 }
4139
TEST_F(TracingServiceImplTest,ObserveAllDataSourceStarted)4140 TEST_F(TracingServiceImplTest, ObserveAllDataSourceStarted) {
4141 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4142 consumer->Connect(svc.get());
4143
4144 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4145 producer->Connect(svc.get(), "mock_producer");
4146 producer->RegisterDataSource("ds1", /*ack_stop=*/false, /*ack_start=*/true);
4147 producer->RegisterDataSource("ds2", /*ack_stop=*/false, /*ack_start=*/true);
4148
4149 TraceConfig trace_config;
4150 trace_config.set_deferred_start(true);
4151 trace_config.add_buffers()->set_size_kb(128);
4152 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4153 ds_config->set_name("ds1");
4154 ds_config = trace_config.add_data_sources()->mutable_config();
4155 ds_config->set_name("ds2");
4156
4157 for (int repetition = 0; repetition < 3; repetition++) {
4158 consumer->EnableTracing(trace_config);
4159
4160 if (repetition == 0)
4161 producer->WaitForTracingSetup();
4162
4163 producer->WaitForDataSourceSetup("ds1");
4164 producer->WaitForDataSourceSetup("ds2");
4165 task_runner.RunUntilIdle();
4166
4167 consumer->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
4168 consumer->StartTracing();
4169 producer->WaitForDataSourceStart("ds1");
4170 producer->WaitForDataSourceStart("ds2");
4171
4172 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds1");
4173 producer->endpoint()->NotifyDataSourceStarted(id1);
4174
4175 // The notification shouldn't happen yet, ds2 has not acked.
4176 task_runner.RunUntilIdle();
4177 Mock::VerifyAndClearExpectations(consumer.get());
4178
4179 EXPECT_THAT(
4180 consumer->ReadBuffers(),
4181 Contains(Property(
4182 &protos::gen::TracePacket::service_event,
4183 Property(
4184 &protos::gen::TracingServiceEvent::all_data_sources_started,
4185 Eq(false)))));
4186
4187 DataSourceInstanceID id2 = producer->GetDataSourceInstanceId("ds2");
4188 producer->endpoint()->NotifyDataSourceStarted(id2);
4189
4190 // Now the |all_data_sources_started| notification should be sent.
4191
4192 auto events = consumer->WaitForObservableEvents();
4193 ObservableEvents::DataSourceInstanceStateChange change;
4194 EXPECT_TRUE(events.all_data_sources_started());
4195
4196 // Disabling should cause an instance state change to STOPPED.
4197 consumer->DisableTracing();
4198 producer->WaitForDataSourceStop("ds1");
4199 producer->WaitForDataSourceStop("ds2");
4200 consumer->WaitForTracingDisabled();
4201
4202 EXPECT_THAT(
4203 consumer->ReadBuffers(),
4204 Contains(Property(
4205 &protos::gen::TracePacket::service_event,
4206 Property(
4207 &protos::gen::TracingServiceEvent::all_data_sources_started,
4208 Eq(true)))));
4209 consumer->FreeBuffers();
4210
4211 task_runner.RunUntilIdle();
4212
4213 Mock::VerifyAndClearExpectations(consumer.get());
4214 Mock::VerifyAndClearExpectations(producer.get());
4215 }
4216 }
4217
TEST_F(TracingServiceImplTest,ObserveAllDataSourceStartedWithoutMatchingInstances)4218 TEST_F(TracingServiceImplTest,
4219 ObserveAllDataSourceStartedWithoutMatchingInstances) {
4220 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4221 consumer->Connect(svc.get());
4222
4223 TraceConfig trace_config;
4224 trace_config.add_buffers()->set_size_kb(128);
4225
4226 consumer->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
4227
4228 // EnableTracing() should immediately cause ALL_DATA_SOURCES_STARTED, because
4229 // there aren't any matching data sources registered.
4230 consumer->EnableTracing(trace_config);
4231
4232 auto events = consumer->WaitForObservableEvents();
4233 ObservableEvents::DataSourceInstanceStateChange change;
4234 EXPECT_TRUE(events.all_data_sources_started());
4235
4236 consumer->DisableTracing();
4237 consumer->WaitForTracingDisabled();
4238
4239 EXPECT_THAT(
4240 consumer->ReadBuffers(),
4241 Contains(Property(
4242 &protos::gen::TracePacket::service_event,
4243 Property(&protos::gen::TracingServiceEvent::all_data_sources_started,
4244 Eq(true)))));
4245 consumer->FreeBuffers();
4246
4247 task_runner.RunUntilIdle();
4248
4249 Mock::VerifyAndClearExpectations(consumer.get());
4250 }
4251
4252 // Similar to ObserveAllDataSourceStarted, but covers the case of some data
4253 // sources not supporting the |notify_on_start|.
TEST_F(TracingServiceImplTest,ObserveAllDataSourceStartedOnlySomeWillAck)4254 TEST_F(TracingServiceImplTest, ObserveAllDataSourceStartedOnlySomeWillAck) {
4255 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4256 consumer->Connect(svc.get());
4257
4258 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4259 producer->Connect(svc.get(), "mock_producer");
4260 producer->RegisterDataSource("ds1", /*ack_stop=*/false, /*ack_start=*/true);
4261 producer->RegisterDataSource("ds2_no_ack");
4262
4263 TraceConfig trace_config;
4264 trace_config.set_deferred_start(true);
4265 trace_config.add_buffers()->set_size_kb(128);
4266 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4267 ds_config->set_name("ds1");
4268 ds_config = trace_config.add_data_sources()->mutable_config();
4269 ds_config->set_name("ds2_no_ack");
4270
4271 for (int repetition = 0; repetition < 3; repetition++) {
4272 consumer->EnableTracing(trace_config);
4273
4274 if (repetition == 0)
4275 producer->WaitForTracingSetup();
4276
4277 producer->WaitForDataSourceSetup("ds1");
4278 producer->WaitForDataSourceSetup("ds2_no_ack");
4279 task_runner.RunUntilIdle();
4280
4281 consumer->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
4282 consumer->StartTracing();
4283 producer->WaitForDataSourceStart("ds1");
4284 producer->WaitForDataSourceStart("ds2_no_ack");
4285
4286 DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds1");
4287 producer->endpoint()->NotifyDataSourceStarted(id1);
4288
4289 auto events = consumer->WaitForObservableEvents();
4290 ObservableEvents::DataSourceInstanceStateChange change;
4291 EXPECT_TRUE(events.all_data_sources_started());
4292
4293 // Disabling should cause an instance state change to STOPPED.
4294 consumer->DisableTracing();
4295 producer->WaitForDataSourceStop("ds1");
4296 producer->WaitForDataSourceStop("ds2_no_ack");
4297 consumer->FreeBuffers();
4298 consumer->WaitForTracingDisabled();
4299
4300 task_runner.RunUntilIdle();
4301 Mock::VerifyAndClearExpectations(consumer.get());
4302 Mock::VerifyAndClearExpectations(producer.get());
4303 }
4304 }
4305
4306 // Similar to ObserveAllDataSourceStarted, but covers the case of no data
4307 // sources supporting the |notify_on_start|. In this case the
4308 // TYPE_ALL_DATA_SOURCES_STARTED notification should be sent immediately after
4309 // calling Start().
TEST_F(TracingServiceImplTest,ObserveAllDataSourceStartedNoAck)4310 TEST_F(TracingServiceImplTest, ObserveAllDataSourceStartedNoAck) {
4311 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4312 consumer->Connect(svc.get());
4313
4314 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4315 producer->Connect(svc.get(), "mock_producer");
4316 producer->RegisterDataSource("ds1_no_ack");
4317 producer->RegisterDataSource("ds2_no_ack");
4318
4319 TraceConfig trace_config;
4320 trace_config.set_deferred_start(true);
4321 trace_config.add_buffers()->set_size_kb(128);
4322 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4323 ds_config->set_name("ds1_no_ack");
4324 ds_config = trace_config.add_data_sources()->mutable_config();
4325 ds_config->set_name("ds2_no_ack");
4326
4327 for (int repetition = 0; repetition < 3; repetition++) {
4328 consumer->EnableTracing(trace_config);
4329
4330 if (repetition == 0)
4331 producer->WaitForTracingSetup();
4332
4333 producer->WaitForDataSourceSetup("ds1_no_ack");
4334 producer->WaitForDataSourceSetup("ds2_no_ack");
4335 task_runner.RunUntilIdle();
4336
4337 consumer->ObserveEvents(ObservableEvents::TYPE_ALL_DATA_SOURCES_STARTED);
4338 consumer->StartTracing();
4339 producer->WaitForDataSourceStart("ds1_no_ack");
4340 producer->WaitForDataSourceStart("ds2_no_ack");
4341
4342 auto events = consumer->WaitForObservableEvents();
4343 ObservableEvents::DataSourceInstanceStateChange change;
4344 EXPECT_TRUE(events.all_data_sources_started());
4345
4346 // Disabling should cause an instance state change to STOPPED.
4347 consumer->DisableTracing();
4348 producer->WaitForDataSourceStop("ds1_no_ack");
4349 producer->WaitForDataSourceStop("ds2_no_ack");
4350 consumer->FreeBuffers();
4351 consumer->WaitForTracingDisabled();
4352
4353 task_runner.RunUntilIdle();
4354 Mock::VerifyAndClearExpectations(consumer.get());
4355 Mock::VerifyAndClearExpectations(producer.get());
4356 }
4357 }
4358
TEST_F(TracingServiceImplTest,LifecycleEventSmoke)4359 TEST_F(TracingServiceImplTest, LifecycleEventSmoke) {
4360 using TracingServiceEvent = protos::gen::TracingServiceEvent;
4361 using TracingServiceEventFnPtr = bool (TracingServiceEvent::*)() const;
4362 auto has_lifecycle_field = [](TracingServiceEventFnPtr ptr) {
4363 return Contains(Property(&protos::gen::TracePacket::service_event,
4364 Property(ptr, Eq(true))));
4365 };
4366 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4367 consumer->Connect(svc.get());
4368
4369 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4370 producer->Connect(svc.get(), "mock_producer");
4371 producer->RegisterDataSource("data_source");
4372
4373 TraceConfig trace_config;
4374 trace_config.add_buffers()->set_size_kb(128);
4375 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
4376
4377 consumer->EnableTracing(trace_config);
4378
4379 producer->WaitForTracingSetup();
4380 producer->WaitForDataSourceSetup("data_source");
4381 producer->WaitForDataSourceStart("data_source");
4382 task_runner.RunUntilIdle();
4383
4384 auto packets = consumer->ReadBuffers();
4385 EXPECT_THAT(packets,
4386 has_lifecycle_field(&TracingServiceEvent::tracing_started));
4387 EXPECT_THAT(packets, has_lifecycle_field(
4388 &TracingServiceEvent::all_data_sources_started));
4389 EXPECT_THAT(packets,
4390 has_lifecycle_field(
4391 &TracingServiceEvent::read_tracing_buffers_completed));
4392
4393 std::unique_ptr<TraceWriter> writer =
4394 producer->CreateTraceWriter("data_source");
4395 {
4396 auto tp = writer->NewTracePacket();
4397 tp->set_for_testing()->set_str("payload");
4398 }
4399
4400 auto flush_request = consumer->Flush();
4401 producer->ExpectFlush(writer.get());
4402 ASSERT_TRUE(flush_request.WaitForReply());
4403
4404 packets = consumer->ReadBuffers();
4405 EXPECT_THAT(packets, has_lifecycle_field(
4406 &TracingServiceEvent::all_data_sources_flushed));
4407 EXPECT_THAT(packets,
4408 has_lifecycle_field(
4409 &TracingServiceEvent::read_tracing_buffers_completed));
4410
4411 consumer->DisableTracing();
4412 producer->WaitForDataSourceStop("data_source");
4413 consumer->WaitForTracingDisabled();
4414
4415 packets = consumer->ReadBuffers();
4416 EXPECT_THAT(packets,
4417 has_lifecycle_field(&TracingServiceEvent::tracing_disabled));
4418 EXPECT_THAT(packets,
4419 has_lifecycle_field(
4420 &TracingServiceEvent::read_tracing_buffers_completed));
4421 }
4422
TEST_F(TracingServiceImplTest,LifecycleMultipleFlushEventsQueued)4423 TEST_F(TracingServiceImplTest, LifecycleMultipleFlushEventsQueued) {
4424 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4425 consumer->Connect(svc.get());
4426
4427 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4428 producer->Connect(svc.get(), "mock_producer");
4429 producer->RegisterDataSource("data_source");
4430
4431 TraceConfig trace_config;
4432 trace_config.add_buffers()->set_size_kb(128);
4433 trace_config.add_data_sources()->mutable_config()->set_name("data_source");
4434
4435 consumer->EnableTracing(trace_config);
4436
4437 producer->WaitForTracingSetup();
4438 producer->WaitForDataSourceSetup("data_source");
4439 producer->WaitForDataSourceStart("data_source");
4440 task_runner.RunUntilIdle();
4441
4442 std::unique_ptr<TraceWriter> writer =
4443 producer->CreateTraceWriter("data_source");
4444 {
4445 auto tp = writer->NewTracePacket();
4446 tp->set_for_testing()->set_str("payload");
4447 }
4448
4449 auto flush_request = consumer->Flush();
4450 producer->ExpectFlush(writer.get());
4451 ASSERT_TRUE(flush_request.WaitForReply());
4452
4453 {
4454 auto tp = writer->NewTracePacket();
4455 tp->set_for_testing()->set_str("payload");
4456 }
4457
4458 flush_request = consumer->Flush();
4459 producer->ExpectFlush(writer.get());
4460 ASSERT_TRUE(flush_request.WaitForReply());
4461
4462 auto packets = consumer->ReadBuffers();
4463 uint32_t count = 0;
4464 for (const auto& packet : packets) {
4465 count += packet.service_event().all_data_sources_flushed();
4466 }
4467 ASSERT_EQ(count, 2u);
4468
4469 consumer->DisableTracing();
4470 producer->WaitForDataSourceStop("data_source");
4471 consumer->WaitForTracingDisabled();
4472 }
4473
TEST_F(TracingServiceImplTest,QueryServiceState)4474 TEST_F(TracingServiceImplTest, QueryServiceState) {
4475 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4476 consumer->Connect(svc.get());
4477
4478 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
4479 producer1->Connect(svc.get(), "producer1", /*uid=*/0);
4480
4481 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
4482 producer2->Connect(svc.get(), "producer2", /*uid=*/1002);
4483
4484 producer1->RegisterDataSource("common_ds");
4485 producer2->RegisterDataSource("common_ds");
4486
4487 producer1->RegisterDataSource("p1_ds");
4488 producer2->RegisterDataSource("p2_ds");
4489
4490 producer2->RegisterDataSource("common_ds");
4491
4492 TracingServiceState svc_state = consumer->QueryServiceState();
4493
4494 EXPECT_EQ(svc_state.producers_size(), 2);
4495 EXPECT_EQ(svc_state.producers().at(0).id(), 1);
4496 EXPECT_EQ(svc_state.producers().at(0).name(), "producer1");
4497 EXPECT_EQ(svc_state.producers().at(0).uid(), 0);
4498 EXPECT_EQ(svc_state.producers().at(1).id(), 2);
4499 EXPECT_EQ(svc_state.producers().at(1).name(), "producer2");
4500 EXPECT_EQ(svc_state.producers().at(1).uid(), 1002);
4501
4502 EXPECT_EQ(svc_state.data_sources_size(), 5);
4503
4504 auto count_ds = [&](int32_t producer_id, const std::string& ds_name) {
4505 int count = 0;
4506 for (const auto& ds : svc_state.data_sources()) {
4507 if (ds.producer_id() == producer_id &&
4508 ds.ds_descriptor().name() == ds_name)
4509 ++count;
4510 }
4511 return count;
4512 };
4513
4514 EXPECT_EQ(count_ds(1, "common_ds"), 1);
4515 EXPECT_EQ(count_ds(1, "p1_ds"), 1);
4516 EXPECT_EQ(count_ds(2, "common_ds"), 2);
4517 EXPECT_EQ(count_ds(2, "p2_ds"), 1);
4518
4519 // Test that descriptors are cleared when a producer disconnects.
4520 producer1.reset();
4521 svc_state = consumer->QueryServiceState();
4522
4523 EXPECT_EQ(svc_state.producers_size(), 1);
4524 EXPECT_EQ(svc_state.data_sources_size(), 3);
4525
4526 EXPECT_EQ(count_ds(1, "common_ds"), 0);
4527 EXPECT_EQ(count_ds(1, "p1_ds"), 0);
4528 EXPECT_EQ(count_ds(2, "common_ds"), 2);
4529 EXPECT_EQ(count_ds(2, "p2_ds"), 1);
4530 }
4531
TEST_F(TracingServiceImplTest,UpdateDataSource)4532 TEST_F(TracingServiceImplTest, UpdateDataSource) {
4533 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4534 consumer->Connect(svc.get());
4535
4536 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
4537 producer1->Connect(svc.get(), "producer1", /*uid=*/0);
4538
4539 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
4540 producer2->Connect(svc.get(), "producer2", /*uid=*/1002);
4541
4542 producer1->RegisterTrackEventDataSource({"cat1"}, 1);
4543 producer2->RegisterTrackEventDataSource({}, 1);
4544 producer2->RegisterTrackEventDataSource({}, 2);
4545
4546 // This request should fail because ID=2 is already registered.
4547 producer2->RegisterTrackEventDataSource({"this_should_fail"}, 2);
4548
4549 TracingServiceState svc_state = consumer->QueryServiceState();
4550
4551 auto parse_desc = [](const perfetto::protos::gen::DataSourceDescriptor& dsd) {
4552 perfetto::protos::gen::TrackEventDescriptor desc;
4553 auto desc_raw = dsd.track_event_descriptor_raw();
4554 EXPECT_TRUE(desc.ParseFromArray(desc_raw.data(), desc_raw.size()));
4555 return desc;
4556 };
4557
4558 EXPECT_EQ(svc_state.data_sources_size(), 3);
4559
4560 EXPECT_EQ(svc_state.data_sources().at(0).producer_id(), 1);
4561 EXPECT_EQ(svc_state.data_sources().at(0).ds_descriptor().name(),
4562 "track_event");
4563 EXPECT_EQ(svc_state.data_sources().at(0).ds_descriptor().id(), 1u);
4564 auto ted = parse_desc(svc_state.data_sources().at(0).ds_descriptor());
4565 EXPECT_EQ(ted.available_categories_size(), 1);
4566 EXPECT_EQ(ted.available_categories()[0].name(), "cat1");
4567
4568 EXPECT_EQ(svc_state.data_sources().at(1).producer_id(), 2);
4569 EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().name(),
4570 "track_event");
4571 EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().id(), 1u);
4572 ted = parse_desc(svc_state.data_sources().at(1).ds_descriptor());
4573 EXPECT_EQ(ted.available_categories_size(), 0);
4574
4575 EXPECT_EQ(svc_state.data_sources().at(2).ds_descriptor().id(), 2u);
4576
4577 // Test that TrackEvent DataSource is updated.
4578 producer2->UpdateTrackEventDataSource({"cat1", "cat2"}, 2);
4579
4580 svc_state = consumer->QueryServiceState();
4581
4582 EXPECT_EQ(svc_state.data_sources_size(), 3);
4583
4584 EXPECT_EQ(svc_state.data_sources().at(0).producer_id(), 1);
4585 EXPECT_EQ(svc_state.data_sources().at(0).ds_descriptor().id(), 1u);
4586 ted = parse_desc(svc_state.data_sources().at(0).ds_descriptor());
4587 EXPECT_EQ(ted.available_categories_size(), 1);
4588
4589 EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().id(), 1u);
4590 ted = parse_desc(svc_state.data_sources().at(1).ds_descriptor());
4591 EXPECT_EQ(ted.available_categories_size(), 0);
4592
4593 EXPECT_EQ(svc_state.data_sources().at(2).producer_id(), 2);
4594 EXPECT_EQ(svc_state.data_sources().at(2).ds_descriptor().id(), 2u);
4595 ted = parse_desc(svc_state.data_sources().at(2).ds_descriptor());
4596 EXPECT_EQ(ted.available_categories_size(), 2);
4597 EXPECT_EQ(ted.available_categories()[0].name(), "cat1");
4598 EXPECT_EQ(ted.available_categories()[1].name(), "cat2");
4599
4600 // Test removal of a category.
4601 producer2->UpdateTrackEventDataSource({"cat2"}, 2);
4602
4603 svc_state = consumer->QueryServiceState();
4604
4605 EXPECT_EQ(svc_state.data_sources_size(), 3);
4606 EXPECT_EQ(svc_state.data_sources().at(2).ds_descriptor().id(), 2u);
4607 ted = parse_desc(svc_state.data_sources().at(2).ds_descriptor());
4608 EXPECT_EQ(ted.available_categories_size(), 1);
4609 EXPECT_EQ(ted.available_categories()[0].name(), "cat2");
4610
4611 // Test adding a category to the first data source.
4612 producer2->UpdateTrackEventDataSource({"cat3"}, 1);
4613
4614 svc_state = consumer->QueryServiceState();
4615
4616 EXPECT_EQ(svc_state.data_sources_size(), 3);
4617 EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().id(), 1u);
4618 ted = parse_desc(svc_state.data_sources().at(1).ds_descriptor());
4619 EXPECT_EQ(ted.available_categories_size(), 1);
4620 EXPECT_EQ(ted.available_categories()[0].name(), "cat3");
4621 }
4622
TEST_F(TracingServiceImplTest,LimitSessionsPerUid)4623 TEST_F(TracingServiceImplTest, LimitSessionsPerUid) {
4624 std::vector<std::unique_ptr<MockConsumer>> consumers;
4625
4626 auto start_new_session = [&](uid_t uid) -> MockConsumer* {
4627 TraceConfig trace_config;
4628 trace_config.add_buffers()->set_size_kb(128);
4629 trace_config.set_duration_ms(0); // Unlimited.
4630 consumers.emplace_back(CreateMockConsumer());
4631 consumers.back()->Connect(svc.get(), uid);
4632 consumers.back()->EnableTracing(trace_config);
4633 return &*consumers.back();
4634 };
4635
4636 const int kMaxConcurrentTracingSessionsPerUid = 5;
4637 const int kUids = 2;
4638
4639 // Create a bunch of legit sessions (2 uids * 5 sessions).
4640 for (int i = 0; i < kMaxConcurrentTracingSessionsPerUid * kUids; i++) {
4641 start_new_session(/*uid=*/static_cast<uid_t>(i) % kUids);
4642 }
4643
4644 // Any other session now should fail for the two uids.
4645 for (int i = 0; i <= kUids; i++) {
4646 auto* consumer = start_new_session(/*uid=*/static_cast<uid_t>(i) % kUids);
4647 auto on_fail = task_runner.CreateCheckpoint("uid_" + std::to_string(i));
4648 EXPECT_CALL(*consumer, OnTracingDisabled(StrNe("")))
4649 .WillOnce(InvokeWithoutArgs(on_fail));
4650 }
4651
4652 // Wait for failure (only after both attempts).
4653 for (int i = 0; i <= kUids; i++) {
4654 task_runner.RunUntilCheckpoint("uid_" + std::to_string(i));
4655 }
4656
4657 // The destruction of |consumers| will tear down and stop the good sessions.
4658 }
4659
TEST_F(TracingServiceImplTest,ProducerProvidedSMB)4660 TEST_F(TracingServiceImplTest, ProducerProvidedSMB) {
4661 static constexpr size_t kShmSizeBytes = 1024 * 1024;
4662 static constexpr size_t kShmPageSizeBytes = 4 * 1024;
4663
4664 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4665
4666 TestSharedMemory::Factory factory;
4667 auto shm = factory.CreateSharedMemory(kShmSizeBytes);
4668 SharedMemory* shm_raw = shm.get();
4669
4670 // Service should adopt the SMB provided by the producer.
4671 producer->Connect(svc.get(), "mock_producer", /*uid=*/42, /*pid=*/1025,
4672 /*shared_memory_size_hint_bytes=*/0, kShmPageSizeBytes,
4673 std::move(shm));
4674 EXPECT_TRUE(producer->endpoint()->IsShmemProvidedByProducer());
4675 EXPECT_NE(producer->endpoint()->MaybeSharedMemoryArbiter(), nullptr);
4676 EXPECT_EQ(producer->endpoint()->shared_memory(), shm_raw);
4677
4678 producer->WaitForTracingSetup();
4679 producer->RegisterDataSource("data_source");
4680
4681 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4682 consumer->Connect(svc.get());
4683
4684 TraceConfig trace_config;
4685 trace_config.add_buffers()->set_size_kb(128);
4686 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4687 ds_config->set_name("data_source");
4688
4689 consumer->EnableTracing(trace_config);
4690 producer->WaitForDataSourceSetup("data_source");
4691 producer->WaitForDataSourceStart("data_source");
4692
4693 // Verify that data written to the producer-provided SMB ends up in trace
4694 // buffer correctly.
4695 std::unique_ptr<TraceWriter> writer =
4696 producer->CreateTraceWriter("data_source");
4697 {
4698 auto tp = writer->NewTracePacket();
4699 tp->set_for_testing()->set_str("payload");
4700 }
4701
4702 auto flush_request = consumer->Flush();
4703 producer->ExpectFlush(writer.get());
4704 ASSERT_TRUE(flush_request.WaitForReply());
4705
4706 consumer->DisableTracing();
4707 producer->WaitForDataSourceStop("data_source");
4708 consumer->WaitForTracingDisabled();
4709 EXPECT_THAT(consumer->ReadBuffers(),
4710 Contains(Property(
4711 &protos::gen::TracePacket::for_testing,
4712 Property(&protos::gen::TestEvent::str, Eq("payload")))));
4713 }
4714
TEST_F(TracingServiceImplTest,ProducerProvidedSMBInvalidSizes)4715 TEST_F(TracingServiceImplTest, ProducerProvidedSMBInvalidSizes) {
4716 static constexpr size_t kShmSizeBytes = 1024 * 1024;
4717 static constexpr size_t kShmPageSizeBytes = 20 * 1024;
4718
4719 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4720
4721 TestSharedMemory::Factory factory;
4722 auto shm = factory.CreateSharedMemory(kShmSizeBytes);
4723
4724 // Service should not adopt the SMB provided by the producer, because the SMB
4725 // size isn't a multiple of the page size.
4726 producer->Connect(svc.get(), "mock_producer", /*uid=*/42, /*pid=*/1025,
4727 /*shared_memory_size_hint_bytes=*/0, kShmPageSizeBytes,
4728 std::move(shm));
4729 EXPECT_FALSE(producer->endpoint()->IsShmemProvidedByProducer());
4730 EXPECT_EQ(producer->endpoint()->shared_memory(), nullptr);
4731 }
4732
4733 // If the consumer specifies a UUID in the TraceConfig, the TraceUuid packet
4734 // must match that.
TEST_F(TracingServiceImplTest,UuidPacketMatchesConfigUuid)4735 TEST_F(TracingServiceImplTest, UuidPacketMatchesConfigUuid) {
4736 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4737 consumer->Connect(svc.get());
4738 TraceConfig trace_config;
4739 trace_config.set_trace_uuid_lsb(1);
4740 trace_config.set_trace_uuid_msb(2);
4741 trace_config.add_buffers()->set_size_kb(8);
4742 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4743 ds_config->set_name("data_source");
4744
4745 consumer->EnableTracing(trace_config);
4746 consumer->DisableTracing();
4747 consumer->WaitForTracingDisabled();
4748
4749 auto packets = consumer->ReadBuffers();
4750
4751 EXPECT_THAT(
4752 packets,
4753 Contains(Property(&protos::gen::TracePacket::trace_uuid,
4754 AllOf(Property(&protos::gen::TraceUuid::lsb, Eq(1)),
4755 Property(&protos::gen::TraceUuid::msb, Eq(2))))));
4756 }
4757
4758 // If the consumer does not specify any UUID in the TraceConfig, a random
4759 // UUID must be generated and reported in the TraceUuid packet.
TEST_F(TracingServiceImplTest,RandomUuidIfNoConfigUuid)4760 TEST_F(TracingServiceImplTest, RandomUuidIfNoConfigUuid) {
4761 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4762 consumer->Connect(svc.get());
4763 TraceConfig trace_config;
4764 trace_config.add_buffers()->set_size_kb(8);
4765 auto* ds_config = trace_config.add_data_sources()->mutable_config();
4766 ds_config->set_name("data_source");
4767
4768 consumer->EnableTracing(trace_config);
4769 consumer->DisableTracing();
4770 consumer->WaitForTracingDisabled();
4771
4772 auto packets = consumer->ReadBuffers();
4773
4774 EXPECT_THAT(packets,
4775 Contains(Property(
4776 &protos::gen::TracePacket::trace_uuid,
4777 Not(AnyOf(Property(&protos::gen::TraceUuid::lsb, Eq(0)),
4778 Property(&protos::gen::TraceUuid::msb, Eq(0)))))));
4779 }
4780
TEST_F(TracingServiceImplTest,CloneSession)4781 TEST_F(TracingServiceImplTest, CloneSession) {
4782 // The consumer the creates the initial tracing session.
4783 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4784 consumer->Connect(svc.get());
4785
4786 // The consumer that clones it and reads back the data.
4787 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
4788 consumer2->Connect(svc.get());
4789
4790 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4791 producer->Connect(svc.get(), "mock_producer");
4792
4793 // Create two data sources, as we'll write on two distinct buffers.
4794 producer->RegisterDataSource("ds_1");
4795 producer->RegisterDataSource("ds_2");
4796
4797 TraceConfig trace_config;
4798 trace_config.add_buffers()->set_size_kb(32); // Buf 0.
4799 trace_config.add_buffers()->set_size_kb(32); // Buf 1.
4800 trace_config.set_trace_uuid_lsb(4242);
4801 trace_config.set_trace_uuid_msb(3737);
4802 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
4803 ds_cfg->set_name("ds_1");
4804 ds_cfg->set_target_buffer(0);
4805 ds_cfg = trace_config.add_data_sources()->mutable_config();
4806 ds_cfg->set_name("ds_2");
4807 ds_cfg->set_target_buffer(1);
4808
4809 // Add a filter and check that the filter is propagated to the cloned session.
4810 // The filter allows the `for_testing` field but not the root `timestamp`.
4811 protozero::FilterBytecodeGenerator filt;
4812 // Message 0: root Trace proto.
4813 filt.AddNestedField(1 /* root trace.packet*/, 1);
4814 filt.EndMessage();
4815 // Message 1: TracePacket proto. Allow only the `for_testing` and `trace_uuid`
4816 // sub-fields.
4817 filt.AddSimpleField(protos::pbzero::TracePacket::kTraceUuidFieldNumber);
4818 filt.AddSimpleField(protos::pbzero::TracePacket::kForTestingFieldNumber);
4819 filt.EndMessage();
4820 trace_config.mutable_trace_filter()->set_bytecode(filt.Serialize());
4821
4822 consumer->EnableTracing(trace_config);
4823 producer->WaitForTracingSetup();
4824
4825 producer->WaitForDataSourceSetup("ds_1");
4826 producer->WaitForDataSourceSetup("ds_2");
4827
4828 producer->WaitForDataSourceStart("ds_1");
4829 producer->WaitForDataSourceStart("ds_2");
4830
4831 std::unique_ptr<TraceWriter> writers[] = {
4832 producer->CreateTraceWriter("ds_1"),
4833 producer->CreateTraceWriter("ds_2"),
4834 };
4835
4836 // Add some data to both buffers.
4837 static constexpr size_t kNumTestPackets = 20;
4838 for (size_t i = 0; i < kNumTestPackets; i++) {
4839 auto tp = writers[i % 1]->NewTracePacket();
4840 std::string payload("payload" + std::to_string(i));
4841 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
4842 tp->set_timestamp(static_cast<uint64_t>(i));
4843 }
4844
4845 auto clone_done = task_runner.CreateCheckpoint("clone_done");
4846 base::Uuid clone_uuid;
4847 EXPECT_CALL(*consumer2, OnSessionCloned(_))
4848 .WillOnce(Invoke(
4849 [clone_done, &clone_uuid](const Consumer::OnSessionClonedArgs& args) {
4850 ASSERT_TRUE(args.success);
4851 ASSERT_TRUE(args.error.empty());
4852 // Ensure the LSB is preserved, but the MSB is different. See
4853 // comments in tracing_service_impl.cc and perfetto_cmd.cc around
4854 // triggering_subscription_id().
4855 ASSERT_EQ(args.uuid.lsb(), 4242);
4856 ASSERT_NE(args.uuid.msb(), 3737);
4857 clone_uuid = args.uuid;
4858 clone_done();
4859 }));
4860 consumer2->CloneSession(1);
4861 // CloneSession() will implicitly issue a flush. Linearize with that.
4862 producer->ExpectFlush({writers[0].get(), writers[1].get()});
4863 task_runner.RunUntilCheckpoint("clone_done");
4864
4865 // Overwrite the ring buffer of the original session to check that clone
4866 // actually returns a copy.
4867 for (size_t i = 0; i < 1000; i++) {
4868 auto tp = writers[i % 2]->NewTracePacket();
4869 std::string payload(1000u, 'x');
4870 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
4871 }
4872
4873 auto flush_request = consumer->Flush();
4874 producer->ExpectFlush({writers[0].get(), writers[1].get()});
4875 ASSERT_TRUE(flush_request.WaitForReply());
4876
4877 // Delete the initial tracing session.
4878 consumer->DisableTracing();
4879 consumer->FreeBuffers();
4880 producer->WaitForDataSourceStop("ds_1");
4881 producer->WaitForDataSourceStop("ds_2");
4882 consumer->WaitForTracingDisabled();
4883
4884 // Read back the cloned trace and check the contents.
4885 auto packets = consumer2->ReadBuffers();
4886 for (size_t i = 0; i < kNumTestPackets; i++) {
4887 std::string payload = "payload" + std::to_string(i);
4888 EXPECT_THAT(packets,
4889 Contains(Property(
4890 &protos::gen::TracePacket::for_testing,
4891 Property(&protos::gen::TestEvent::str, Eq(payload)))));
4892 }
4893
4894 // Check that the "x" payload written after cloning the session is not there.
4895 EXPECT_THAT(packets,
4896 Not(Contains(Property(&protos::gen::TracePacket::for_testing,
4897 Property(&protos::gen::TestEvent::str,
4898 testing::StartsWith("x"))))));
4899
4900 // Check that the `timestamp` field is filtered out.
4901 EXPECT_THAT(packets,
4902 Each(Property(&protos::gen::TracePacket::has_timestamp, false)));
4903
4904 // Check that the UUID in the trace matches the UUID passed to to the
4905 // OnCloneSession consumer API.
4906 EXPECT_THAT(
4907 packets,
4908 Contains(Property(
4909 &protos::gen::TracePacket::trace_uuid,
4910 AllOf(
4911 Property(&protos::gen::TraceUuid::msb, Eq(clone_uuid.msb())),
4912 Property(&protos::gen::TraceUuid::lsb, Eq(clone_uuid.lsb()))))));
4913 }
4914
4915 // Test that a consumer cannot clone a session from a consumer with a different
4916 // uid (unless it's marked as eligible for bugreport, see next test).
TEST_F(TracingServiceImplTest,CloneSessionAcrossUidDenied)4917 TEST_F(TracingServiceImplTest, CloneSessionAcrossUidDenied) {
4918 // The consumer the creates the initial tracing session.
4919 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4920 consumer->Connect(svc.get());
4921
4922 // The consumer that clones it and reads back the data.
4923 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
4924 consumer2->Connect(svc.get(), 1234);
4925
4926 TraceConfig trace_config;
4927 trace_config.add_buffers()->set_size_kb(32);
4928
4929 consumer->EnableTracing(trace_config);
4930 auto flush_request = consumer->Flush();
4931 ASSERT_TRUE(flush_request.WaitForReply());
4932
4933 auto clone_done = task_runner.CreateCheckpoint("clone_done");
4934 EXPECT_CALL(*consumer2, OnSessionCloned(_))
4935 .WillOnce(Invoke([clone_done](const Consumer::OnSessionClonedArgs& args) {
4936 clone_done();
4937 ASSERT_FALSE(args.success);
4938 ASSERT_TRUE(base::Contains(args.error, "session from another UID"));
4939 }));
4940 consumer2->CloneSession(1);
4941 task_runner.RunUntilCheckpoint("clone_done");
4942 }
4943
4944 // Test that a consumer can clone a session from the shell uid if the trace is
4945 // marked as eligible for bugreport. Android only.
4946 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
TEST_F(TracingServiceImplTest,CloneSessionAcrossUidForBugreport)4947 TEST_F(TracingServiceImplTest, CloneSessionAcrossUidForBugreport) {
4948 // The consumer the creates the initial tracing session.
4949 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
4950 consumer->Connect(svc.get());
4951
4952 std::unique_ptr<MockProducer> producer = CreateMockProducer();
4953 producer->Connect(svc.get(), "mock_producer");
4954 producer->RegisterDataSource("ds_1");
4955
4956 // The consumer that clones it and reads back the data.
4957 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
4958 clone_consumer->Connect(svc.get(), AID_SHELL);
4959
4960 TraceConfig trace_config;
4961 trace_config.add_buffers()->set_size_kb(32);
4962 trace_config.set_bugreport_score(1);
4963 trace_config.add_data_sources()->mutable_config()->set_name("ds_1");
4964
4965 // Add a trace filter and ensure it's ignored for bugreports (b/317065412).
4966 protozero::FilterBytecodeGenerator filt;
4967 filt.AddNestedField(1 /* root trace.packet*/, 1);
4968 filt.EndMessage();
4969 // Add a random field to keep the generator happy. This technically still
4970 // filters out the for_testing packet that we are using below.
4971 filt.AddSimpleField(protos::pbzero::TracePacket::kTraceUuidFieldNumber);
4972 filt.EndMessage();
4973 trace_config.mutable_trace_filter()->set_bytecode_v2(filt.Serialize());
4974
4975 consumer->EnableTracing(trace_config);
4976 producer->WaitForTracingSetup();
4977 producer->WaitForDataSourceSetup("ds_1");
4978 producer->WaitForDataSourceStart("ds_1");
4979 std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
4980 writer->NewTracePacket()->set_for_testing()->set_str("payload");
4981 writer.reset();
4982
4983 auto flush_request = consumer->Flush();
4984 FlushFlags flush_flags(FlushFlags::Initiator::kConsumerSdk,
4985 FlushFlags::Reason::kExplicit);
4986 producer->ExpectFlush({}, /*reply=*/true, flush_flags);
4987 ASSERT_TRUE(flush_request.WaitForReply());
4988
4989 auto clone_done = task_runner.CreateCheckpoint("clone_done");
4990 EXPECT_CALL(*clone_consumer, OnSessionCloned(_))
4991 .WillOnce(Invoke([clone_done](const Consumer::OnSessionClonedArgs& args) {
4992 clone_done();
4993 ASSERT_TRUE(args.success);
4994 }));
4995
4996 FlushFlags flush_flags2(FlushFlags::Initiator::kTraced,
4997 FlushFlags::Reason::kTraceClone,
4998 FlushFlags::CloneTarget::kBugreport);
4999 producer->ExpectFlush({}, /*reply=*/true, flush_flags2);
5000
5001 clone_consumer->CloneSession(kBugreportSessionId);
5002 task_runner.RunUntilCheckpoint("clone_done");
5003
5004 auto packets = clone_consumer->ReadBuffers();
5005 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5006 Property(&protos::gen::TestEvent::str,
5007 HasSubstr("payload")))));
5008 }
5009 #endif // OS_ANDROID
5010
TEST_F(TracingServiceImplTest,TransferOnClone)5011 TEST_F(TracingServiceImplTest, TransferOnClone) {
5012 // The consumer the creates the initial tracing session.
5013 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5014 consumer->Connect(svc.get());
5015
5016 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5017 producer->Connect(svc.get(), "mock_producer");
5018
5019 // Create two data sources, as we'll write on two distinct buffers.
5020 producer->RegisterDataSource("ds_1");
5021 producer->RegisterDataSource("ds_2");
5022
5023 TraceConfig trace_config;
5024 trace_config.add_buffers()->set_size_kb(1024); // Buf 0.
5025 auto* buf1_cfg = trace_config.add_buffers(); // Buf 1 (transfer_on_clone).
5026 buf1_cfg->set_size_kb(1024);
5027 buf1_cfg->set_transfer_on_clone(true);
5028 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5029 ds_cfg->set_name("ds_1");
5030 ds_cfg->set_target_buffer(0);
5031 ds_cfg = trace_config.add_data_sources()->mutable_config();
5032 ds_cfg->set_name("ds_2");
5033 ds_cfg->set_target_buffer(1);
5034
5035 consumer->EnableTracing(trace_config);
5036 producer->WaitForTracingSetup();
5037
5038 producer->WaitForDataSourceSetup("ds_1");
5039 producer->WaitForDataSourceSetup("ds_2");
5040
5041 producer->WaitForDataSourceStart("ds_1");
5042 producer->WaitForDataSourceStart("ds_2");
5043
5044 std::unique_ptr<TraceWriter> writers[] = {
5045 producer->CreateTraceWriter("ds_1"),
5046 producer->CreateTraceWriter("ds_2"),
5047 };
5048
5049 // Write once in the first buffer. This is expected persist across clones.
5050 static constexpr int kNumTestPackets = 10;
5051 for (int n = 0; n < kNumTestPackets; n++) {
5052 auto tp = writers[0]->NewTracePacket();
5053 base::StackString<64> payload("persistent_%d", n);
5054 tp->set_for_testing()->set_str(payload.c_str(), payload.len());
5055 }
5056
5057 const int kLastIteration = 3;
5058 for (int iteration = 1; iteration <= kLastIteration; iteration++) {
5059 // The consumer the creates the initial tracing session.
5060 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
5061 clone_consumer->Connect(svc.get());
5062
5063 // Add some new data to the 2nd buffer, which is transferred.
5064 // Omit the writing the last iteration to test we get an empty buffer.
5065 for (int n = 0; n < kNumTestPackets && iteration != kLastIteration; n++) {
5066 auto tp = writers[1]->NewTracePacket();
5067 base::StackString<64> payload("transferred_%d_%d", iteration, n);
5068 tp->set_for_testing()->set_str(payload.c_str(), payload.len());
5069 }
5070
5071 std::string clone_checkpoint_name = "clone_" + std::to_string(iteration);
5072 auto clone_done = task_runner.CreateCheckpoint(clone_checkpoint_name);
5073 base::Uuid clone_uuid;
5074 EXPECT_CALL(*clone_consumer, OnSessionCloned(_))
5075 .WillOnce(InvokeWithoutArgs(clone_done));
5076 clone_consumer->CloneSession(1);
5077
5078 // CloneSession() will implicitly issue a flush. Linearize with that.
5079 EXPECT_CALL(
5080 *producer,
5081 Flush(_, Pointee(producer->GetDataSourceInstanceId("ds_1")), 1, _))
5082 .WillOnce(Invoke([&](FlushRequestID flush_req_id,
5083 const DataSourceInstanceID*, size_t, FlushFlags) {
5084 writers[0]->Flush();
5085 producer->endpoint()->NotifyFlushComplete(flush_req_id);
5086 }));
5087 EXPECT_CALL(
5088 *producer,
5089 Flush(_, Pointee(producer->GetDataSourceInstanceId("ds_2")), 1, _))
5090 .WillOnce(Invoke([&](FlushRequestID flush_req_id,
5091 const DataSourceInstanceID*, size_t, FlushFlags) {
5092 writers[1]->Flush();
5093 producer->endpoint()->NotifyFlushComplete(flush_req_id);
5094 }));
5095 task_runner.RunUntilCheckpoint(clone_checkpoint_name);
5096
5097 auto packets = clone_consumer->ReadBuffers();
5098 std::vector<std::string> actual_payloads;
5099 for (const auto& packet : packets) {
5100 if (packet.has_for_testing())
5101 actual_payloads.emplace_back(packet.for_testing().str());
5102 }
5103 std::vector<std::string> expected_payloads;
5104 for (int n = 0; n < kNumTestPackets; n++) {
5105 base::StackString<64> expected_payload("persistent_%d", n);
5106 expected_payloads.emplace_back(expected_payload.ToStdString());
5107 }
5108 for (int n = 0; n < kNumTestPackets && iteration != kLastIteration; n++) {
5109 base::StackString<64> expected_payload("transferred_%d_%d", iteration, n);
5110 expected_payloads.emplace_back(expected_payload.ToStdString());
5111 }
5112 ASSERT_THAT(actual_payloads, ElementsAreArray(expected_payloads));
5113 } // for (iteration)
5114
5115 consumer->DisableTracing();
5116 producer->WaitForDataSourceStop("ds_1");
5117 producer->WaitForDataSourceStop("ds_2");
5118 consumer->WaitForTracingDisabled();
5119
5120 // Read the data from the primary (non-cloned) tracing session. Check that
5121 // it doesn't have any "transferred_xxx" payload but only the "persistent_xxx"
5122 // coming from the standard non-transferred buffer.
5123 auto packets = consumer->ReadBuffers();
5124 EXPECT_THAT(packets,
5125 Not(Contains(Property(&protos::gen::TracePacket::for_testing,
5126 Property(&protos::gen::TestEvent::str,
5127 HasSubstr("transferred_"))))));
5128 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5129 Property(&protos::gen::TestEvent::str,
5130 HasSubstr("persistent_")))));
5131 }
5132
TEST_F(TracingServiceImplTest,ClearBeforeClone)5133 TEST_F(TracingServiceImplTest, ClearBeforeClone) {
5134 // The consumer that creates the initial tracing session.
5135 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5136 consumer->Connect(svc.get());
5137
5138 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5139 producer->Connect(svc.get(), "mock_producer");
5140
5141 producer->RegisterDataSource("ds_1");
5142
5143 TraceConfig trace_config;
5144 // Unused. This buffer is created only to make the test less trivial and cover
5145 // the case of the clear-bufferd to be the beyond the 0th entry.
5146 trace_config.add_buffers()->set_size_kb(32);
5147
5148 auto* buf_cfg = trace_config.add_buffers();
5149 buf_cfg->set_size_kb(1024);
5150 buf_cfg->set_clear_before_clone(true);
5151 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5152 ds_cfg->set_name("ds_1");
5153 ds_cfg->set_target_buffer(1);
5154
5155 consumer->EnableTracing(trace_config);
5156 producer->WaitForTracingSetup();
5157 producer->WaitForDataSourceSetup("ds_1");
5158 producer->WaitForDataSourceStart("ds_1");
5159
5160 std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
5161
5162 // These packets, emitted before the clone, should be dropped.
5163 for (int i = 0; i < 3; i++) {
5164 writer->NewTracePacket()->set_for_testing()->set_str("before_clone");
5165 }
5166 auto flush_request = consumer->Flush();
5167 producer->ExpectFlush(writer.get());
5168 ASSERT_TRUE(flush_request.WaitForReply());
5169
5170 // The consumer the creates the initial tracing session.
5171 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
5172 clone_consumer->Connect(svc.get());
5173
5174 auto clone_done = task_runner.CreateCheckpoint("clone_done");
5175 EXPECT_CALL(*clone_consumer, OnSessionCloned(_))
5176 .WillOnce(InvokeWithoutArgs(clone_done));
5177 clone_consumer->CloneSession(1);
5178
5179 // CloneSession() will implicitly issue a flush. Write some other packets
5180 // in that callback. Those are the only ones that should survive in the cloned
5181 // session.
5182 FlushFlags flush_flags(FlushFlags::Initiator::kTraced,
5183 FlushFlags::Reason::kTraceClone);
5184 EXPECT_CALL(*producer, Flush(_, _, _, flush_flags))
5185 .WillOnce(Invoke([&](FlushRequestID flush_req_id,
5186 const DataSourceInstanceID*, size_t, FlushFlags) {
5187 writer->NewTracePacket()->set_for_testing()->set_str("after_clone");
5188 writer->Flush(
5189 [&] { producer->endpoint()->NotifyFlushComplete(flush_req_id); });
5190 }));
5191
5192 task_runner.RunUntilCheckpoint("clone_done");
5193
5194 auto packets = clone_consumer->ReadBuffers();
5195 EXPECT_THAT(packets,
5196 Not(Contains(Property(&protos::gen::TracePacket::for_testing,
5197 Property(&protos::gen::TestEvent::str,
5198 HasSubstr("before_clone"))))));
5199 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5200 Property(&protos::gen::TestEvent::str,
5201 HasSubstr("after_clone")))));
5202 }
5203
TEST_F(TracingServiceImplTest,CloneMainSessionStopped)5204 TEST_F(TracingServiceImplTest, CloneMainSessionStopped) {
5205 // The consumer that creates the initial tracing session.
5206 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5207 consumer->Connect(svc.get());
5208
5209 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5210 producer->Connect(svc.get(), "mock_producer1");
5211 producer->RegisterDataSource("ds_1");
5212
5213 TraceConfig trace_config;
5214 trace_config.add_buffers()->set_size_kb(1024); // Buf 0.
5215 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5216 ds_cfg->set_name("ds_1");
5217 ds_cfg->set_target_buffer(0);
5218
5219 consumer->EnableTracing(trace_config);
5220 producer->WaitForTracingSetup();
5221 producer->WaitForDataSourceSetup("ds_1");
5222 producer->WaitForDataSourceStart("ds_1");
5223
5224 std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
5225 {
5226 auto packet = writer->NewTracePacket();
5227 packet->set_for_testing()->set_str("before_clone");
5228 }
5229 writer->Flush();
5230
5231 consumer->DisableTracing();
5232 producer->WaitForDataSourceStop("ds_1");
5233 consumer->WaitForTracingDisabled();
5234
5235 // The tracing session is disabled, but it's still there. We can still clone
5236 // it.
5237 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
5238 clone_consumer->Connect(svc.get());
5239
5240 auto clone_done = task_runner.CreateCheckpoint("clone_done");
5241 EXPECT_CALL(*clone_consumer, OnSessionCloned(_))
5242 .WillOnce(InvokeWithoutArgs(clone_done));
5243 clone_consumer->CloneSession(1);
5244
5245 auto packets = clone_consumer->ReadBuffers();
5246 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5247 Property(&protos::gen::TestEvent::str,
5248 HasSubstr("before_clone")))));
5249 }
5250
TEST_F(TracingServiceImplTest,CloneConsumerDisconnect)5251 TEST_F(TracingServiceImplTest, CloneConsumerDisconnect) {
5252 // The consumer that creates the initial tracing session.
5253 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5254 consumer->Connect(svc.get());
5255
5256 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5257 producer->Connect(svc.get(), "mock_producer1");
5258 producer->RegisterDataSource("ds_1");
5259
5260 TraceConfig trace_config;
5261 trace_config.add_buffers()->set_size_kb(1024); // Buf 0.
5262 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5263 ds_cfg->set_name("ds_1");
5264 ds_cfg->set_target_buffer(0);
5265
5266 consumer->EnableTracing(trace_config);
5267 producer->WaitForTracingSetup();
5268 producer->WaitForDataSourceSetup("ds_1");
5269 producer->WaitForDataSourceStart("ds_1");
5270
5271 std::unique_ptr<TraceWriter> writer1 = producer->CreateTraceWriter("ds_1");
5272
5273 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
5274 clone_consumer->Connect(svc.get());
5275
5276 // CloneSession() will issue a flush.
5277 std::string producer1_flush_checkpoint_name = "producer1_flush_requested";
5278 FlushRequestID flush1_req_id;
5279 auto flush1_requested =
5280 task_runner.CreateCheckpoint(producer1_flush_checkpoint_name);
5281 EXPECT_CALL(*producer, Flush(_, _, _, _))
5282 .WillOnce([&](FlushRequestID req_id, const DataSourceInstanceID*, size_t,
5283 FlushFlags) {
5284 flush1_req_id = req_id;
5285 flush1_requested();
5286 });
5287 clone_consumer->CloneSession(1);
5288
5289 task_runner.RunUntilCheckpoint(producer1_flush_checkpoint_name);
5290
5291 // producer hasn't replied to the flush yet, so the clone operation is still
5292 // pending.
5293
5294 // The clone_consumer disconnect and goes away.
5295 clone_consumer.reset();
5296
5297 // producer replies to the flush request now.
5298 writer1->Flush();
5299 producer->endpoint()->NotifyFlushComplete(flush1_req_id);
5300 task_runner.RunUntilIdle();
5301
5302 consumer->DisableTracing();
5303 producer->WaitForDataSourceStop("ds_1");
5304 consumer->WaitForTracingDisabled();
5305 }
5306
TEST_F(TracingServiceImplTest,CloneMainSessionGoesAwayDuringFlush)5307 TEST_F(TracingServiceImplTest, CloneMainSessionGoesAwayDuringFlush) {
5308 // The consumer that creates the initial tracing session.
5309 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5310 consumer->Connect(svc.get());
5311
5312 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
5313 producer1->Connect(svc.get(), "mock_producer1");
5314 producer1->RegisterDataSource("ds_1");
5315
5316 TraceConfig trace_config;
5317 trace_config.add_buffers()->set_size_kb(1024); // Buf 0.
5318 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5319 ds_cfg->set_name("ds_1");
5320 ds_cfg->set_target_buffer(0);
5321
5322 consumer->EnableTracing(trace_config);
5323 producer1->WaitForTracingSetup();
5324 producer1->WaitForDataSourceSetup("ds_1");
5325 producer1->WaitForDataSourceStart("ds_1");
5326
5327 std::unique_ptr<TraceWriter> writer1 = producer1->CreateTraceWriter("ds_1");
5328
5329 {
5330 auto tp = writer1->NewTracePacket();
5331 tp->set_for_testing()->set_str("buf1_beforeflush");
5332 }
5333 writer1->Flush();
5334
5335 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
5336 clone_consumer->Connect(svc.get());
5337
5338 EXPECT_CALL(*clone_consumer, OnSessionCloned)
5339 .Times(1)
5340 .WillOnce(Invoke([](const Consumer::OnSessionClonedArgs& args) {
5341 EXPECT_FALSE(args.success);
5342 EXPECT_THAT(args.error, HasSubstr("Original session ended"));
5343 }));
5344 clone_consumer->CloneSession(1);
5345
5346 std::string producer1_flush_checkpoint_name = "producer1_flush_requested";
5347 auto flush1_requested =
5348 task_runner.CreateCheckpoint(producer1_flush_checkpoint_name);
5349 FlushRequestID flush1_req_id;
5350
5351 // CloneSession() will issue a flush.
5352 EXPECT_CALL(*producer1, Flush(_, _, _, _))
5353 .WillOnce([&](FlushRequestID flush_id, const DataSourceInstanceID*,
5354 size_t, FlushFlags) {
5355 flush1_req_id = flush_id;
5356 flush1_requested();
5357 });
5358
5359 task_runner.RunUntilCheckpoint(producer1_flush_checkpoint_name);
5360
5361 // The main session goes away.
5362 consumer->DisableTracing();
5363 producer1->WaitForDataSourceStop("ds_1");
5364 consumer->WaitForTracingDisabled();
5365 consumer.reset();
5366
5367 // producer1 replies to flush much later.
5368 producer1->endpoint()->NotifyFlushComplete(flush1_req_id);
5369 task_runner.RunUntilIdle();
5370 }
5371
TEST_F(TracingServiceImplTest,CloneTransferFlush)5372 TEST_F(TracingServiceImplTest, CloneTransferFlush) {
5373 // The consumer the creates the initial tracing session.
5374 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5375 consumer->Connect(svc.get());
5376
5377 std::unique_ptr<MockProducer> producer1 = CreateMockProducer();
5378 producer1->Connect(svc.get(), "mock_producer1");
5379 producer1->RegisterDataSource("ds_1");
5380
5381 std::unique_ptr<MockProducer> producer2 = CreateMockProducer();
5382 producer2->Connect(svc.get(), "mock_producer2");
5383 producer2->RegisterDataSource("ds_2");
5384
5385 TraceConfig trace_config;
5386 trace_config.add_buffers()->set_size_kb(1024); // Buf 0.
5387 auto* buf1_cfg = trace_config.add_buffers(); // Buf 1 (transfer_on_clone).
5388 buf1_cfg->set_size_kb(1024);
5389 buf1_cfg->set_transfer_on_clone(true);
5390 buf1_cfg->set_clear_before_clone(true);
5391 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5392 ds_cfg->set_name("ds_1");
5393 ds_cfg->set_target_buffer(0);
5394 ds_cfg = trace_config.add_data_sources()->mutable_config();
5395 ds_cfg->set_name("ds_2");
5396 ds_cfg->set_target_buffer(1);
5397
5398 consumer->EnableTracing(trace_config);
5399 producer1->WaitForTracingSetup();
5400 producer1->WaitForDataSourceSetup("ds_1");
5401
5402 producer2->WaitForTracingSetup();
5403 producer2->WaitForDataSourceSetup("ds_2");
5404
5405 producer1->WaitForDataSourceStart("ds_1");
5406 producer2->WaitForDataSourceStart("ds_2");
5407
5408 std::unique_ptr<TraceWriter> writer1 = producer1->CreateTraceWriter("ds_1");
5409 std::unique_ptr<TraceWriter> writer2 = producer2->CreateTraceWriter("ds_2");
5410
5411 {
5412 auto tp = writer1->NewTracePacket();
5413 tp->set_for_testing()->set_str("buf1_beforeflush");
5414 }
5415
5416 {
5417 std::unique_ptr<MockConsumer> clone_consumer = CreateMockConsumer();
5418 clone_consumer->Connect(svc.get());
5419
5420 {
5421 auto tp = writer2->NewTracePacket();
5422 tp->set_for_testing()->set_str("buf2_beforeflush");
5423 }
5424
5425 std::string clone_checkpoint_name = "clone";
5426 auto clone_done = task_runner.CreateCheckpoint(clone_checkpoint_name);
5427 EXPECT_CALL(*clone_consumer, OnSessionCloned(_))
5428 .WillOnce(InvokeWithoutArgs(clone_done));
5429 clone_consumer->CloneSession(1);
5430
5431 std::string producer1_flush_checkpoint_name = "producer1_flush_requested";
5432 FlushRequestID flush1_req_id;
5433 auto flush1_requested =
5434 task_runner.CreateCheckpoint(producer1_flush_checkpoint_name);
5435 std::string producer2_flush_checkpoint_name = "producer2_flush_requested";
5436 FlushRequestID flush2_req_id;
5437 auto flush2_requested =
5438 task_runner.CreateCheckpoint(producer2_flush_checkpoint_name);
5439
5440 // CloneSession() will issue a flush.
5441 EXPECT_CALL(*producer1, Flush(_, _, _, _))
5442 .WillOnce([&](FlushRequestID req_id, const DataSourceInstanceID*,
5443 size_t, FlushFlags) {
5444 flush1_req_id = req_id;
5445 flush1_requested();
5446 });
5447 EXPECT_CALL(*producer2, Flush(_, _, _, _))
5448 .WillOnce([&](FlushRequestID req_id, const DataSourceInstanceID*,
5449 size_t, FlushFlags) {
5450 flush2_req_id = req_id;
5451 flush2_requested();
5452 });
5453
5454 task_runner.RunUntilCheckpoint(producer1_flush_checkpoint_name);
5455 task_runner.RunUntilCheckpoint(producer2_flush_checkpoint_name);
5456
5457 // producer1 is fast and replies to the Flush request immediately.
5458 writer1->Flush();
5459 producer1->endpoint()->NotifyFlushComplete(flush1_req_id);
5460 task_runner.RunUntilIdle();
5461
5462 // producer1 writes another packet, after acking the flush.
5463 {
5464 auto tp = writer1->NewTracePacket();
5465 tp->set_for_testing()->set_str("buf1_afterflush");
5466 }
5467 writer1->Flush();
5468
5469 // producer2 is slower and is still writing data.
5470 {
5471 auto tp = writer2->NewTracePacket();
5472 tp->set_for_testing()->set_str("buf2_afterflush");
5473 }
5474
5475 // now producer2 replies to the Flush request.
5476 writer2->Flush();
5477 producer2->endpoint()->NotifyFlushComplete(flush2_req_id);
5478 task_runner.RunUntilCheckpoint(clone_checkpoint_name);
5479
5480 auto packets = clone_consumer->ReadBuffers();
5481 std::vector<std::string> actual_payloads;
5482 for (const auto& packet : packets) {
5483 if (packet.has_for_testing())
5484 actual_payloads.emplace_back(packet.for_testing().str());
5485 }
5486 EXPECT_THAT(actual_payloads, Contains("buf1_beforeflush"));
5487 EXPECT_THAT(actual_payloads, Contains("buf2_beforeflush"));
5488 // This packet was sent after producer1 acked the flush. producer2 hadn't
5489 // acked the flush yet, but producer2's buffer is on a separate flush group.
5490 EXPECT_THAT(actual_payloads, Not(Contains("buf1_afterflush")));
5491 EXPECT_THAT(actual_payloads, Contains("buf2_afterflush"));
5492 }
5493
5494 consumer->DisableTracing();
5495 producer1->WaitForDataSourceStop("ds_1");
5496 producer2->WaitForDataSourceStop("ds_2");
5497 consumer->WaitForTracingDisabled();
5498 }
5499
TEST_F(TracingServiceImplTest,InvalidBufferSizes)5500 TEST_F(TracingServiceImplTest, InvalidBufferSizes) {
5501 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5502 consumer->Connect(svc.get());
5503
5504 TraceConfig trace_config;
5505 trace_config.add_buffers()->set_size_kb(128);
5506 trace_config.add_buffers()->set_size_kb(256);
5507 trace_config.add_buffers()->set_size_kb(4 * 1024 * 1024);
5508 auto* ds = trace_config.add_data_sources();
5509 auto* ds_config = ds->mutable_config();
5510 ds_config->set_name("data_source");
5511 consumer->EnableTracing(trace_config);
5512
5513 std::string error;
5514 auto checkpoint = task_runner.CreateCheckpoint("tracing_disabled");
5515 EXPECT_CALL(*consumer, OnTracingDisabled(_))
5516 .WillOnce(DoAll(SaveArg<0>(&error), checkpoint));
5517 task_runner.RunUntilCheckpoint("tracing_disabled");
5518 EXPECT_THAT(error, HasSubstr("Invalid buffer sizes"));
5519 }
5520
TEST_F(TracingServiceImplTest,StringFiltering)5521 TEST_F(TracingServiceImplTest, StringFiltering) {
5522 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5523 consumer->Connect(svc.get());
5524
5525 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5526 producer->Connect(svc.get(), "mock_producer");
5527
5528 producer->RegisterDataSource("ds_1");
5529
5530 TraceConfig trace_config;
5531 trace_config.add_buffers()->set_size_kb(32); // Buf 0.
5532 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5533 ds_cfg->set_name("ds_1");
5534 ds_cfg->set_target_buffer(0);
5535
5536 protozero::FilterBytecodeGenerator filt;
5537 // Message 0: root Trace proto.
5538 filt.AddNestedField(1 /* root trace.packet*/, 1);
5539 filt.EndMessage();
5540 // Message 1: TracePacket proto. Allow only the `for_testing` sub-field.
5541 filt.AddNestedField(protos::pbzero::TracePacket::kForTestingFieldNumber, 2);
5542 filt.EndMessage();
5543 // Message 2: TestEvent proto. Allow only the `str` sub-field as a striong.
5544 filt.AddFilterStringField(protos::pbzero::TestEvent::kStrFieldNumber);
5545 filt.EndMessage();
5546 trace_config.mutable_trace_filter()->set_bytecode_v2(filt.Serialize());
5547
5548 auto* chain =
5549 trace_config.mutable_trace_filter()->mutable_string_filter_chain();
5550 auto* rule = chain->add_rules();
5551 rule->set_policy(
5552 protos::gen::TraceConfig::TraceFilter::SFP_ATRACE_MATCH_REDACT_GROUPS);
5553 rule->set_atrace_payload_starts_with("payload1");
5554 rule->set_regex_pattern(R"(B\|\d+\|pay(lo)ad1(\d*))");
5555
5556 consumer->EnableTracing(trace_config);
5557 producer->WaitForTracingSetup();
5558
5559 producer->WaitForDataSourceSetup("ds_1");
5560 producer->WaitForDataSourceStart("ds_1");
5561
5562 std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
5563 static constexpr size_t kNumTestPackets = 20;
5564 for (size_t i = 0; i < kNumTestPackets; i++) {
5565 auto tp = writer->NewTracePacket();
5566 std::string payload("B|1023|payload" + std::to_string(i));
5567 tp->set_for_testing()->set_str(payload.c_str(), payload.size());
5568 }
5569
5570 auto flush_request = consumer->Flush();
5571 producer->ExpectFlush(writer.get());
5572 ASSERT_TRUE(flush_request.WaitForReply());
5573
5574 const DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_1");
5575 EXPECT_CALL(*producer, StopDataSource(id1));
5576
5577 consumer->DisableTracing();
5578 consumer->WaitForTracingDisabled();
5579
5580 auto packets = consumer->ReadBuffers();
5581 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5582 Property(&protos::gen::TestEvent::str,
5583 Eq("B|1023|payP6ad1")))));
5584 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5585 Property(&protos::gen::TestEvent::str,
5586 Eq("B|1023|payP6ad1P")))));
5587 }
5588
TEST_F(TracingServiceImplTest,StringFilteringAndCloneSession)5589 TEST_F(TracingServiceImplTest, StringFilteringAndCloneSession) {
5590 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5591 consumer->Connect(svc.get());
5592
5593 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5594 producer->Connect(svc.get(), "mock_producer");
5595
5596 producer->RegisterDataSource("ds_1");
5597
5598 TraceConfig trace_config;
5599 trace_config.add_buffers()->set_size_kb(32); // Buf 0.
5600 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5601 ds_cfg->set_name("ds_1");
5602 ds_cfg->set_target_buffer(0);
5603
5604 protozero::FilterBytecodeGenerator filt;
5605 // Message 0: root Trace proto.
5606 filt.AddNestedField(1 /* root trace.packet*/, 1);
5607 filt.EndMessage();
5608 // Message 1: TracePacket proto. Allow only the `for_testing` sub-field.
5609 filt.AddNestedField(protos::pbzero::TracePacket::kForTestingFieldNumber, 2);
5610 filt.EndMessage();
5611 // Message 2: TestEvent proto. Allow only the `str` sub-field as a string.
5612 filt.AddFilterStringField(protos::pbzero::TestEvent::kStrFieldNumber);
5613 filt.EndMessage();
5614 trace_config.mutable_trace_filter()->set_bytecode_v2(filt.Serialize());
5615
5616 auto* chain =
5617 trace_config.mutable_trace_filter()->mutable_string_filter_chain();
5618 auto* rule = chain->add_rules();
5619 rule->set_policy(
5620 protos::gen::TraceConfig::TraceFilter::SFP_ATRACE_MATCH_REDACT_GROUPS);
5621 rule->set_atrace_payload_starts_with("payload");
5622 rule->set_regex_pattern(R"(B\|\d+\|pay(lo)ad(\d*))");
5623
5624 consumer->EnableTracing(trace_config);
5625 producer->WaitForTracingSetup();
5626
5627 producer->WaitForDataSourceSetup("ds_1");
5628 producer->WaitForDataSourceStart("ds_1");
5629
5630 std::unique_ptr<TraceWriter> writer = producer->CreateTraceWriter("ds_1");
5631
5632 {
5633 auto tp = writer->NewTracePacket();
5634 tp->set_for_testing()->set_str("B|1023|payload");
5635 }
5636
5637 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
5638 consumer2->Connect(svc.get());
5639
5640 auto clone_done = task_runner.CreateCheckpoint("clone_done");
5641 EXPECT_CALL(*consumer2, OnSessionCloned(_))
5642 .WillOnce(Invoke([clone_done](const Consumer::OnSessionClonedArgs&) {
5643 clone_done();
5644 }));
5645 consumer2->CloneSession(1);
5646 // CloneSession() will implicitly issue a flush. Linearize with that.
5647 producer->ExpectFlush(std::vector<TraceWriter*>{writer.get()});
5648 task_runner.RunUntilCheckpoint("clone_done");
5649
5650 const DataSourceInstanceID id1 = producer->GetDataSourceInstanceId("ds_1");
5651 EXPECT_CALL(*producer, StopDataSource(id1));
5652
5653 consumer->DisableTracing();
5654 consumer->WaitForTracingDisabled();
5655
5656 auto packets = consumer->ReadBuffers();
5657 EXPECT_THAT(packets, Contains(Property(&protos::gen::TracePacket::for_testing,
5658 Property(&protos::gen::TestEvent::str,
5659 Eq("B|1023|payP6ad")))));
5660 EXPECT_THAT(packets,
5661 Not(Contains(Property(&protos::gen::TracePacket::for_testing,
5662 Property(&protos::gen::TestEvent::str,
5663 Eq("B|1023|payload"))))));
5664
5665 auto cloned_packets = consumer2->ReadBuffers();
5666 EXPECT_THAT(cloned_packets,
5667 Contains(Property(&protos::gen::TracePacket::for_testing,
5668 Property(&protos::gen::TestEvent::str,
5669 Eq("B|1023|payP6ad")))));
5670 EXPECT_THAT(cloned_packets,
5671 Not(Contains(Property(&protos::gen::TracePacket::for_testing,
5672 Property(&protos::gen::TestEvent::str,
5673 Eq("B|1023|payload"))))));
5674 }
5675
5676 // This is a regression test for https://b.corp.google.com/issues/307601836. The
5677 // test covers the case of a consumer disconnecting while the tracing session is
5678 // executing the final flush.
TEST_F(TracingServiceImplTest,ConsumerDisconnectionRacesFlushAndDisable)5679 TEST_F(TracingServiceImplTest, ConsumerDisconnectionRacesFlushAndDisable) {
5680 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5681 consumer->Connect(svc.get());
5682
5683 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5684 producer->Connect(svc.get(), "mock_producer");
5685
5686 producer->RegisterDataSource("ds");
5687
5688 TraceConfig trace_config;
5689 trace_config.add_buffers()->set_size_kb(128);
5690 auto* trigger_config = trace_config.mutable_trigger_config();
5691 trigger_config->set_trigger_mode(TraceConfig::TriggerConfig::STOP_TRACING);
5692 trigger_config->set_trigger_timeout_ms(100000);
5693 auto* trigger = trigger_config->add_triggers();
5694 trigger->set_name("trigger_name");
5695 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5696 ds_cfg->set_name("ds");
5697
5698 consumer->EnableTracing(trace_config);
5699 producer->WaitForTracingSetup();
5700 producer->WaitForDataSourceSetup("ds");
5701 producer->WaitForDataSourceStart("ds");
5702
5703 auto writer1 = producer->CreateTraceWriter("ds");
5704
5705 auto producer_flush_cb = [&](FlushRequestID flush_req_id,
5706 const DataSourceInstanceID* /*id*/, size_t,
5707 FlushFlags) {
5708 // Notify the tracing service that the flush is complete.
5709 producer->endpoint()->NotifyFlushComplete(flush_req_id);
5710 // Also disconnect the consumer (this terminates the tracing session). The
5711 // consumer disconnection is postponed with a PostTask(). The goal is to run
5712 // the lambda inside TracingServiceImpl::FlushAndDisableTracing() with an
5713 // empty `tracing_sessions_` map.
5714 task_runner.PostTask([&]() { consumer.reset(); });
5715 };
5716 EXPECT_CALL(*producer, Flush(_, _, _, _)).WillOnce(Invoke(producer_flush_cb));
5717
5718 // Cause the tracing session to stop. Note that
5719 // TracingServiceImpl::FlushAndDisableTracing() is also called when
5720 // duration_ms expires, but in a test it's faster to use a trigger.
5721 producer->endpoint()->ActivateTriggers({"trigger_name"});
5722 producer->WaitForDataSourceStop("ds");
5723
5724 task_runner.RunUntilIdle();
5725 }
5726
TEST_F(TracingServiceImplTest,RelayEndpointClockSync)5727 TEST_F(TracingServiceImplTest, RelayEndpointClockSync) {
5728 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5729 consumer->Connect(svc.get());
5730
5731 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5732 producer->Connect(svc.get(), "mock_producer");
5733
5734 auto relay_client = svc->ConnectRelayClient(
5735 std::make_pair<uint32_t, uint64_t>(/*base::MachineID=*/0x103, 1));
5736
5737 uint32_t clock_id =
5738 static_cast<uint32_t>(protos::gen::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
5739
5740 relay_client->SyncClocks(RelayEndpoint::SyncMode::PING,
5741 /*client_clocks=*/{{clock_id, 100}},
5742 /*host_clocks=*/{{clock_id, 1000}});
5743 relay_client->SyncClocks(RelayEndpoint::SyncMode::UPDATE,
5744 /*client_clocks=*/{{clock_id, 300}},
5745 /*host_clocks=*/{{clock_id, 1200}});
5746
5747 producer->RegisterDataSource("ds");
5748
5749 TraceConfig trace_config;
5750 trace_config.add_buffers()->set_size_kb(128);
5751 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5752 ds_cfg->set_name("ds");
5753
5754 consumer->EnableTracing(trace_config);
5755 producer->WaitForTracingSetup();
5756 producer->WaitForDataSourceSetup("ds");
5757 producer->WaitForDataSourceStart("ds");
5758
5759 auto writer1 = producer->CreateTraceWriter("ds");
5760
5761 consumer->DisableTracing();
5762 producer->WaitForDataSourceStop("ds");
5763 consumer->WaitForTracingDisabled();
5764
5765 task_runner.RunUntilIdle();
5766
5767 auto trace_packets = consumer->ReadBuffers();
5768 bool clock_sync_packet_seen = false;
5769 for (auto& packet : trace_packets) {
5770 if (!packet.has_remote_clock_sync())
5771 continue;
5772 clock_sync_packet_seen = true;
5773
5774 auto& remote_clock_sync = packet.remote_clock_sync();
5775 ASSERT_EQ(remote_clock_sync.synced_clocks_size(), 2);
5776
5777 auto& snapshots = remote_clock_sync.synced_clocks();
5778 ASSERT_TRUE(snapshots[0].has_client_clocks());
5779 auto* snapshot = &snapshots[0].client_clocks();
5780 ASSERT_EQ(snapshot->clocks_size(), 1);
5781 ASSERT_EQ(snapshot->clocks()[0].clock_id(), clock_id);
5782 ASSERT_EQ(snapshot->clocks()[0].timestamp(), 100u);
5783
5784 snapshot = &snapshots[0].host_clocks();
5785 ASSERT_EQ(snapshot->clocks_size(), 1);
5786 ASSERT_EQ(snapshot->clocks()[0].clock_id(), clock_id);
5787 ASSERT_EQ(snapshot->clocks()[0].timestamp(), 1000u);
5788
5789 snapshot = &snapshots[1].client_clocks();
5790 ASSERT_EQ(snapshot->clocks_size(), 1);
5791 ASSERT_EQ(snapshot->clocks()[0].clock_id(), clock_id);
5792 ASSERT_EQ(snapshot->clocks()[0].timestamp(), 300u);
5793
5794 snapshot = &snapshots[1].host_clocks();
5795 ASSERT_EQ(snapshot->clocks_size(), 1);
5796 ASSERT_EQ(snapshot->clocks()[0].clock_id(), clock_id);
5797 ASSERT_EQ(snapshot->clocks()[0].timestamp(), 1200u);
5798 }
5799 ASSERT_TRUE(clock_sync_packet_seen);
5800 }
5801
TEST_F(TracingServiceImplTest,RelayEndpointDisconnect)5802 TEST_F(TracingServiceImplTest, RelayEndpointDisconnect) {
5803 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5804 consumer->Connect(svc.get());
5805
5806 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5807 producer->Connect(svc.get(), "mock_producer");
5808
5809 auto relay_client = svc->ConnectRelayClient(
5810 std::make_pair<uint32_t, uint64_t>(/*base::MachineID=*/0x103, 1));
5811 uint32_t clock_id =
5812 static_cast<uint32_t>(protos::gen::BuiltinClock::BUILTIN_CLOCK_BOOTTIME);
5813
5814 relay_client->SyncClocks(RelayEndpoint::SyncMode::PING,
5815 /*client_clocks=*/{{clock_id, 100}},
5816 /*host_clocks=*/{{clock_id, 1000}});
5817 relay_client->SyncClocks(RelayEndpoint::SyncMode::UPDATE,
5818 /*client_clocks=*/{{clock_id, 300}},
5819 /*host_clocks=*/{{clock_id, 1200}});
5820
5821 relay_client->Disconnect();
5822
5823 producer->RegisterDataSource("ds");
5824
5825 TraceConfig trace_config;
5826 trace_config.add_buffers()->set_size_kb(128);
5827 auto* ds_cfg = trace_config.add_data_sources()->mutable_config();
5828 ds_cfg->set_name("ds");
5829
5830 consumer->EnableTracing(trace_config);
5831 producer->WaitForTracingSetup();
5832 producer->WaitForDataSourceSetup("ds");
5833 producer->WaitForDataSourceStart("ds");
5834
5835 auto writer1 = producer->CreateTraceWriter("ds");
5836
5837 consumer->DisableTracing();
5838 producer->WaitForDataSourceStop("ds");
5839 consumer->WaitForTracingDisabled();
5840
5841 task_runner.RunUntilIdle();
5842
5843 auto trace_packets = consumer->ReadBuffers();
5844 bool clock_sync_packet_seen = false;
5845 for (auto& packet : trace_packets) {
5846 if (!packet.has_remote_clock_sync())
5847 continue;
5848 clock_sync_packet_seen = true;
5849 }
5850 ASSERT_FALSE(clock_sync_packet_seen);
5851 }
5852
TEST_F(TracingServiceImplTest,SessionSemaphoreMutexSingleSession)5853 TEST_F(TracingServiceImplTest, SessionSemaphoreMutexSingleSession) {
5854 TraceConfig trace_config;
5855 trace_config.add_buffers()->set_size_kb(32); // Buf 0.
5856 trace_config.add_session_semaphores()->set_name("mutex");
5857
5858 std::unique_ptr<MockProducer> producer = CreateMockProducer();
5859 producer->Connect(svc.get(), "mock_producer");
5860
5861 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5862 consumer->Connect(svc.get());
5863 consumer->EnableTracing(trace_config);
5864 consumer->DisableTracing();
5865 consumer->WaitForTracingDisabledWithError(IsEmpty());
5866 }
5867
TEST_F(TracingServiceImplTest,SessionSemaphoreMutexMultipleSession)5868 TEST_F(TracingServiceImplTest, SessionSemaphoreMutexMultipleSession) {
5869 TraceConfig trace_config;
5870 trace_config.add_buffers()->set_size_kb(32);
5871 trace_config.add_session_semaphores()->set_name("mutex");
5872
5873 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5874 consumer->Connect(svc.get());
5875 consumer->EnableTracing(trace_config);
5876
5877 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
5878 consumer2->Connect(svc.get());
5879 consumer2->EnableTracing(trace_config);
5880 consumer2->WaitForTracingDisabledWithError(LowerCase(HasSubstr("semaphore")));
5881
5882 consumer->DisableTracing();
5883 consumer->WaitForTracingDisabledWithError(IsEmpty());
5884 }
5885
TEST_F(TracingServiceImplTest,SessionSemaphoreHigherCurrentFails)5886 TEST_F(TracingServiceImplTest, SessionSemaphoreHigherCurrentFails) {
5887 TraceConfig trace_config;
5888 trace_config.add_buffers()->set_size_kb(32);
5889
5890 auto* session_semaphore = trace_config.add_session_semaphores();
5891 session_semaphore->set_name("diff_value_semaphore");
5892 session_semaphore->set_max_other_session_count(0);
5893
5894 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5895 consumer->Connect(svc.get());
5896 consumer->EnableTracing(trace_config);
5897
5898 // The second consumer sets a higher count.
5899 session_semaphore->set_max_other_session_count(1);
5900
5901 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
5902 consumer2->Connect(svc.get());
5903 consumer2->EnableTracing(trace_config);
5904 consumer2->WaitForTracingDisabledWithError(LowerCase(HasSubstr("semaphore")));
5905
5906 consumer->DisableTracing();
5907 consumer->WaitForTracingDisabledWithError(IsEmpty());
5908 }
5909
TEST_F(TracingServiceImplTest,SessionSemaphoreHigherPreviousFails)5910 TEST_F(TracingServiceImplTest, SessionSemaphoreHigherPreviousFails) {
5911 TraceConfig trace_config;
5912 trace_config.add_buffers()->set_size_kb(32);
5913
5914 auto* session_semaphore = trace_config.add_session_semaphores();
5915 session_semaphore->set_name("diff_value_semaphore");
5916 session_semaphore->set_max_other_session_count(1);
5917
5918 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5919 consumer->Connect(svc.get());
5920 consumer->EnableTracing(trace_config);
5921
5922 // The second consumer sets a lower count.
5923 session_semaphore->set_max_other_session_count(0);
5924
5925 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
5926 consumer2->Connect(svc.get());
5927 consumer2->EnableTracing(trace_config);
5928 consumer2->WaitForTracingDisabledWithError(LowerCase(HasSubstr("semaphore")));
5929
5930 consumer->DisableTracing();
5931 consumer->WaitForTracingDisabledWithError(IsEmpty());
5932 }
5933
TEST_F(TracingServiceImplTest,SessionSemaphoreAllowedUpToLimit)5934 TEST_F(TracingServiceImplTest, SessionSemaphoreAllowedUpToLimit) {
5935 TraceConfig trace_config;
5936 trace_config.add_buffers()->set_size_kb(32);
5937
5938 auto* session_semaphore = trace_config.add_session_semaphores();
5939 session_semaphore->set_name("multi_semaphore");
5940 session_semaphore->set_max_other_session_count(3);
5941
5942 std::unique_ptr<MockConsumer> consumer = CreateMockConsumer();
5943 consumer->Connect(svc.get());
5944 consumer->EnableTracing(trace_config);
5945
5946 std::unique_ptr<MockConsumer> consumer2 = CreateMockConsumer();
5947 consumer2->Connect(svc.get());
5948 consumer2->EnableTracing(trace_config);
5949
5950 std::unique_ptr<MockConsumer> consumer3 = CreateMockConsumer();
5951 consumer3->Connect(svc.get());
5952 consumer3->EnableTracing(trace_config);
5953
5954 std::unique_ptr<MockConsumer> consumer4 = CreateMockConsumer();
5955 consumer4->Connect(svc.get());
5956 consumer4->EnableTracing(trace_config);
5957
5958 std::unique_ptr<MockConsumer> consumer5 = CreateMockConsumer();
5959 consumer5->Connect(svc.get());
5960 consumer5->EnableTracing(trace_config);
5961 consumer5->WaitForTracingDisabledWithError(LowerCase(HasSubstr("semaphore")));
5962
5963 consumer4->DisableTracing();
5964 consumer4->WaitForTracingDisabledWithError(IsEmpty());
5965
5966 consumer3->DisableTracing();
5967 consumer3->WaitForTracingDisabledWithError(IsEmpty());
5968
5969 consumer2->DisableTracing();
5970 consumer2->WaitForTracingDisabledWithError(IsEmpty());
5971
5972 consumer->DisableTracing();
5973 consumer->WaitForTracingDisabledWithError(IsEmpty());
5974 }
5975
5976 } // namespace perfetto
5977