blob: 8e25a7e35f4fa38039ea641e271ca9492f9f9e58 [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 "chromecast/base/metrics/cast_metrics_helper.h"
#include <string>
#include "base/json/json_reader.h"
#include "base/test/scoped_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()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
metrics_helper_(scoped_task_environment_.GetMainThreadTaskRunner(),
scoped_task_environment_.GetMockTickClock()) {
metrics_helper_.SetMetricsSink(&metrics_sink_);
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
MockMetricsSink metrics_sink_;
CastMetricsHelper metrics_helper_;
};
TEST_F(CastMetricsHelperTest, RecordEventWithValue) {
const base::TimeDelta time = base::TimeDelta::FromSeconds(5);
scoped_task_environment_.FastForwardBy(time);
EXPECT_CALL(metrics_sink_,
OnAction(AllOf(HasString("name", kEvent),
HasDouble("time", time.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 base::TimeDelta time = base::TimeDelta::FromSeconds(5);
scoped_task_environment_.FastForwardBy(time);
EXPECT_CALL(
metrics_sink_,
OnAction(AllOf(
HasString("name", kEvent), HasDouble("time", time.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 base::TimeDelta time = base::TimeDelta::FromSeconds(5);
scoped_task_environment_.FastForwardBy(time);
EXPECT_CALL(
metrics_sink_,
OnAction(AllOf(
HasString("name", kEvent), HasDouble("time", time.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);
const base::TimeDelta time_to_first_paint = base::TimeDelta::FromSeconds(5);
scoped_task_environment_.FastForwardBy(time_to_first_paint);
EXPECT_CALL(metrics_sink_, OnTimeEvent(AllOf(HasSubstr(kAppId1),
HasSubstr("TimeToFirstPaint")),
time_to_first_paint, _, _, _));
metrics_helper_.LogTimeToFirstPaint();
}
TEST_F(CastMetricsHelperTest, LogTimeToFirstAudio) {
metrics_helper_.DidStartLoad(kAppId1);
metrics_helper_.DidCompleteLoad(kAppId1, kSessionId1);
const base::TimeDelta time_to_first_audio = base::TimeDelta::FromSeconds(5);
scoped_task_environment_.FastForwardBy(time_to_first_audio);
EXPECT_CALL(metrics_sink_, OnTimeEvent(AllOf(HasSubstr(kAppId1),
HasSubstr("TimeToFirstAudio")),
time_to_first_audio, _, _, _));
metrics_helper_.LogTimeToFirstAudio();
}
TEST_F(CastMetricsHelperTest, MultipleApps) {
metrics_helper_.DidStartLoad(kAppId1);
scoped_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