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