| // 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 "chromecast/base/metrics/cast_metrics_helper.h" |
| |
| #include <string> |
| |
| #include "base/json/json_reader.h" |
| #include "base/test/task_environment.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using ::testing::AllOf; |
| using ::testing::HasSubstr; |
| using ::testing::SaveArg; |
| using ::testing::_; |
| |
| namespace chromecast { |
| namespace metrics { |
| |
| namespace { |
| |
| constexpr char kAppId1[] = "APP_ID_1"; |
| constexpr char kAppId2[] = "APP_ID_2"; |
| constexpr char kAppId3[] = "APP_ID_3"; |
| constexpr char kEvent[] = "EVENT"; |
| constexpr char kSdkVersion[] = "SDK_VERSION"; |
| constexpr char kSessionId1[] = "SESSION_ID_1"; |
| constexpr char kSessionId2[] = "SESSION_ID_2"; |
| constexpr char kSessionId3[] = "SESSION_ID_3"; |
| constexpr int kValue = 123; |
| |
| constexpr base::TimeDelta kAppLoadTimeout = base::TimeDelta::FromMinutes(5); |
| |
| MATCHER_P2(HasDouble, key, value, "") { |
| auto v = base::JSONReader::ReadDeprecated(arg); |
| return v && v->FindKey(key) && v->FindKey(key)->is_double() && |
| v->FindKey(key)->GetDouble() == value; |
| } |
| |
| MATCHER_P2(HasInt, key, value, "") { |
| auto v = base::JSONReader::ReadDeprecated(arg); |
| return v && v->FindKey(key) && v->FindKey(key)->is_int() && |
| v->FindKey(key)->GetInt() == value; |
| } |
| |
| MATCHER_P2(HasString, key, value, "") { |
| auto v = base::JSONReader::ReadDeprecated(arg); |
| return v && v->FindKey(key) && v->FindKey(key)->is_string() && |
| v->FindKey(key)->GetString() == value; |
| } |
| |
| } // namespace |
| |
| class MockMetricsSink : public CastMetricsHelper::MetricsSink { |
| public: |
| MOCK_METHOD1(OnAction, void(const std::string&)); |
| MOCK_METHOD3(OnEnumerationEvent, void(const std::string&, int, int)); |
| MOCK_METHOD5(OnTimeEvent, |
| void(const std::string&, |
| base::TimeDelta, |
| base::TimeDelta, |
| base::TimeDelta, |
| int)); |
| }; |
| |
| class CastMetricsHelperTest : public ::testing::Test { |
| public: |
| CastMetricsHelperTest() |
| : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), |
| metrics_helper_(task_environment_.GetMainThreadTaskRunner(), |
| task_environment_.GetMockTickClock()) { |
| metrics_helper_.SetMetricsSink(&metrics_sink_); |
| } |
| |
| base::test::TaskEnvironment task_environment_; |
| MockMetricsSink metrics_sink_; |
| CastMetricsHelper metrics_helper_; |
| }; |
| |
| TEST_F(CastMetricsHelperTest, RecordEventWithValue) { |
| const auto expected_time = task_environment_.NowTicks(); |
| |
| EXPECT_CALL( |
| metrics_sink_, |
| OnAction( |
| AllOf(HasString("name", kEvent), |
| HasDouble("time", |
| (expected_time - base::TimeTicks()).InMicroseconds()), |
| HasInt("value", kValue)))); |
| metrics_helper_.RecordApplicationEventWithValue(kEvent, kValue); |
| } |
| |
| TEST_F(CastMetricsHelperTest, RecordApplicationEvent) { |
| metrics_helper_.DidStartLoad(kAppId1); |
| metrics_helper_.DidCompleteLoad(kAppId1, kSessionId1); |
| metrics_helper_.UpdateSDKInfo(kSdkVersion); |
| |
| const auto expected_time = task_environment_.NowTicks(); |
| |
| EXPECT_CALL( |
| metrics_sink_, |
| OnAction(AllOf( |
| HasString("name", kEvent), |
| HasDouble("time", |
| (expected_time - base::TimeTicks()).InMicroseconds()), |
| HasString("app_id", kAppId1), HasString("session_id", kSessionId1), |
| HasString("sdk_version", kSdkVersion)))); |
| metrics_helper_.RecordApplicationEvent(kEvent); |
| } |
| |
| TEST_F(CastMetricsHelperTest, RecordApplicationEventWithValue) { |
| metrics_helper_.DidStartLoad(kAppId1); |
| metrics_helper_.DidCompleteLoad(kAppId1, kSessionId1); |
| metrics_helper_.UpdateSDKInfo(kSdkVersion); |
| |
| const auto expected_time = task_environment_.NowTicks(); |
| |
| EXPECT_CALL( |
| metrics_sink_, |
| OnAction(AllOf( |
| HasString("name", kEvent), |
| HasDouble("time", |
| (expected_time - base::TimeTicks()).InMicroseconds()), |
| HasString("app_id", kAppId1), HasString("session_id", kSessionId1), |
| HasString("sdk_version", kSdkVersion), HasInt("value", kValue)))); |
| metrics_helper_.RecordApplicationEventWithValue(kEvent, kValue); |
| } |
| |
| TEST_F(CastMetricsHelperTest, LogTimeToFirstPaint) { |
| metrics_helper_.DidStartLoad(kAppId1); |
| metrics_helper_.DidCompleteLoad(kAppId1, kSessionId1); |
| |
| constexpr base::TimeDelta kTimeToFirstPaint = base::TimeDelta::FromSeconds(5); |
| task_environment_.FastForwardBy(kTimeToFirstPaint); |
| |
| EXPECT_CALL(metrics_sink_, OnTimeEvent(AllOf(HasSubstr(kAppId1), |
| HasSubstr("TimeToFirstPaint")), |
| kTimeToFirstPaint, _, _, _)); |
| metrics_helper_.LogTimeToFirstPaint(); |
| } |
| |
| TEST_F(CastMetricsHelperTest, LogTimeToFirstAudio) { |
| metrics_helper_.DidStartLoad(kAppId1); |
| metrics_helper_.DidCompleteLoad(kAppId1, kSessionId1); |
| |
| constexpr base::TimeDelta kTimeToFirstAudio = base::TimeDelta::FromSeconds(5); |
| task_environment_.FastForwardBy(kTimeToFirstAudio); |
| |
| EXPECT_CALL(metrics_sink_, OnTimeEvent(AllOf(HasSubstr(kAppId1), |
| HasSubstr("TimeToFirstAudio")), |
| kTimeToFirstAudio, _, _, _)); |
| metrics_helper_.LogTimeToFirstAudio(); |
| } |
| |
| TEST_F(CastMetricsHelperTest, MultipleApps) { |
| metrics_helper_.DidStartLoad(kAppId1); |
| task_environment_.FastForwardBy(kAppLoadTimeout); |
| metrics_helper_.DidStartLoad(kAppId2); |
| metrics_helper_.DidStartLoad(kAppId3); |
| metrics_helper_.DidCompleteLoad(kAppId3, kSessionId3); |
| // kAppId2 should become the current app. |
| metrics_helper_.DidCompleteLoad(kAppId2, kSessionId2); |
| // kAppId1 should not become the current app because it timed out. |
| metrics_helper_.DidCompleteLoad(kAppId1, kSessionId1); |
| |
| EXPECT_CALL(metrics_sink_, |
| OnAction(AllOf(HasString("app_id", kAppId2), |
| HasString("session_id", kSessionId2)))); |
| metrics_helper_.RecordApplicationEvent(kEvent); |
| } |
| |
| } // namespace metrics |
| } // namespace chromecast |