blob: 0f2b53acde1619bbf0870c61f6717e7147295744 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/metrics/perf/metric_provider.h"
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/test/bind_test_util.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/sampled_profile.pb.h"
namespace metrics {
namespace {
// Returns an example PerfDataProto. The contents don't have to make sense. They
// just need to constitute a semantically valid protobuf.
// |proto| is an output parameter that will contain the created protobuf.
PerfDataProto GetExamplePerfDataProto() {
PerfDataProto proto;
proto.set_timestamp_sec(1435604013); // Time since epoch in seconds.
PerfDataProto_PerfFileAttr* file_attr = proto.add_file_attrs();
file_attr->add_ids(61);
file_attr->add_ids(62);
file_attr->add_ids(63);
PerfDataProto_PerfEventAttr* attr = file_attr->mutable_attr();
attr->set_type(1);
attr->set_size(2);
attr->set_config(3);
attr->set_sample_period(4);
attr->set_sample_freq(5);
PerfDataProto_PerfEventStats* stats = proto.mutable_stats();
stats->set_num_events_read(100);
stats->set_num_sample_events(200);
stats->set_num_mmap_events(300);
stats->set_num_fork_events(400);
stats->set_num_exit_events(500);
return proto;
}
// Allows access to some private methods for testing.
class TestMetricCollector : public internal::MetricCollector {
public:
TestMetricCollector() : TestMetricCollector(CollectionParams()) {}
explicit TestMetricCollector(const CollectionParams& collection_params)
: internal::MetricCollector("UMA.CWP.TestData", collection_params),
weak_factory_(this) {}
const char* ToolName() const override { return "test"; }
base::WeakPtr<internal::MetricCollector> GetWeakPtr() override {
return weak_factory_.GetWeakPtr();
}
void CollectProfile(
std::unique_ptr<SampledProfile> sampled_profile) override {
PerfDataProto perf_data_proto = GetExamplePerfDataProto();
SaveSerializedPerfProto(std::move(sampled_profile),
PerfProtoType::PERF_TYPE_DATA,
perf_data_proto.SerializeAsString());
}
private:
base::WeakPtrFactory<TestMetricCollector> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TestMetricCollector);
};
const base::TimeDelta kPeriodicCollectionInterval =
base::TimeDelta::FromHours(1);
const base::TimeDelta kMaxCollectionDelay = base::TimeDelta::FromSeconds(1);
} // namespace
class MetricProviderTest : public testing::Test {
public:
MetricProviderTest()
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
CollectionParams test_params;
// Set the sampling factors for the triggers to 1, so we always trigger
// collection, and set the collection delays to well known quantities, so
// we can fast forward the time.
test_params.resume_from_suspend.sampling_factor = 1;
test_params.resume_from_suspend.max_collection_delay = kMaxCollectionDelay;
test_params.restore_session.sampling_factor = 1;
test_params.restore_session.max_collection_delay = kMaxCollectionDelay;
test_params.periodic_interval = kPeriodicCollectionInterval;
metric_provider_ = std::make_unique<MetricProvider>(
std::make_unique<TestMetricCollector>(test_params));
metric_provider_->Init();
task_environment_.RunUntilIdle();
}
void TearDown() override { metric_provider_.reset(); }
protected:
// task_environment_ must be the first member (or at least before
// any member that cares about tasks) to be initialized first and destroyed
// last.
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<MetricProvider> metric_provider_;
DISALLOW_COPY_AND_ASSIGN(MetricProviderTest);
};
TEST_F(MetricProviderTest, CheckSetup) {
// There are no cached profiles at start.
std::vector<SampledProfile> stored_profiles;
EXPECT_FALSE(metric_provider_->GetSampledProfiles(&stored_profiles));
EXPECT_TRUE(stored_profiles.empty());
}
TEST_F(MetricProviderTest, DisabledBeforeLogin) {
task_environment_.FastForwardBy(kPeriodicCollectionInterval);
// There are no cached profiles after a profiling interval.
std::vector<SampledProfile> stored_profiles;
EXPECT_FALSE(metric_provider_->GetSampledProfiles(&stored_profiles));
EXPECT_TRUE(stored_profiles.empty());
}
TEST_F(MetricProviderTest, EnabledOnLogin) {
metric_provider_->OnUserLoggedIn();
task_environment_.FastForwardBy(kPeriodicCollectionInterval);
// We should find a cached PERIODIC_COLLECTION profile after a profiling
// interval.
std::vector<SampledProfile> stored_profiles;
EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
EXPECT_EQ(stored_profiles.size(), 1u);
const SampledProfile& profile = stored_profiles[0];
EXPECT_EQ(SampledProfile::PERIODIC_COLLECTION, profile.trigger_event());
EXPECT_FALSE(profile.has_suspend_duration_ms());
EXPECT_FALSE(profile.has_ms_after_resume());
EXPECT_TRUE(profile.has_ms_after_login());
EXPECT_TRUE(profile.has_ms_after_boot());
}
TEST_F(MetricProviderTest, DisabledOnDeactivate) {
metric_provider_->OnUserLoggedIn();
task_environment_.RunUntilIdle();
metric_provider_->Deactivate();
task_environment_.FastForwardBy(kPeriodicCollectionInterval);
// There are no cached profiles after a profiling interval.
std::vector<SampledProfile> stored_profiles;
EXPECT_FALSE(metric_provider_->GetSampledProfiles(&stored_profiles));
EXPECT_TRUE(stored_profiles.empty());
}
TEST_F(MetricProviderTest, SuspendDone) {
metric_provider_->OnUserLoggedIn();
task_environment_.RunUntilIdle();
const auto kSuspendDuration = base::TimeDelta::FromMinutes(3);
metric_provider_->SuspendDone(kSuspendDuration);
// Fast forward the time by the max collection delay.
task_environment_.FastForwardBy(kMaxCollectionDelay);
// Check that the SuspendDone trigger produced one profile.
std::vector<SampledProfile> stored_profiles;
EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
ASSERT_EQ(1U, stored_profiles.size());
const SampledProfile& profile = stored_profiles[0];
EXPECT_EQ(SampledProfile::RESUME_FROM_SUSPEND, profile.trigger_event());
EXPECT_EQ(kSuspendDuration.InMilliseconds(), profile.suspend_duration_ms());
EXPECT_TRUE(profile.has_ms_after_resume());
EXPECT_TRUE(profile.has_ms_after_login());
EXPECT_TRUE(profile.has_ms_after_boot());
}
TEST_F(MetricProviderTest, OnSessionRestoreDone) {
metric_provider_->OnUserLoggedIn();
task_environment_.RunUntilIdle();
const int kRestoredTabs = 7;
metric_provider_->OnSessionRestoreDone(kRestoredTabs);
// Fast forward the time by the max collection delay.
task_environment_.FastForwardBy(kMaxCollectionDelay);
std::vector<SampledProfile> stored_profiles;
EXPECT_TRUE(metric_provider_->GetSampledProfiles(&stored_profiles));
ASSERT_EQ(1U, stored_profiles.size());
const SampledProfile& profile = stored_profiles[0];
EXPECT_EQ(SampledProfile::RESTORE_SESSION, profile.trigger_event());
EXPECT_EQ(kRestoredTabs, profile.num_tabs_restored());
EXPECT_FALSE(profile.has_ms_after_resume());
EXPECT_TRUE(profile.has_ms_after_login());
EXPECT_TRUE(profile.has_ms_after_boot());
}
} // namespace metrics