blob: 54f81e8aa5f8bacc08a1bd8cbad0a43abf12b4ab [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 "chromeos/components/tether/ble_connection_metrics_logger.h"
#include "base/memory/ptr_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace tether {
constexpr base::TimeDelta kReceiveAdvertisementTime =
base::TimeDelta::FromSeconds(1);
constexpr base::TimeDelta kStatusConnectedTime =
base::TimeDelta::FromSeconds(3);
constexpr base::TimeDelta kStatusAuthenticatedTime =
base::TimeDelta::FromSeconds(7);
static const size_t kNumFailedConnectionAttempts = 6u;
std::string kDeviceId1 = "deviceId1";
std::string kDeviceId2 = "deviceId2";
std::string kDeviceId3 = "deviceId3";
class BleConnectionMetricsLoggerTest : public testing::Test {
protected:
BleConnectionMetricsLoggerTest() {}
void SetUp() override {
ble_connection_metrics_logger_ =
base::WrapUnique(new BleConnectionMetricsLogger());
test_clock_.SetNow(base::Time::UnixEpoch());
ble_connection_metrics_logger_->SetClockForTesting(&test_clock_);
}
void AuthenticateAndDisconnectDeviceAndVerifyMetrics(
const std::string& device_id,
bool is_background_advertisement,
size_t num_previous_devices = 0u) {
size_t num_total_devices = num_previous_devices + 1;
ble_connection_metrics_logger_->OnConnectionAttemptStarted(device_id);
ReceiveAdvertisementAndAdvanceClock(device_id, is_background_advertisement);
if (is_background_advertisement) {
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration.Background",
kReceiveAdvertisementTime, num_total_devices);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration",
0);
} else {
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration.Background",
0);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration",
kReceiveAdvertisementTime, num_total_devices);
}
ConnectAndAdvanceClock(device_id, is_background_advertisement);
if (is_background_advertisement) {
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration.Background",
kStatusConnectedTime, num_total_devices);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance.StartScanToConnectionDuration."
"Background",
kReceiveAdvertisementTime + kStatusConnectedTime, num_total_devices);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration",
0);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance.AdvertisementToConnectionDuration", 0);
} else {
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration.Background",
0);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance.StartScanToConnectionDuration."
"Background",
0);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration",
kStatusConnectedTime, num_total_devices);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance.AdvertisementToConnectionDuration",
kReceiveAdvertisementTime + kStatusConnectedTime, num_total_devices);
}
CreateSecureChannelAndAdvanceClock(device_id, is_background_advertisement);
if (is_background_advertisement) {
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance.ConnectionToAuthenticationDuration."
"Background",
kStatusAuthenticatedTime, num_total_devices);
} else {
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance.ConnectionToAuthenticationDuration",
kStatusAuthenticatedTime, num_total_devices);
}
ble_connection_metrics_logger_->OnDeviceDisconnected(
device_id,
BleConnectionManager::StateChangeDetail::
STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED,
is_background_advertisement);
VerifyGattConnectionMetrics(
num_total_devices /* num_expected_successful_gatt_connections */,
0u /* num_expected_failed_gatt_connections */,
num_total_devices /* num_expected_successful_effective_gatt_connections
*/
,
0u /* num_expected_failed_effective_gatt_connections */,
is_background_advertisement);
}
void VerifyGattConnectionMetrics(
size_t num_expected_successful_gatt_connections,
size_t num_expected_failed_gatt_connections,
size_t num_expected_successful_effective_gatt_connections,
size_t num_expected_failed_effective_gatt_connections,
bool is_background_advertisement) {
if (num_expected_successful_gatt_connections > 0u) {
if (is_background_advertisement) {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt.SuccessRate.Background",
true, num_expected_successful_gatt_connections);
} else {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt.SuccessRate", true,
num_expected_successful_gatt_connections);
}
}
if (num_expected_failed_gatt_connections > 0u) {
if (is_background_advertisement) {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt.SuccessRate.Background",
false, num_expected_failed_gatt_connections);
} else {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt.SuccessRate", false,
num_expected_failed_gatt_connections);
}
}
if (num_expected_successful_gatt_connections == 0u &&
num_expected_failed_gatt_connections == 0u) {
histogram_tester_.ExpectTotalCount(
"InstantTethering.GattConnectionAttempt.SuccessRate.Background", 0u);
histogram_tester_.ExpectTotalCount(
"InstantTethering.GattConnectionAttempt.SuccessRate", 0u);
}
if (num_expected_successful_effective_gatt_connections > 0u) {
if (is_background_advertisement) {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt."
"EffectiveSuccessRateWithRetries.Background",
true, num_expected_successful_effective_gatt_connections);
} else {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt."
"EffectiveSuccessRateWithRetries",
true, num_expected_successful_effective_gatt_connections);
}
}
if (num_expected_failed_effective_gatt_connections > 0u) {
if (is_background_advertisement) {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt."
"EffectiveSuccessRateWithRetries.Background",
false, num_expected_failed_effective_gatt_connections);
} else {
histogram_tester_.ExpectBucketCount(
"InstantTethering.GattConnectionAttempt."
"EffectiveSuccessRateWithRetries",
false, num_expected_failed_effective_gatt_connections);
}
}
if (num_expected_successful_effective_gatt_connections == 0u &&
num_expected_failed_effective_gatt_connections == 0u) {
histogram_tester_.ExpectTotalCount(
"InstantTethering.GattConnectionAttempt."
"EffectiveSuccessRateWithRetries.Background",
0u);
histogram_tester_.ExpectTotalCount(
"InstantTethering.GattConnectionAttempt."
"EffectiveSuccessRateWithRetries",
0u);
}
}
void FailAllGattConnectionAttemptsAndVerifyMetrics(
const std::string& device_id,
bool is_background_advertisement) {
AttemptGattConnectionsAndThenUnregister(
device_id, kNumFailedConnectionAttempts,
false /* succeed_on_additional_last_attempt */,
is_background_advertisement);
VerifyGattConnectionMetrics(
0u /* num_expected_successful_gatt_connections */,
kNumFailedConnectionAttempts /* num_expected_failed_gatt_connections */,
0u /* num_expected_successful_effective_gatt_connections */,
1u /* num_expected_failed_effective_gatt_connections */,
is_background_advertisement);
}
void FailAlmostAllGattConnectionAttemptsAndVerifyMetrics(
const std::string& device_id,
bool is_background_advertisement) {
AttemptGattConnectionsAndThenUnregister(
device_id, kNumFailedConnectionAttempts,
true /* succeed_on_additional_last_attempt */,
is_background_advertisement);
VerifyGattConnectionMetrics(
1u /* num_expected_successful_gatt_connections */,
kNumFailedConnectionAttempts /* num_expected_failed_gatt_connections */,
1u /* num_expected_successful_effective_gatt_connections */,
0u /* num_expected_failed_effective_gatt_connections */,
is_background_advertisement);
}
void AttemptGattConnectionsAndThenUnregister(
const std::string& device_id,
size_t num_failed_connection_attempts,
bool succeed_on_additional_last_attempt,
bool is_background_advertisement) {
for (size_t i = 0u; i < num_failed_connection_attempts; ++i) {
ble_connection_metrics_logger_->OnConnectionAttemptStarted(device_id);
ReceiveAdvertisementAndAdvanceClock(device_id,
is_background_advertisement);
ble_connection_metrics_logger_->OnDeviceDisconnected(
device_id,
BleConnectionManager::StateChangeDetail::
STATE_CHANGE_DETAIL_GATT_CONNECTION_WAS_ATTEMPTED,
is_background_advertisement);
}
if (succeed_on_additional_last_attempt) {
// Now succeed on the last possible connection attempt:
ble_connection_metrics_logger_->OnConnectionAttemptStarted(device_id);
ReceiveAdvertisementAndAdvanceClock(device_id,
is_background_advertisement);
ConnectAndAdvanceClock(device_id, is_background_advertisement);
CreateSecureChannelAndAdvanceClock(device_id,
is_background_advertisement);
}
ble_connection_metrics_logger_->OnDeviceDisconnected(
device_id,
BleConnectionManager::StateChangeDetail::
STATE_CHANGE_DETAIL_DEVICE_WAS_UNREGISTERED,
is_background_advertisement);
}
void ReceiveAdvertisementAndAdvanceClock(const std::string& device_id,
bool is_background_advertisement) {
test_clock_.Advance(kReceiveAdvertisementTime);
ble_connection_metrics_logger_->OnAdvertisementReceived(
device_id, is_background_advertisement);
}
void ConnectAndAdvanceClock(const std::string& device_id,
bool is_background_advertisement) {
test_clock_.Advance(kStatusConnectedTime);
ble_connection_metrics_logger_->OnConnection(device_id,
is_background_advertisement);
}
void CreateSecureChannelAndAdvanceClock(const std::string& device_id,
bool is_background_advertisement) {
test_clock_.Advance(kStatusAuthenticatedTime);
ble_connection_metrics_logger_->OnSecureChannelCreated(
device_id, is_background_advertisement);
}
std::unique_ptr<BleConnectionMetricsLogger> ble_connection_metrics_logger_;
base::SimpleTestClock test_clock_;
base::HistogramTester histogram_tester_;
private:
DISALLOW_COPY_AND_ASSIGN(BleConnectionMetricsLoggerTest);
};
TEST_F(BleConnectionMetricsLoggerTest, TestRecordMetrics_OneDevice) {
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId1, false /* is_background_advertisement */);
}
TEST_F(BleConnectionMetricsLoggerTest, TestRecordMetrics_OneDevice_Background) {
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId1, true /* is_background_advertisement */);
}
TEST_F(BleConnectionMetricsLoggerTest, TestRecordMetrics_MultipleDevices) {
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId1, false /* is_background_advertisement */,
0u /* num_previous_devices */);
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId2, false /* is_background_advertisement */,
1u /* num_previous_devices */);
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId3, false /* is_background_advertisement */,
2u /* num_previous_devices */);
}
TEST_F(BleConnectionMetricsLoggerTest,
TestRecordMetrics_MultipleDevices_Background) {
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId1, true /* is_background_advertisement */,
0u /* num_previous_devices */);
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId2, true /* is_background_advertisement */,
1u /* num_previous_devices */);
AuthenticateAndDisconnectDeviceAndVerifyMetrics(
kDeviceId3, true /* is_background_advertisement */,
2u /* num_previous_devices */);
}
TEST_F(BleConnectionMetricsLoggerTest,
TestRecordMetrics_NeverReceiveAdvertisement) {
ble_connection_metrics_logger_->OnConnectionAttemptStarted(kDeviceId1);
ble_connection_metrics_logger_->OnDeviceDisconnected(
kDeviceId1,
BleConnectionManager::StateChangeDetail::
STATE_CHANGE_DETAIL_GATT_CONNECTION_WAS_ATTEMPTED,
false /* is_background_advertisement */);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration",
0);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration",
0);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance.AdvertisementToConnectionDuration", 0);
}
TEST_F(BleConnectionMetricsLoggerTest, TestRecordMetrics_NeverConnect) {
ble_connection_metrics_logger_->OnConnectionAttemptStarted(kDeviceId1);
ReceiveAdvertisementAndAdvanceClock(kDeviceId1,
false /* is_background_advertisement */);
ble_connection_metrics_logger_->OnDeviceDisconnected(
kDeviceId1,
BleConnectionManager::StateChangeDetail::
STATE_CHANGE_DETAIL_GATT_CONNECTION_WAS_ATTEMPTED,
false /* is_background_advertisement */);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration",
kReceiveAdvertisementTime, 1);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration",
0);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance.AdvertisementToConnectionDuration", 0);
}
TEST_F(BleConnectionMetricsLoggerTest,
TestRecordMetrics_NeverCreateSecureChannel) {
ble_connection_metrics_logger_->OnConnectionAttemptStarted(kDeviceId1);
ReceiveAdvertisementAndAdvanceClock(kDeviceId1,
false /* is_background_advertisement */);
ConnectAndAdvanceClock(kDeviceId1, false /* is_background_advertisement */);
ble_connection_metrics_logger_->OnDeviceDisconnected(
kDeviceId1,
BleConnectionManager::StateChangeDetail::
STATE_CHANGE_DETAIL_GATT_CONNECTION_WAS_ATTEMPTED,
false /* is_background_advertisement */);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"StartScanToReceiveAdvertisementDuration",
kReceiveAdvertisementTime, 1);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance."
"ReceiveAdvertisementToConnectionDuration",
kStatusConnectedTime, 1);
histogram_tester_.ExpectTimeBucketCount(
"InstantTethering.Performance.AdvertisementToConnectionDuration",
kReceiveAdvertisementTime + kStatusConnectedTime, 1);
histogram_tester_.ExpectTotalCount(
"InstantTethering.Performance.ConnectionToAuthenticationDuration", 0);
}
TEST_F(BleConnectionMetricsLoggerTest,
TestRecordMetrics_CannotCompleteGattConnection_RetryLimitReached) {
FailAllGattConnectionAttemptsAndVerifyMetrics(
kDeviceId1, false /* is_background_advertisement */);
}
TEST_F(
BleConnectionMetricsLoggerTest,
TestRecordMetrics_CannotCompleteGattConnection_RetryLimitReached_Background) {
FailAllGattConnectionAttemptsAndVerifyMetrics(
kDeviceId1, true /* is_background_advertisement */);
}
TEST_F(BleConnectionMetricsLoggerTest,
TestRecordMetrics_CompleteGattConnection_RetryLimitAlmostReached) {
FailAlmostAllGattConnectionAttemptsAndVerifyMetrics(
kDeviceId1, false /* is_background_advertisement */);
}
TEST_F(
BleConnectionMetricsLoggerTest,
TestRecordMetrics_CompleteGattConnection_RetryLimitAlmostReached_Background) {
FailAlmostAllGattConnectionAttemptsAndVerifyMetrics(
kDeviceId1, true /* is_background_advertisement */);
}
} // namespace tether
} // namespace chromeos