| /* | 
 |  * Copyright (C) 2019 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/profiling/memory/heapprofd_producer.h" | 
 |  | 
 | #include "perfetto/ext/base/file_utils.h" | 
 | #include "perfetto/ext/base/temp_file.h" | 
 | #include "perfetto/ext/tracing/core/basic_types.h" | 
 | #include "perfetto/ext/tracing/core/commit_data_request.h" | 
 | #include "perfetto/tracing/core/data_source_descriptor.h" | 
 | #include "src/base/test/test_task_runner.h" | 
 | #include "src/tracing/test/mock_producer_endpoint.h" | 
 | #include "test/gtest_and_gmock.h" | 
 |  | 
 | namespace perfetto { | 
 | namespace profiling { | 
 |  | 
 | using ::testing::Contains; | 
 | using ::testing::Eq; | 
 | using ::testing::Pair; | 
 | using ::testing::Property; | 
 |  | 
 | TEST(LogHistogramTest, Simple) { | 
 |   LogHistogram h; | 
 |   h.Add(1); | 
 |   h.Add(0); | 
 |   EXPECT_THAT(h.GetData(), Contains(Pair(2, 1))); | 
 |   EXPECT_THAT(h.GetData(), Contains(Pair(1, 1))); | 
 | } | 
 |  | 
 | TEST(LogHistogramTest, Overflow) { | 
 |   LogHistogram h; | 
 |   h.Add(std::numeric_limits<uint64_t>::max()); | 
 |   EXPECT_THAT(h.GetData(), Contains(Pair(LogHistogram::kMaxBucket, 1))); | 
 | } | 
 |  | 
 | TEST(HeapprofdProducerTest, ExposesDataSource) { | 
 |   base::TestTaskRunner task_runner; | 
 |   HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner, | 
 |                              /* exit_when_done= */ false); | 
 |  | 
 |   std::unique_ptr<MockProducerEndpoint> endpoint(new MockProducerEndpoint()); | 
 |   EXPECT_CALL(*endpoint, | 
 |               RegisterDataSource(Property(&DataSourceDescriptor::name, | 
 |                                           Eq("android.heapprofd")))) | 
 |       .Times(1); | 
 |   producer.SetProducerEndpoint(std::move(endpoint)); | 
 |   producer.OnConnect(); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, Smoke) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 4096u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, DefaultHeap) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "libc.malloc"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 4096u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, TwoHeaps) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.add_heaps("bar"); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 2u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_STREQ(cli_config.heaps[1].name, "bar"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 4096u); | 
 |   EXPECT_EQ(cli_config.heaps[1].interval, 4096u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, TwoHeapsIntervals) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.add_heap_sampling_intervals(4096u); | 
 |   cfg.add_heaps("bar"); | 
 |   cfg.add_heap_sampling_intervals(1u); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 2u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_STREQ(cli_config.heaps[1].name, "bar"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 4096u); | 
 |   EXPECT_EQ(cli_config.heaps[1].interval, 1u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, OverflowHeapName) { | 
 |   std::string large_name(100, 'a'); | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps(large_name); | 
 |   cfg.set_sampling_interval_bytes(1); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 0u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, OverflowHeapNameAndValid) { | 
 |   std::string large_name(100, 'a'); | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps(large_name); | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.set_sampling_interval_bytes(1); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, ZeroSampling) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.set_sampling_interval_bytes(0); | 
 |   ClientConfiguration cli_config; | 
 |   EXPECT_FALSE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, ZeroSamplingMultiple) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.add_heap_sampling_intervals(4096u); | 
 |   cfg.add_heaps("bar"); | 
 |   cfg.add_heap_sampling_intervals(0); | 
 |   ClientConfiguration cli_config; | 
 |   EXPECT_FALSE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, AdaptiveSampling) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   cfg.set_adaptive_sampling_shmem_threshold(1024u); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 4096u); | 
 |   EXPECT_EQ(cli_config.adaptive_sampling_shmem_threshold, 1024u); | 
 |   EXPECT_EQ(cli_config.adaptive_sampling_max_sampling_interval_bytes, 0u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, AdaptiveSamplingWithMax) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   cfg.set_adaptive_sampling_shmem_threshold(1024u); | 
 |   cfg.set_adaptive_sampling_max_sampling_interval_bytes(4 * 4096u); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 4096u); | 
 |   EXPECT_EQ(cli_config.adaptive_sampling_shmem_threshold, 1024u); | 
 |   EXPECT_EQ(cli_config.adaptive_sampling_max_sampling_interval_bytes, | 
 |             4 * 4096u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, AllHeaps) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.set_all_heaps(true); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 0u); | 
 |   EXPECT_EQ(cli_config.default_interval, 4096u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, AllHeapsAndExplicit) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.set_all_heaps(true); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   cfg.add_heaps("foo"); | 
 |   cfg.add_heap_sampling_intervals(1024u); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 1024u); | 
 |   EXPECT_EQ(cli_config.default_interval, 4096u); | 
 | } | 
 |  | 
 | TEST(HeapprofdConfigToClientConfigurationTest, AllHeapsAndDisabled) { | 
 |   HeapprofdConfig cfg; | 
 |   cfg.set_all_heaps(true); | 
 |   cfg.set_sampling_interval_bytes(4096); | 
 |   cfg.add_exclude_heaps("foo"); | 
 |   ClientConfiguration cli_config; | 
 |   ASSERT_TRUE(HeapprofdConfigToClientConfiguration(cfg, &cli_config)); | 
 |   EXPECT_EQ(cli_config.num_heaps, 1u); | 
 |   EXPECT_STREQ(cli_config.heaps[0].name, "foo"); | 
 |   EXPECT_EQ(cli_config.heaps[0].interval, 0u); | 
 |   EXPECT_EQ(cli_config.default_interval, 4096u); | 
 | } | 
 |  | 
 | }  // namespace profiling | 
 | }  // namespace perfetto |