blob: efd5459244da5db648b18e6ac4efa5fa28ec92cb [file] [log] [blame]
// Copyright 2016 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 "components/media_router/browser/media_router_metrics.h"
#include <string>
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_clock.h"
#include "base/time/time.h"
#include "components/media_router/common/media_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using base::Bucket;
using testing::ElementsAre;
namespace media_router {
namespace {
// Tests that calling |recording_cb| with a TimeDelta records it in
// |histogram_name|.
void TestRecordTimeDeltaMetric(
base::RepeatingCallback<void(const base::TimeDelta&)> recording_cb,
const std::string& histogram_name) {
base::HistogramTester tester;
const base::TimeDelta delta = base::TimeDelta::FromMilliseconds(10);
tester.ExpectTotalCount(histogram_name, 0);
recording_cb.Run(delta);
tester.ExpectUniqueSample(histogram_name, delta.InMilliseconds(), 1);
}
// Tests that calling |recording_cb| with boolean values records them in
// |histogram_name|.
void TestRecordBooleanMetric(base::RepeatingCallback<void(bool)> recording_cb,
const std::string& histogram_name) {
base::HistogramTester tester;
tester.ExpectTotalCount(histogram_name, 0);
recording_cb.Run(true);
recording_cb.Run(false);
recording_cb.Run(true);
tester.ExpectTotalCount(histogram_name, 3);
EXPECT_THAT(tester.GetAllSamples(histogram_name),
ElementsAre(Bucket(false, 1), Bucket(true, 2)));
}
// Tests that |record_cb| records metrics for each MediaRouteProvider in a
// histogram specific to the provider.
void TestRouteResultCodeHistogramsWithProviders(
base::RepeatingCallback<void(MediaRouteProviderId,
RouteRequestResult::ResultCode)> record_cb,
MediaRouteProviderId provider1,
const std::string& histogram_provider1,
MediaRouteProviderId provider2,
const std::string& histogram_provider2) {
base::HistogramTester tester;
tester.ExpectTotalCount(histogram_provider1, 0);
tester.ExpectTotalCount(histogram_provider2, 0);
record_cb.Run(provider1, RouteRequestResult::SINK_NOT_FOUND);
record_cb.Run(provider2, RouteRequestResult::OK);
record_cb.Run(provider1, RouteRequestResult::SINK_NOT_FOUND);
record_cb.Run(provider2, RouteRequestResult::ROUTE_NOT_FOUND);
record_cb.Run(provider1, RouteRequestResult::OK);
tester.ExpectTotalCount(histogram_provider1, 3);
EXPECT_THAT(
tester.GetAllSamples(histogram_provider1),
ElementsAre(
Bucket(static_cast<int>(RouteRequestResult::OK), 1),
Bucket(static_cast<int>(RouteRequestResult::SINK_NOT_FOUND), 2)));
tester.ExpectTotalCount(histogram_provider2, 2);
EXPECT_THAT(
tester.GetAllSamples(histogram_provider2),
ElementsAre(
Bucket(static_cast<int>(RouteRequestResult::OK), 1),
Bucket(static_cast<int>(RouteRequestResult::ROUTE_NOT_FOUND), 1)));
}
void TestRouteResultCodeHistograms(
base::RepeatingCallback<void(MediaRouteProviderId,
RouteRequestResult::ResultCode)> record_cb,
const std::string& base_histogram_name) {
TestRouteResultCodeHistogramsWithProviders(
record_cb, MediaRouteProviderId::EXTENSION, base_histogram_name,
MediaRouteProviderId::WIRED_DISPLAY,
base_histogram_name + ".WiredDisplay");
TestRouteResultCodeHistogramsWithProviders(
record_cb, MediaRouteProviderId::CAST, base_histogram_name + ".Cast",
MediaRouteProviderId::DIAL, base_histogram_name + ".DIAL");
TestRouteResultCodeHistogramsWithProviders(
record_cb, MediaRouteProviderId::CAST, base_histogram_name + ".Cast",
MediaRouteProviderId::ANDROID_CAF, base_histogram_name + ".AndroidCaf");
}
} // namespace
TEST(MediaRouterMetricsTest, RecordMediaRouterDialogOrigin) {
base::HistogramTester tester;
const MediaRouterDialogOpenOrigin origin1 =
MediaRouterDialogOpenOrigin::TOOLBAR;
const MediaRouterDialogOpenOrigin origin2 =
MediaRouterDialogOpenOrigin::CONTEXTUAL_MENU;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramIconClickLocation, 0);
MediaRouterMetrics::RecordMediaRouterDialogOrigin(origin1);
MediaRouterMetrics::RecordMediaRouterDialogOrigin(origin2);
MediaRouterMetrics::RecordMediaRouterDialogOrigin(origin1);
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramIconClickLocation, 3);
EXPECT_THAT(
tester.GetAllSamples(MediaRouterMetrics::kHistogramIconClickLocation),
ElementsAre(Bucket(static_cast<int>(origin1), 2),
Bucket(static_cast<int>(origin2), 1)));
}
TEST(MediaRouterMetricsTest, RecordMediaRouterDialogPaint) {
TestRecordTimeDeltaMetric(
base::BindRepeating(&MediaRouterMetrics::RecordMediaRouterDialogPaint),
MediaRouterMetrics::kHistogramUiDialogPaint);
}
TEST(MediaRouterMetricsTest, RecordMediaRouterDialogLoaded) {
TestRecordTimeDeltaMetric(
base::BindRepeating(&MediaRouterMetrics::RecordMediaRouterDialogLoaded),
MediaRouterMetrics::kHistogramUiDialogLoadedWithData);
}
TEST(MediaRouterMetricsTest, RecordCloseDialogLatency) {
TestRecordTimeDeltaMetric(
base::BindRepeating(&MediaRouterMetrics::RecordCloseDialogLatency),
MediaRouterMetrics::kHistogramCloseLatency);
}
TEST(MediaRouterMetricsTest, RecordMediaRouterInitialUserAction) {
base::HistogramTester tester;
const MediaRouterUserAction action1 = MediaRouterUserAction::START_LOCAL;
const MediaRouterUserAction action2 = MediaRouterUserAction::CLOSE;
const MediaRouterUserAction action3 = MediaRouterUserAction::STATUS_REMOTE;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramUiFirstAction, 0);
MediaRouterMetrics::RecordMediaRouterInitialUserAction(action3);
MediaRouterMetrics::RecordMediaRouterInitialUserAction(action2);
MediaRouterMetrics::RecordMediaRouterInitialUserAction(action3);
MediaRouterMetrics::RecordMediaRouterInitialUserAction(action1);
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramUiFirstAction, 4);
EXPECT_THAT(tester.GetAllSamples(MediaRouterMetrics::kHistogramUiFirstAction),
ElementsAre(Bucket(static_cast<int>(action1), 1),
Bucket(static_cast<int>(action2), 1),
Bucket(static_cast<int>(action3), 2)));
}
TEST(MediaRouterMetricsTest, RecordRouteCreationOutcome) {
base::HistogramTester tester;
const MediaRouterRouteCreationOutcome outcome1 =
MediaRouterRouteCreationOutcome::SUCCESS;
const MediaRouterRouteCreationOutcome outcome2 =
MediaRouterRouteCreationOutcome::FAILURE_NO_ROUTE;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramRouteCreationOutcome,
0);
MediaRouterMetrics::RecordRouteCreationOutcome(outcome2);
MediaRouterMetrics::RecordRouteCreationOutcome(outcome1);
MediaRouterMetrics::RecordRouteCreationOutcome(outcome2);
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramRouteCreationOutcome,
3);
EXPECT_THAT(
tester.GetAllSamples(MediaRouterMetrics::kHistogramRouteCreationOutcome),
ElementsAre(Bucket(static_cast<int>(outcome1), 1),
Bucket(static_cast<int>(outcome2), 2)));
}
TEST(MediaRouterMetricsTest, RecordPresentationUrlType) {
base::HistogramTester tester;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramPresentationUrlType, 0);
MediaRouterMetrics::RecordPresentationUrlType(GURL("cast:DEADBEEF"));
MediaRouterMetrics::RecordPresentationUrlType(GURL("dial:AppName"));
MediaRouterMetrics::RecordPresentationUrlType(GURL("cast-dial:AppName"));
MediaRouterMetrics::RecordPresentationUrlType(GURL("https://example.com"));
MediaRouterMetrics::RecordPresentationUrlType(GURL("http://example.com"));
MediaRouterMetrics::RecordPresentationUrlType(
GURL("https://google.com/cast#__castAppId__=DEADBEEF"));
MediaRouterMetrics::RecordPresentationUrlType(GURL("remote-playback:foo"));
MediaRouterMetrics::RecordPresentationUrlType(GURL("test:test"));
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramPresentationUrlType, 8);
EXPECT_THAT(
tester.GetAllSamples(MediaRouterMetrics::kHistogramPresentationUrlType),
ElementsAre(
Bucket(static_cast<int>(PresentationUrlType::kOther), 1),
Bucket(static_cast<int>(PresentationUrlType::kCast), 1),
Bucket(static_cast<int>(PresentationUrlType::kCastDial), 1),
Bucket(static_cast<int>(PresentationUrlType::kCastLegacy), 1),
Bucket(static_cast<int>(PresentationUrlType::kDial), 1),
Bucket(static_cast<int>(PresentationUrlType::kHttp), 1),
Bucket(static_cast<int>(PresentationUrlType::kHttps), 1),
Bucket(static_cast<int>(PresentationUrlType::kRemotePlayback), 1)));
}
TEST(MediaRouterMetricsTest, RecordMediaSinkType) {
base::HistogramTester tester;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramMediaSinkType, 0);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::WIRED_DISPLAY);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::CAST);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::CAST_AUDIO);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::CAST);
MediaRouterMetrics::RecordMediaSinkType(SinkIconType::GENERIC);
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramMediaSinkType, 5);
EXPECT_THAT(
tester.GetAllSamples(MediaRouterMetrics::kHistogramMediaSinkType),
ElementsAre(Bucket(static_cast<int>(SinkIconType::CAST), 2),
Bucket(static_cast<int>(SinkIconType::CAST_AUDIO), 1),
Bucket(static_cast<int>(SinkIconType::WIRED_DISPLAY), 1),
Bucket(static_cast<int>(SinkIconType::GENERIC), 1)));
}
TEST(MediaRouterMetricsTest, RecordDeviceCount) {
base::HistogramTester tester;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramUiDeviceCount, 0);
MediaRouterMetrics::RecordDeviceCount(30);
MediaRouterMetrics::RecordDeviceCount(0);
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramUiDeviceCount, 2);
EXPECT_THAT(tester.GetAllSamples(MediaRouterMetrics::kHistogramUiDeviceCount),
ElementsAre(Bucket(0, 1), Bucket(30, 1)));
}
TEST(MediaRouterMetricsTest, RecordStartRouteDeviceIndex) {
base::HistogramTester tester;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramStartLocalPosition, 0);
MediaRouterMetrics::RecordStartRouteDeviceIndex(30);
MediaRouterMetrics::RecordStartRouteDeviceIndex(0);
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramStartLocalPosition, 2);
EXPECT_THAT(
tester.GetAllSamples(MediaRouterMetrics::kHistogramStartLocalPosition),
ElementsAre(Bucket(0, 1), Bucket(30, 1)));
}
TEST(MediaRouterMetricsTest, RecordStartLocalSessionLatency) {
TestRecordTimeDeltaMetric(
base::BindRepeating(&MediaRouterMetrics::RecordStartLocalSessionLatency),
MediaRouterMetrics::kHistogramStartLocalLatency);
}
TEST(MediaRouterMetricsTest, RecordStartLocalSessionSuccessful) {
TestRecordBooleanMetric(
base::BindRepeating(
&MediaRouterMetrics::RecordStartLocalSessionSuccessful),
MediaRouterMetrics::kHistogramStartLocalSessionSuccessful);
}
TEST(MediaRouterMetricsTest, RecordStopRoute) {
base::HistogramTester tester;
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramStopRoute, 0);
MediaRouterMetrics::RecordStopLocalRoute();
MediaRouterMetrics::RecordStopRemoteRoute();
MediaRouterMetrics::RecordStopLocalRoute();
tester.ExpectTotalCount(MediaRouterMetrics::kHistogramStopRoute, 3);
EXPECT_THAT(tester.GetAllSamples(MediaRouterMetrics::kHistogramStopRoute),
ElementsAre(Bucket(/* Local route */ 0, 2),
Bucket(/* Remote route */ 1, 1)));
}
TEST(MediaRouterMetricsTest, RecordIconStateAtDialogOpen) {
TestRecordBooleanMetric(
base::BindRepeating(&MediaRouterMetrics::RecordIconStateAtDialogOpen),
MediaRouterMetrics::kHistogramUiDialogIconStateAtOpen);
}
TEST(MediaRouterMetricsTest, RecordIconStateAtInit) {
TestRecordBooleanMetric(
base::BindRepeating(&MediaRouterMetrics::RecordIconStateAtInit),
MediaRouterMetrics::kHistogramUiIconStateAtInit);
}
TEST(MediaRouterMetricsTest, RecordCloudPrefAtDialogOpen) {
TestRecordBooleanMetric(
base::BindRepeating(&MediaRouterMetrics::RecordCloudPrefAtDialogOpen),
MediaRouterMetrics::kHistogramCloudPrefAtDialogOpen);
}
TEST(MediaRouterMetricsTest, RecordCloudPrefAtInit) {
TestRecordBooleanMetric(
base::BindRepeating(&MediaRouterMetrics::RecordCloudPrefAtInit),
MediaRouterMetrics::kHistogramCloudPrefAtInit);
}
TEST(MediaRouterMetricsTest, RecordCreateRouteResultCode) {
TestRouteResultCodeHistograms(
base::BindRepeating(&MediaRouterMetrics::RecordCreateRouteResultCode),
"MediaRouter.Provider.CreateRoute.Result");
}
TEST(MediaRouterMetricsTest, RecordJoinRouteResultCode) {
TestRouteResultCodeHistograms(
base::BindRepeating(&MediaRouterMetrics::RecordJoinRouteResultCode),
"MediaRouter.Provider.JoinRoute.Result");
}
TEST(MediaRouterMetricsTest, RecordTerminateRouteResultCode) {
TestRouteResultCodeHistograms(
base::BindRepeating(
&MediaRouterMetrics::RecordMediaRouteProviderTerminateRoute),
"MediaRouter.Provider.TerminateRoute.Result");
}
} // namespace media_router