/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "src/traced/service/builtin_producer.h" #include "perfetto/tracing/core/data_source_config.h" #include "src/base/test/test_task_runner.h" #include "test/gtest_and_gmock.h" namespace perfetto { namespace { constexpr char kHeapprofdDataSourceName[] = "android.heapprofd"; constexpr char kTracedPerfDataSourceName[] = "linux.perf"; constexpr char kLazyHeapprofdPropertyName[] = "traced.lazy.heapprofd"; constexpr char kLazyTracedPerfPropertyName[] = "traced.lazy.traced_perf"; using ::testing::_; using ::testing::InvokeWithoutArgs; using ::testing::Mock; using ::testing::Return; using ::testing::StrictMock; class MockBuiltinProducer : public BuiltinProducer { public: MockBuiltinProducer(base::TaskRunner* task_runner) : BuiltinProducer(task_runner, /*lazy_stop_delay_ms=*/0) {} MOCK_METHOD2(SetAndroidProperty, bool(const std::string&, const std::string&)); }; TEST(BuiltinProducerTest, LazyHeapprofdSimple) { DataSourceConfig cfg; cfg.set_name(kHeapprofdDataSourceName); base::TestTaskRunner task_runner; auto done = task_runner.CreateCheckpoint("done"); StrictMock p(&task_runner); testing::InSequence s; EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1")) .WillOnce(Return(true)); EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "")) .WillOnce(InvokeWithoutArgs([&done]() { done(); return true; })); p.SetupDataSource(1, cfg); p.StopDataSource(1); task_runner.RunUntilCheckpoint("done"); } TEST(BuiltinProducerTest, LazyTracedPerfSimple) { DataSourceConfig cfg; cfg.set_name(kTracedPerfDataSourceName); base::TestTaskRunner task_runner; auto done = task_runner.CreateCheckpoint("done"); StrictMock p(&task_runner); testing::InSequence s; EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, "1")) .WillOnce(Return(true)); EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, "")) .WillOnce(InvokeWithoutArgs([&done]() { done(); return true; })); p.SetupDataSource(1, cfg); p.StopDataSource(1); task_runner.RunUntilCheckpoint("done"); } TEST(BuiltinProducerTest, LazyHeapprofdRefCount) { DataSourceConfig cfg; cfg.set_name(kHeapprofdDataSourceName); base::TestTaskRunner task_runner; auto done = task_runner.CreateCheckpoint("done"); StrictMock p(&task_runner); testing::InSequence s; EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1")) .WillRepeatedly(Return(true)); p.SetupDataSource(1, cfg); p.SetupDataSource(2, cfg); p.StopDataSource(2); task_runner.RunUntilIdle(); EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "")) .WillOnce(InvokeWithoutArgs([&done]() { done(); return true; })); p.StopDataSource(1); task_runner.RunUntilCheckpoint("done"); } TEST(BuiltinProducerTest, LazyHeapprofdNoFlap) { DataSourceConfig cfg; cfg.set_name(kHeapprofdDataSourceName); base::TestTaskRunner task_runner; auto done = task_runner.CreateCheckpoint("done"); StrictMock p(&task_runner); testing::InSequence s; EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1")) .WillRepeatedly(Return(true)); p.SetupDataSource(1, cfg); p.StopDataSource(1); p.SetupDataSource(2, cfg); task_runner.RunUntilIdle(); p.StopDataSource(2); EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "")) .WillOnce(InvokeWithoutArgs([&done]() { done(); return true; })); task_runner.RunUntilCheckpoint("done"); } TEST(BuiltinProducerTest, LazyRefCountsIndependent) { DataSourceConfig cfg_perf; cfg_perf.set_name(kTracedPerfDataSourceName); DataSourceConfig cfg_heap; cfg_heap.set_name(kHeapprofdDataSourceName); base::TestTaskRunner task_runner; StrictMock p(&task_runner); testing::InSequence s; // start one instance of both types of sources EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "1")) .WillOnce(Return(true)); EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, "1")) .WillOnce(Return(true)); p.SetupDataSource(1, cfg_heap); p.SetupDataSource(2, cfg_perf); task_runner.RunUntilIdle(); Mock::VerifyAndClearExpectations(&p); // stop heapprofd source EXPECT_CALL(p, SetAndroidProperty(kLazyHeapprofdPropertyName, "")) .WillOnce(Return(true)); p.StopDataSource(1); task_runner.RunUntilIdle(); Mock::VerifyAndClearExpectations(&p); // stop traced_perf source EXPECT_CALL(p, SetAndroidProperty(kLazyTracedPerfPropertyName, "")) .WillOnce(Return(true)); p.StopDataSource(2); task_runner.RunUntilIdle(); Mock::VerifyAndClearExpectations(&p); } } // namespace } // namespace perfetto