blob: 93e1ba62de1385c45232688b338eccc21c31fa5a [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modemfwd/heartbeat_task.h"
#include <memory>
#include <utility>
#include <base/run_loop.h>
#include <base/test/task_environment.h>
#include <base/time/time.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "modemfwd/mock_daemon_delegate.h"
#include "modemfwd/mock_metrics.h"
#include "modemfwd/mock_modem.h"
using testing::_;
using testing::InSequence;
using testing::Return;
namespace {
constexpr char kModemDeviceId[] = "modem_device_id";
} // namespace
namespace modemfwd {
class HeartbeatTaskTest : public ::testing::Test {
public:
HeartbeatTaskTest() {
delegate_ = std::make_unique<MockDelegate>();
modem_ = std::make_unique<MockModem>();
metrics_ = std::make_unique<MockMetrics>();
ON_CALL(*modem_, GetDeviceId()).WillByDefault(Return(kModemDeviceId));
}
protected:
std::unique_ptr<HeartbeatTask> GetTask(HeartbeatConfig config) {
return std::make_unique<HeartbeatTask>(delegate_.get(), modem_.get(),
metrics_.get(), config);
}
void RunFor(base::TimeDelta time) {
task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
FROM_HERE, task_environment_.QuitClosure(), time);
task_environment_.RunUntilQuit();
}
// Must be the first member.
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::unique_ptr<MockDelegate> delegate_;
std::unique_ptr<MockModem> modem_;
std::unique_ptr<MockMetrics> metrics_;
};
TEST_F(HeartbeatTaskTest, HeartbeatSuccess) {
constexpr base::TimeDelta kInterval = base::Seconds(10);
constexpr int kChecks = 5;
EXPECT_CALL(*modem_, SupportsHealthCheck()).WillRepeatedly(Return(true));
EXPECT_CALL(*modem_, CheckHealth())
.Times(kChecks)
.WillRepeatedly(Return(true));
EXPECT_CALL(*delegate_, ResetModem(kModemDeviceId)).Times(0);
auto task = GetTask(HeartbeatConfig{3, kInterval});
task->Start();
RunFor((kChecks + 0.5) * kInterval);
}
TEST_F(HeartbeatTaskTest, HeartbeatFailureResetSuccess) {
constexpr base::TimeDelta kInterval = base::Seconds(10);
constexpr int kNumFailures = 3;
EXPECT_CALL(*modem_, SupportsHealthCheck()).WillRepeatedly(Return(true));
EXPECT_CALL(*modem_, CheckHealth()).WillRepeatedly(Return(false));
EXPECT_CALL(*delegate_, ResetModem(kModemDeviceId)).WillOnce(Return(true));
EXPECT_CALL(*metrics_,
SendModemRecoveryState(
metrics::ModemRecoveryState::kRecoveryStateSuccess));
auto task = GetTask(HeartbeatConfig{kNumFailures, kInterval});
task->Start();
RunFor((kNumFailures + 0.5) * kInterval);
}
TEST_F(HeartbeatTaskTest, HeartbeatFailureResetFailure) {
constexpr base::TimeDelta kInterval = base::Seconds(10);
constexpr int kNumFailures = 3;
EXPECT_CALL(*modem_, SupportsHealthCheck()).WillRepeatedly(Return(true));
EXPECT_CALL(*modem_, CheckHealth()).WillRepeatedly(Return(false));
EXPECT_CALL(*delegate_, ResetModem(kModemDeviceId)).WillOnce(Return(false));
EXPECT_CALL(*metrics_,
SendModemRecoveryState(
metrics::ModemRecoveryState::kRecoveryStateFailure));
auto task = GetTask(HeartbeatConfig{kNumFailures, kInterval});
task->Start();
RunFor((kNumFailures + 0.5) * kInterval);
}
TEST_F(HeartbeatTaskTest, HeartbeatTemporaryFailureAndRecovery) {
constexpr base::TimeDelta kInterval = base::Seconds(10);
constexpr int kNumFailures = 3;
EXPECT_CALL(*modem_, SupportsHealthCheck()).WillRepeatedly(Return(true));
{
InSequence seq;
for (int i = 0; i < kNumFailures; i++) {
EXPECT_CALL(*modem_, CheckHealth()).WillOnce(Return(false));
EXPECT_CALL(*modem_, CheckHealth()).WillOnce(Return(true));
}
}
EXPECT_CALL(*delegate_, ResetModem(kModemDeviceId)).Times(0);
auto task = GetTask(HeartbeatConfig{kNumFailures, kInterval});
task->Start();
RunFor((2 * kNumFailures + 0.5) * kInterval);
}
TEST_F(HeartbeatTaskTest, HeartbeatStopLowPowerState) {
constexpr base::TimeDelta kInterval = base::Seconds(10);
constexpr int kChecks = 3;
EXPECT_CALL(*modem_, GetPowerState())
.WillOnce(Return(Modem::PowerState::LOW));
ON_CALL(*modem_, SupportsHealthCheck()).WillByDefault(Return(true));
EXPECT_CALL(*modem_, CheckHealth()).Times(0);
auto task = GetTask(HeartbeatConfig{3, kInterval});
task->Start();
RunFor((kChecks + 0.5) * kInterval);
}
TEST_F(HeartbeatTaskTest, HeartbeatSuccessModemIdle) {
constexpr base::TimeDelta kInterval = base::Seconds(10);
constexpr base::TimeDelta kIntervalModemIdle = base::Seconds(100);
constexpr int kChecks = 5;
EXPECT_CALL(*modem_, GetPowerState())
.WillRepeatedly(Return(Modem::PowerState::ON));
EXPECT_CALL(*modem_, GetState())
.WillRepeatedly(Return(Modem::State::REGISTERED));
EXPECT_CALL(*modem_, SupportsHealthCheck()).WillRepeatedly(Return(true));
EXPECT_CALL(*modem_, CheckHealth())
.Times(kChecks)
.WillRepeatedly(Return(true));
EXPECT_CALL(*delegate_, ResetModem(kModemDeviceId)).Times(0);
auto task = GetTask(HeartbeatConfig{3, kInterval, kIntervalModemIdle});
task->Start();
RunFor((kChecks + 0.5) * kIntervalModemIdle);
}
} // namespace modemfwd