blob: 70d343ac015101bb607331561a8145e3a48844cd [file] [log] [blame]
//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "shill/wifi/mac80211_monitor.h"
#include <vector>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "shill/mock_event_dispatcher.h"
#include "shill/mock_log.h"
#include "shill/mock_metrics.h"
#include "shill/net/mock_time.h"
using std::string;
using std::vector;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::DoAll;
using ::testing::ElementsAre;
using ::testing::HasSubstr;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::StrictMock;
namespace shill {
namespace {
const char kTestDeviceName[] = "test-dev";
const char kJunkData[] = "junk data";
} // namespace
typedef Mac80211Monitor::QueueState QState;
class Mac80211MonitorTest : public testing::Test {
public:
Mac80211MonitorTest()
: metrics_(nullptr),
mac80211_monitor_(
&event_dispatcher_,
kTestDeviceName,
kQueueLengthLimit,
base::Bind(&Mac80211MonitorTest::OnRepairHandler,
base::Unretained(this)),
&metrics_) {
mac80211_monitor_.time_ = &time_;
}
virtual ~Mac80211MonitorTest() {}
protected:
static const size_t kQueueLengthLimit = 5;
base::FilePath fake_queue_state_file_path_; // Call FakeUpSysfs() first.
base::FilePath fake_wake_queues_file_path_; // Call FakeUpSysfs() first.
// Getters for fixture fields.
MockTime& time() { return time_; }
MockEventDispatcher& event_dispatcher() { return event_dispatcher_; }
MockMetrics& metrics() { return metrics_; }
// Complex fixture methods.
void AllowWakeQueuesIfNeededCommonCalls() {
// Allow any number of these calls, as these aspects of
// WakeQueuesIfNeeded interaction are tested elsewhere.
EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _, _))
.Times(AnyNumber());
EXPECT_CALL(metrics(), SendEnumToUMA(_, _, _))
.Times(AnyNumber());
EXPECT_CALL(metrics(), SendToUMA(_, _, _, _, _))
.Times(AnyNumber());
}
void FakeUpNotStuckState() {
FakeUpQueueFiles("00: 0x00000000/10\n");
}
void FakeUpStuckByDriverState() {
FakeUpQueueFiles("00: 0x00000001/10\n");
}
void FakeUpStuckByPowerSaveState() {
FakeUpQueueFiles("00: 0x00000002/10\n");
}
void FakeUpSysfs() {
CHECK(fake_sysfs_tree_.CreateUniqueTempDir());
CHECK(base::CreateTemporaryFileInDir(
fake_sysfs_tree_.path(), &fake_queue_state_file_path_));
CHECK(base::CreateTemporaryFileInDir(
fake_sysfs_tree_.path(), &fake_wake_queues_file_path_));
PlumbFakeSysfs();
}
void DeleteQueueStateFile() {
fake_queue_state_file_path_.clear();
PlumbFakeSysfs();
}
bool IsRunning() const {
return mac80211_monitor_.is_running_ &&
!mac80211_monitor_.check_queues_callback_.IsCancelled();
}
bool IsStopped() const {
return !mac80211_monitor_.is_running_ &&
mac80211_monitor_.check_queues_callback_.IsCancelled();
}
bool IsWakeQueuesFileModified() const {
CHECK(fake_sysfs_tree_.IsValid()); // Keep tests hermetic.
string wake_file_contents;
base::ReadFileToString(fake_wake_queues_file_path_, &wake_file_contents);
return wake_file_contents != kJunkData;
}
MOCK_METHOD0(OnRepairHandler, void());
// Getters for Mac80211Monitor state.
bool GetIsDeviceConnected() const {
return mac80211_monitor_.is_device_connected_;
}
time_t GetLastWokeQueuesMonotonicSeconds() const {
return mac80211_monitor_.last_woke_queues_monotonic_seconds_;
}
const string& GetLinkName() const {
return mac80211_monitor_.link_name_;
}
time_t GetMinimumTimeBetweenWakesSeconds() const {
return Mac80211Monitor::kMinimumTimeBetweenWakesSeconds;
}
const string& GetPhyName() const {
return mac80211_monitor_.phy_name_;
}
const base::FilePath& GetQueueStateFilePath() const {
return mac80211_monitor_.queue_state_file_path_;
}
const base::FilePath& GetWakeQueuesFilePath() const {
return mac80211_monitor_.wake_queues_file_path_;
}
// Pass-through methods to Mac80211Monitor methods.
void StartMonitor(const string& phy_name) {
EXPECT_CALL(
event_dispatcher_,
PostDelayedTask(
_, _, Mac80211Monitor::kQueueStatePollIntervalSeconds * 1000));
mac80211_monitor_.Start(phy_name);
if (fake_sysfs_tree_.IsValid()) {
PlumbFakeSysfs(); // Re-plumb, since un-plumbed by Start().
}
}
void StopMonitor() {
mac80211_monitor_.Stop();
}
uint32_t CheckAreQueuesStuck(const vector<QState>& queue_states) {
return mac80211_monitor_.CheckAreQueuesStuck(queue_states);
}
void UpdateConnectedState(bool new_state) {
mac80211_monitor_.UpdateConnectedState(new_state);
}
void WakeQueuesIfNeeded() {
CHECK(fake_sysfs_tree_.IsValid()); // Keep tests hermetic.
mac80211_monitor_.WakeQueuesIfNeeded();
}
private:
base::ScopedTempDir fake_sysfs_tree_; // Call FakeUpSysfs() first.
StrictMock<MockEventDispatcher> event_dispatcher_;
StrictMock<MockMetrics> metrics_;
StrictMock<MockTime> time_;
Mac80211Monitor mac80211_monitor_;
void FakeUpQueueFiles(const string& queue_state_string) {
CHECK(fake_sysfs_tree_.IsValid()); // Keep tests hermetic.
base::WriteFile(fake_queue_state_file_path_,
queue_state_string.c_str(),
queue_state_string.length());
ASSERT_TRUE(base::WriteFile(fake_wake_queues_file_path_,
kJunkData, strlen(kJunkData)));
}
void PlumbFakeSysfs() {
mac80211_monitor_.queue_state_file_path_ = fake_queue_state_file_path_;
mac80211_monitor_.wake_queues_file_path_ = fake_wake_queues_file_path_;
}
};
// Can't be in an anonymous namespace, due to ADL.
// Instead, we use static to constain visibility to this unit.
static bool operator==(const QState& a, const QState& b) {
return a.queue_number == b.queue_number &&
a.stop_flags == b.stop_flags &&
a.queue_length == b.queue_length;
}
TEST_F(Mac80211MonitorTest, Ctor) {
EXPECT_TRUE(IsStopped());
EXPECT_EQ(kTestDeviceName, GetLinkName());
}
TEST_F(Mac80211MonitorTest, Start) {
StartMonitor("test-phy");
EXPECT_TRUE(IsRunning());
EXPECT_EQ("test-phy", GetPhyName());
EXPECT_EQ("/sys/kernel/debug/ieee80211/test-phy/queues",
GetQueueStateFilePath().value());
EXPECT_EQ("/sys/kernel/debug/ieee80211/test-phy/wake_queues",
GetWakeQueuesFilePath().value());
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
}
TEST_F(Mac80211MonitorTest, Stop) {
StartMonitor("dont-care-phy");
EXPECT_TRUE(IsRunning());
StopMonitor();
EXPECT_TRUE(IsStopped());
}
TEST_F(Mac80211MonitorTest, UpdateConnectedState) {
UpdateConnectedState(false);
EXPECT_FALSE(GetIsDeviceConnected());
UpdateConnectedState(true);
EXPECT_TRUE(GetIsDeviceConnected());
// Initial state was unknown. Ensure that we can move from true to false.
UpdateConnectedState(false);
EXPECT_FALSE(GetIsDeviceConnected());
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededFullMacDevice) {
FakeUpSysfs();
StartMonitor("dont-care-phy");
UpdateConnectedState(false);
EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _, _));
ScopedMockLog log;
EXPECT_CALL(log, Log(_, _, HasSubstr(": incomplete read on "))).Times(0);
// In case of using device with Full-Mac support,
// there is no queue state file in debugfs.
DeleteQueueStateFile();
WakeQueuesIfNeeded();
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRearmsTimerWhenDisconnected) {
FakeUpSysfs();
StartMonitor("dont-care-phy");
UpdateConnectedState(false);
EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _, _));
WakeQueuesIfNeeded();
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededFailToReadQueueState) {
FakeUpSysfs();
StartMonitor("dont-care-phy");
UpdateConnectedState(false);
AllowWakeQueuesIfNeededCommonCalls();
WakeQueuesIfNeeded();
// In case we succeeded reading queue state before, but fail this time.
ScopedMockLog log;
EXPECT_CALL(log, Log(_, _, HasSubstr(": incomplete read on "))).Times(1);
DeleteQueueStateFile();
WakeQueuesIfNeeded();
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRearmsTimerWhenConnected) {
FakeUpSysfs();
StartMonitor("dont-care-phy");
UpdateConnectedState(true);
EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _, _));
WakeQueuesIfNeeded();
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededWakeNeeded) {
FakeUpSysfs();
FakeUpStuckByPowerSaveState();
StartMonitor("dont-care-phy");
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
const time_t kNowMonotonicSeconds = GetMinimumTimeBetweenWakesSeconds();
EXPECT_CALL(time(), GetSecondsMonotonic(_))
.WillOnce(DoAll(SetArgumentPointee<0>(kNowMonotonicSeconds),
Return(true)));
EXPECT_CALL(*this, OnRepairHandler());
AllowWakeQueuesIfNeededCommonCalls();
WakeQueuesIfNeeded();
EXPECT_EQ(kNowMonotonicSeconds, GetLastWokeQueuesMonotonicSeconds());
EXPECT_TRUE(IsWakeQueuesFileModified());
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRateLimiting) {
FakeUpSysfs();
FakeUpStuckByPowerSaveState();
StartMonitor("dont-care-phy");
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
EXPECT_CALL(time(), GetSecondsMonotonic(_))
.WillOnce(DoAll(
SetArgumentPointee<0>(GetMinimumTimeBetweenWakesSeconds() - 1),
Return(true)));
EXPECT_CALL(*this, OnRepairHandler()).Times(0);
AllowWakeQueuesIfNeededCommonCalls();
WakeQueuesIfNeeded();
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
EXPECT_FALSE(IsWakeQueuesFileModified());
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededNotStuck) {
FakeUpSysfs();
FakeUpNotStuckState();
StartMonitor("dont-care-phy");
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
EXPECT_CALL(*this, OnRepairHandler()).Times(0);
AllowWakeQueuesIfNeededCommonCalls();
WakeQueuesIfNeeded();
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
EXPECT_FALSE(IsWakeQueuesFileModified());
}
TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededStuckByDriver) {
FakeUpSysfs();
FakeUpStuckByDriverState();
StartMonitor("dont-care-phy");
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
EXPECT_CALL(*this, OnRepairHandler()).Times(0);
AllowWakeQueuesIfNeededCommonCalls();
WakeQueuesIfNeeded();
EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
EXPECT_FALSE(IsWakeQueuesFileModified());
}
TEST_F(Mac80211MonitorTest, ParseQueueStateSimple) {
// Single queue.
EXPECT_THAT(Mac80211Monitor::ParseQueueState("00: 0x00000000/0\n"),
ElementsAre(QState(0, 0, 0)));
// Multiple queues, non-empty.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState(
"00: 0x00000000/10\n"
"01: 0x00000000/20\n"),
ElementsAre(QState(0, 0, 10), QState(1, 0, 20)));
}
TEST_F(Mac80211MonitorTest, ParseQueueStateStopped) {
// Single queue, stopped for various reasons.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x00000001/10\n"),
ElementsAre(QState(0, Mac80211Monitor::kStopFlagDriver, 10)));
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x00000003/10\n"),
ElementsAre(QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave,
10)));
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x00000007/10\n"),
ElementsAre(QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch,
10)));
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x0000000f/10\n"),
ElementsAre(QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch |
Mac80211Monitor::kStopFlagAggregation,
10)));
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x0000001f/10\n"),
ElementsAre(QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch |
Mac80211Monitor::kStopFlagAggregation |
Mac80211Monitor::kStopFlagSuspend,
10)));
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x0000003f/10\n"),
ElementsAre(QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch |
Mac80211Monitor::kStopFlagAggregation |
Mac80211Monitor::kStopFlagSuspend |
Mac80211Monitor::kStopFlagBufferAdd,
10)));
EXPECT_THAT(
Mac80211Monitor::ParseQueueState("00: 0x0000007f/10\n"),
ElementsAre(QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch |
Mac80211Monitor::kStopFlagAggregation |
Mac80211Monitor::kStopFlagSuspend |
Mac80211Monitor::kStopFlagBufferAdd |
Mac80211Monitor::kStopFlagChannelTypeChange,
10)));
}
TEST_F(Mac80211MonitorTest, ParseQueueStateBadInput) {
// Empty input -> Empty output.
EXPECT_TRUE(Mac80211Monitor::ParseQueueState("").empty());
// Missing queue length for queue 0.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState(
"00: 0x00000000\n"
"01: 0xffffffff/10\n"),
ElementsAre(QState(1, 0xffffffff, 10)));
// Missing flags for queue 0.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState(
"00: 0\n"
"01: 0xffffffff/10\n"),
ElementsAre(QState(1, 0xffffffff, 10)));
// Bad number for queue 0.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState(
"aa: 0xabcdefgh/0\n"
"01: 0xffffffff/10\n"),
ElementsAre(QState(1, 0xffffffff, 10)));
// Bad flags for queue 0.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState(
"00: 0xabcdefgh/0\n"
"01: 0xffffffff/10\n"),
ElementsAre(QState(1, 0xffffffff, 10)));
// Bad length for queue 0.
EXPECT_THAT(
Mac80211Monitor::ParseQueueState(
"00: 0x00000000/-1\n"
"01: 0xffffffff/10\n"),
ElementsAre(QState(1, 0xffffffff, 10)));
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckNotStuck) {
EXPECT_FALSE(CheckAreQueuesStuck({}));
EXPECT_FALSE(CheckAreQueuesStuck({QState(0, 0, 0)}));
// Not stuck when queue length is below limit.
EXPECT_FALSE(CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1)}));
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckSingleReason) {
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonDriver,
Mac80211Monitor::kStopReasonMax));
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonPowerSave,
Mac80211Monitor::kStopReasonMax));
EXPECT_CALL(metrics(), SendToUMA(
Metrics::kMetricWifiStoppedTxQueueLength,
kQueueLengthLimit,
Metrics::kMetricWifiStoppedTxQueueLengthMin,
Metrics::kMetricWifiStoppedTxQueueLengthMax,
Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(2);
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagDriver,
kQueueLengthLimit)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit)}));
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckMultipleReasons) {
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonPowerSave,
Mac80211Monitor::kStopReasonMax)).Times(2);
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonDriver,
Mac80211Monitor::kStopReasonMax)).Times(2);
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonChannelSwitch,
Mac80211Monitor::kStopReasonMax)).Times(2);
EXPECT_CALL(metrics(), SendToUMA(
Metrics::kMetricWifiStoppedTxQueueLength,
kQueueLengthLimit,
Metrics::kMetricWifiStoppedTxQueueLengthMin,
Metrics::kMetricWifiStoppedTxQueueLengthMax,
Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(3);
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagPowerSave |
Mac80211Monitor::kStopFlagChannelSwitch,
kQueueLengthLimit)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagChannelSwitch,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagChannelSwitch,
kQueueLengthLimit)}));
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckMultipleQueues) {
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonPowerSave,
Mac80211Monitor::kStopReasonMax)).Times(5);
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonDriver,
Mac80211Monitor::kStopReasonMax)).Times(2);
EXPECT_CALL(metrics(), SendToUMA(
Metrics::kMetricWifiStoppedTxQueueLength,
kQueueLengthLimit,
Metrics::kMetricWifiStoppedTxQueueLengthMin,
Metrics::kMetricWifiStoppedTxQueueLengthMax,
Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(5);
EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0, 0, 0),
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit),
QState(0, 0, 0)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit),
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit),
QState(0,
Mac80211Monitor::kStopFlagDriver,
kQueueLengthLimit)}));
EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
Mac80211Monitor::kStopFlagPowerSave,
CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagDriver, kQueueLengthLimit),
QState(0,
Mac80211Monitor::kStopFlagPowerSave,
kQueueLengthLimit)}));
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckQueueLength) {
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonPowerSave,
Mac80211Monitor::kStopReasonMax)).Times(4);
EXPECT_CALL(metrics(), SendToUMA(
Metrics::kMetricWifiStoppedTxQueueLength,
kQueueLengthLimit,
Metrics::kMetricWifiStoppedTxQueueLengthMin,
Metrics::kMetricWifiStoppedTxQueueLengthMax,
Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(4);
EXPECT_TRUE(CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
EXPECT_TRUE(CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
EXPECT_TRUE(CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2)}));
EXPECT_TRUE(CheckAreQueuesStuck({
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2)}));
}
TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckQueueLengthIgnoresUnstopped) {
EXPECT_CALL(metrics(), SendEnumToUMA(
Metrics::kMetricWifiStoppedTxQueueReason,
Mac80211Monitor::kStopReasonPowerSave,
Mac80211Monitor::kStopReasonMax));
EXPECT_CALL(metrics(), SendToUMA(
Metrics::kMetricWifiStoppedTxQueueLength,
kQueueLengthLimit,
Metrics::kMetricWifiStoppedTxQueueLengthMin,
Metrics::kMetricWifiStoppedTxQueueLengthMax,
Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets));
EXPECT_TRUE(CheckAreQueuesStuck({
QState(0, 0, kQueueLengthLimit * 10),
QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
}
} // namespace shill