blob: da72f9350a37b27402ff6ce3cd90410191197155 [file] [log] [blame]
// Copyright 2017 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 "services/resource_coordinator/observers/metrics_collector.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "build/build_config.h"
#include "components/ukm/test_ukm_recorder.h"
#include "services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h"
#include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h"
#include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h"
#include "services/resource_coordinator/resource_coordinator_clock.h"
namespace resource_coordinator {
const char kResponsivenessMeasurement[] = "ResponsivenessMeasurement";
const char kExpectedQueueingTime[] = "ExpectedTaskQueueingDuration";
const base::TimeDelta kTestMetricsReportDelayTimeout =
kMetricsReportDelayTimeout + base::TimeDelta::FromSeconds(1);
const base::TimeDelta kTestMaxAudioSlientTimeout =
kMaxAudioSlientTimeout + base::TimeDelta::FromSeconds(1);
// TODO(crbug.com/759905) Enable on Windows once this bug is fixed.
#if defined(OS_WIN)
#define MAYBE_MetricsCollectorTest DISABLED_MetricsCollectorTest
#else
#define MAYBE_MetricsCollectorTest MetricsCollectorTest
#endif
class MAYBE_MetricsCollectorTest : public CoordinationUnitTestHarness {
public:
MAYBE_MetricsCollectorTest() : CoordinationUnitTestHarness() {}
void SetUp() override {
MetricsCollector* metrics_collector = new MetricsCollector();
ResourceCoordinatorClock::SetClockForTesting(&clock_);
// Sets a valid starting time.
clock_.SetNowTicks(base::TimeTicks::Now());
coordination_unit_graph()->RegisterObserver(
base::WrapUnique(metrics_collector));
}
void TearDown() override {
ResourceCoordinatorClock::ResetClockForTesting();
}
protected:
static constexpr char kDummyUrl[] = "http://www.example.org";
static constexpr uint64_t kDummyID = 1u;
void AdvanceClock(base::TimeDelta delta) { clock_.Advance(delta); }
base::HistogramTester histogram_tester_;
base::SimpleTestTickClock clock_;
private:
DISALLOW_COPY_AND_ASSIGN(MAYBE_MetricsCollectorTest);
};
constexpr char MAYBE_MetricsCollectorTest::kDummyUrl[];
TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstAudioStartsUMA) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->SetVisibility(true);
frame_cu->SetAudibility(true);
// The page is not backgrounded, thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
0);
frame_cu->SetAudibility(false);
page_cu->SetVisibility(false);
frame_cu->SetAudibility(true);
// The page was recently audible, thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
0);
frame_cu->SetAudibility(false);
AdvanceClock(kTestMaxAudioSlientTimeout);
page_cu->SetVisibility(true);
frame_cu->SetAudibility(true);
// The page was not recently audible but it is not backgrounded, thus no
// metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
0);
frame_cu->SetAudibility(false);
page_cu->SetVisibility(false);
AdvanceClock(kTestMaxAudioSlientTimeout);
frame_cu->SetAudibility(true);
// The page was not recently audible and it is backgrounded, thus metrics
// recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
1);
frame_cu->SetAudibility(false);
page_cu->SetVisibility(true);
page_cu->SetVisibility(false);
AdvanceClock(kTestMaxAudioSlientTimeout);
frame_cu->SetAudibility(true);
// The page becomes visible and then invisible again, thus metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
2);
}
TEST_F(MAYBE_MetricsCollectorTest,
FromBackgroundedToFirstAudioStartsUMA5MinutesTimeout) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
page_cu->SetVisibility(false);
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
frame_cu->SetAudibility(true);
// The page is within 5 minutes after main frame navigation was committed,
// thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
0);
frame_cu->SetAudibility(false);
AdvanceClock(kTestMetricsReportDelayTimeout);
frame_cu->SetAudibility(true);
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAudioStartsUMA,
1);
}
TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstTitleUpdatedUMA) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->SetVisibility(true);
page_cu->OnTitleUpdated();
// The page is not backgrounded, thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA,
0);
page_cu->SetVisibility(false);
page_cu->OnTitleUpdated();
// The page is backgrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA,
1);
page_cu->OnTitleUpdated();
// Metrics should only be recorded once per background period, thus metrics
// not recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA,
1);
page_cu->SetVisibility(true);
page_cu->SetVisibility(false);
page_cu->OnTitleUpdated();
// The page is backgrounded from foregrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA,
2);
}
TEST_F(MAYBE_MetricsCollectorTest,
FromBackgroundedToFirstTitleUpdatedUMA5MinutesTimeout) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
page_cu->SetVisibility(false);
page_cu->OnTitleUpdated();
// The page is within 5 minutes after main frame navigation was committed,
// thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA,
0);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->OnTitleUpdated();
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstTitleUpdatedUMA,
1);
}
TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstAlertFiredUMA) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->SetVisibility(true);
frame_cu->OnAlertFired();
// The page is not backgrounded, thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAlertFiredUMA,
0);
page_cu->SetVisibility(false);
frame_cu->OnAlertFired();
// The page is backgrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAlertFiredUMA,
1);
frame_cu->OnAlertFired();
// Metrics should only be recorded once per background period, thus metrics
// not recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAlertFiredUMA,
1);
page_cu->SetVisibility(true);
page_cu->SetVisibility(false);
frame_cu->OnAlertFired();
// The page is backgrounded from foregrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAlertFiredUMA,
2);
}
TEST_F(MAYBE_MetricsCollectorTest,
FromBackgroundedToFirstAlertFiredUMA5MinutesTimeout) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
page_cu->SetVisibility(false);
frame_cu->OnAlertFired();
// The page is within 5 minutes after main frame navigation was committed,
// thus no metrics recorded.
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAlertFiredUMA,
0);
AdvanceClock(kTestMetricsReportDelayTimeout);
frame_cu->OnAlertFired();
histogram_tester_.ExpectTotalCount(kTabFromBackgroundedToFirstAlertFiredUMA,
1);
}
TEST_F(MAYBE_MetricsCollectorTest,
FromBackgroundedToFirstNonPersistentNotificationCreatedUMA) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->SetVisibility(true);
frame_cu->OnNonPersistentNotificationCreated();
// The page is not backgrounded, thus no metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstNonPersistentNotificationCreatedUMA, 0);
page_cu->SetVisibility(false);
frame_cu->OnNonPersistentNotificationCreated();
// The page is backgrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstNonPersistentNotificationCreatedUMA, 1);
frame_cu->OnNonPersistentNotificationCreated();
// Metrics should only be recorded once per background period, thus metrics
// not recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstNonPersistentNotificationCreatedUMA, 1);
page_cu->SetVisibility(true);
page_cu->SetVisibility(false);
frame_cu->OnNonPersistentNotificationCreated();
// The page is backgrounded from foregrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstNonPersistentNotificationCreatedUMA, 2);
}
TEST_F(
MAYBE_MetricsCollectorTest,
FromBackgroundedToFirstNonPersistentNotificationCreatedUMA5MinutesTimeout) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
page_cu->SetVisibility(false);
frame_cu->OnNonPersistentNotificationCreated();
// The page is within 5 minutes after main frame navigation was committed,
// thus no metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstNonPersistentNotificationCreatedUMA, 0);
AdvanceClock(kTestMetricsReportDelayTimeout);
frame_cu->OnNonPersistentNotificationCreated();
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstNonPersistentNotificationCreatedUMA, 1);
}
TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstFaviconUpdatedUMA) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->SetVisibility(true);
page_cu->OnFaviconUpdated();
// The page is not backgrounded, thus no metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstFaviconUpdatedUMA, 0);
page_cu->SetVisibility(false);
page_cu->OnFaviconUpdated();
// The page is backgrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstFaviconUpdatedUMA, 1);
page_cu->OnFaviconUpdated();
// Metrics should only be recorded once per background period, thus metrics
// not recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstFaviconUpdatedUMA, 1);
page_cu->SetVisibility(true);
page_cu->SetVisibility(false);
page_cu->OnFaviconUpdated();
// The page is backgrounded from foregrounded, thus metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstFaviconUpdatedUMA, 2);
}
TEST_F(MAYBE_MetricsCollectorTest,
FromBackgroundedToFirstFaviconUpdatedUMA5MinutesTimeout) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
page_cu->SetVisibility(false);
page_cu->OnFaviconUpdated();
// The page is within 5 minutes after main frame navigation was committed,
// thus no metrics recorded.
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstFaviconUpdatedUMA, 0);
AdvanceClock(kTestMetricsReportDelayTimeout);
page_cu->OnFaviconUpdated();
histogram_tester_.ExpectTotalCount(
kTabFromBackgroundedToFirstFaviconUpdatedUMA, 1);
}
// Flaky test: https://crbug.com/833028
TEST_F(MAYBE_MetricsCollectorTest, ResponsivenessMetric) {
auto page_cu = CreateCoordinationUnit<PageCoordinationUnitImpl>();
auto process_cu = CreateCoordinationUnit<ProcessCoordinationUnitImpl>();
auto frame_cu = CreateCoordinationUnit<FrameCoordinationUnitImpl>();
page_cu->AddFrame(frame_cu->id());
frame_cu->SetProcess(process_cu->id());
ukm::TestUkmRecorder ukm_recorder;
coordination_unit_graph()->set_ukm_recorder(&ukm_recorder);
ukm::SourceId id = ukm_recorder.GetNewSourceID();
GURL url = GURL("https://google.com/foobar");
ukm_recorder.UpdateSourceURL(id, url);
page_cu->SetUKMSourceId(id);
page_cu->OnMainFrameNavigationCommitted(ResourceCoordinatorClock::NowTicks(),
kDummyID, kDummyUrl);
for (int count = 1; count < kDefaultFrequencyUkmEQTReported; ++count) {
process_cu->SetExpectedTaskQueueingDuration(
base::TimeDelta::FromMilliseconds(3));
EXPECT_EQ(0U, ukm_recorder.entries_count());
EXPECT_EQ(1U, ukm_recorder.sources_count());
}
process_cu->SetExpectedTaskQueueingDuration(
base::TimeDelta::FromMilliseconds(4));
EXPECT_EQ(1U, ukm_recorder.sources_count());
EXPECT_EQ(1U, ukm_recorder.entries_count());
for (int count = 1; count < kDefaultFrequencyUkmEQTReported; ++count) {
process_cu->SetExpectedTaskQueueingDuration(
base::TimeDelta::FromMilliseconds(3));
EXPECT_EQ(1U, ukm_recorder.entries_count());
EXPECT_EQ(1U, ukm_recorder.sources_count());
}
process_cu->SetExpectedTaskQueueingDuration(
base::TimeDelta::FromMilliseconds(4));
EXPECT_EQ(1U, ukm_recorder.sources_count());
EXPECT_EQ(2U, ukm_recorder.entries_count());
const auto& entries =
ukm_recorder.GetEntriesByName(kResponsivenessMeasurement);
EXPECT_EQ(2U, entries.size());
for (const auto* entry : entries) {
ukm_recorder.ExpectEntrySourceHasUrl(entry, url);
ukm_recorder.ExpectEntryMetric(entry, kExpectedQueueingTime, 4);
}
}
} // namespace resource_coordinator