Home | History | Annotate | Download | only in wifi
      1 //
      2 // Copyright (C) 2014 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/wifi/mac80211_monitor.h"
     18 
     19 #include <vector>
     20 
     21 #include <base/files/file_util.h>
     22 #include <base/files/scoped_temp_dir.h>
     23 #include <gmock/gmock.h>
     24 #include <gtest/gtest.h>
     25 
     26 #include "shill/mock_event_dispatcher.h"
     27 #include "shill/mock_log.h"
     28 #include "shill/mock_metrics.h"
     29 #include "shill/net/mock_time.h"
     30 
     31 using std::string;
     32 using std::vector;
     33 using ::testing::_;
     34 using ::testing::AnyNumber;
     35 using ::testing::DoAll;
     36 using ::testing::ElementsAre;
     37 using ::testing::HasSubstr;
     38 using ::testing::Return;
     39 using ::testing::SetArgumentPointee;
     40 using ::testing::StrictMock;
     41 
     42 namespace shill {
     43 
     44 namespace {
     45 
     46 const char kTestDeviceName[] = "test-dev";
     47 const char kJunkData[] = "junk data";
     48 
     49 }  // namespace
     50 
     51 typedef Mac80211Monitor::QueueState QState;
     52 
     53 class Mac80211MonitorTest : public testing::Test {
     54  public:
     55   Mac80211MonitorTest()
     56       : metrics_(nullptr),
     57         mac80211_monitor_(
     58             &event_dispatcher_,
     59             kTestDeviceName,
     60             kQueueLengthLimit,
     61             base::Bind(&Mac80211MonitorTest::OnRepairHandler,
     62                        base::Unretained(this)),
     63             &metrics_) {
     64     mac80211_monitor_.time_ = &time_;
     65   }
     66   virtual ~Mac80211MonitorTest() {}
     67 
     68  protected:
     69   static const size_t kQueueLengthLimit = 5;
     70   base::FilePath fake_queue_state_file_path_;  // Call FakeUpSysfs() first.
     71   base::FilePath fake_wake_queues_file_path_;  // Call FakeUpSysfs() first.
     72 
     73   // Getters for fixture fields.
     74   MockTime& time() { return time_; }
     75   MockEventDispatcher& event_dispatcher() { return event_dispatcher_; }
     76   MockMetrics& metrics() { return metrics_; }
     77 
     78   // Complex fixture methods.
     79   void AllowWakeQueuesIfNeededCommonCalls() {
     80     // Allow any number of these calls, as these aspects of
     81     // WakeQueuesIfNeeded interaction are tested elsewhere.
     82     EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _))
     83         .Times(AnyNumber());
     84     EXPECT_CALL(metrics(), SendEnumToUMA(_, _, _))
     85         .Times(AnyNumber());
     86     EXPECT_CALL(metrics(), SendToUMA(_, _, _, _, _))
     87         .Times(AnyNumber());
     88   }
     89   void FakeUpNotStuckState() {
     90     FakeUpQueueFiles("00: 0x00000000/10\n");
     91   }
     92   void FakeUpStuckByDriverState() {
     93     FakeUpQueueFiles("00: 0x00000001/10\n");
     94   }
     95   void FakeUpStuckByPowerSaveState() {
     96     FakeUpQueueFiles("00: 0x00000002/10\n");
     97   }
     98   void FakeUpSysfs() {
     99     CHECK(fake_sysfs_tree_.CreateUniqueTempDir());
    100     CHECK(base::CreateTemporaryFileInDir(
    101         fake_sysfs_tree_.path(), &fake_queue_state_file_path_));
    102     CHECK(base::CreateTemporaryFileInDir(
    103         fake_sysfs_tree_.path(), &fake_wake_queues_file_path_));
    104     PlumbFakeSysfs();
    105   }
    106   void DeleteQueueStateFile() {
    107     fake_queue_state_file_path_.clear();
    108     PlumbFakeSysfs();
    109   }
    110   bool IsRunning() const {
    111     return mac80211_monitor_.is_running_ &&
    112         !mac80211_monitor_.check_queues_callback_.IsCancelled();
    113   }
    114   bool IsStopped() const {
    115     return !mac80211_monitor_.is_running_ &&
    116         mac80211_monitor_.check_queues_callback_.IsCancelled();
    117   }
    118   bool IsWakeQueuesFileModified() const {
    119     CHECK(fake_sysfs_tree_.IsValid());  // Keep tests hermetic.
    120     string wake_file_contents;
    121     base::ReadFileToString(fake_wake_queues_file_path_, &wake_file_contents);
    122     return wake_file_contents != kJunkData;
    123   }
    124   MOCK_METHOD0(OnRepairHandler, void());
    125 
    126   // Getters for Mac80211Monitor state.
    127   bool GetIsDeviceConnected() const {
    128     return mac80211_monitor_.is_device_connected_;
    129   }
    130   time_t GetLastWokeQueuesMonotonicSeconds() const {
    131     return mac80211_monitor_.last_woke_queues_monotonic_seconds_;
    132   }
    133   const string& GetLinkName() const {
    134     return mac80211_monitor_.link_name_;
    135   }
    136   time_t GetMinimumTimeBetweenWakesSeconds() const {
    137     return Mac80211Monitor::kMinimumTimeBetweenWakesSeconds;
    138   }
    139   const string& GetPhyName() const {
    140     return mac80211_monitor_.phy_name_;
    141   }
    142   const base::FilePath& GetQueueStateFilePath() const {
    143     return mac80211_monitor_.queue_state_file_path_;
    144   }
    145   const base::FilePath& GetWakeQueuesFilePath() const {
    146     return mac80211_monitor_.wake_queues_file_path_;
    147   }
    148 
    149   // Pass-through methods to Mac80211Monitor methods.
    150   void StartMonitor(const string& phy_name) {
    151     EXPECT_CALL(
    152         event_dispatcher_,
    153         PostDelayedTask(
    154             _, Mac80211Monitor::kQueueStatePollIntervalSeconds * 1000));
    155     mac80211_monitor_.Start(phy_name);
    156     if (fake_sysfs_tree_.IsValid()) {
    157       PlumbFakeSysfs();  // Re-plumb, since un-plumbed by Start().
    158     }
    159   }
    160   void StopMonitor() {
    161     mac80211_monitor_.Stop();
    162   }
    163   uint32_t CheckAreQueuesStuck(const vector<QState>& queue_states) {
    164     return mac80211_monitor_.CheckAreQueuesStuck(queue_states);
    165   }
    166   void UpdateConnectedState(bool new_state) {
    167     mac80211_monitor_.UpdateConnectedState(new_state);
    168   }
    169   void WakeQueuesIfNeeded() {
    170     CHECK(fake_sysfs_tree_.IsValid());  // Keep tests hermetic.
    171     mac80211_monitor_.WakeQueuesIfNeeded();
    172   }
    173 
    174  private:
    175   base::ScopedTempDir fake_sysfs_tree_;  // Call FakeUpSysfs() first.
    176   StrictMock<MockEventDispatcher> event_dispatcher_;
    177   StrictMock<MockMetrics> metrics_;
    178   StrictMock<MockTime> time_;
    179   Mac80211Monitor mac80211_monitor_;
    180 
    181   void FakeUpQueueFiles(const string& queue_state_string) {
    182     CHECK(fake_sysfs_tree_.IsValid());  // Keep tests hermetic.
    183     base::WriteFile(fake_queue_state_file_path_,
    184                     queue_state_string.c_str(),
    185                     queue_state_string.length());
    186     ASSERT_TRUE(base::WriteFile(fake_wake_queues_file_path_,
    187                                 kJunkData, strlen(kJunkData)));
    188   }
    189   void PlumbFakeSysfs() {
    190     mac80211_monitor_.queue_state_file_path_ = fake_queue_state_file_path_;
    191     mac80211_monitor_.wake_queues_file_path_ = fake_wake_queues_file_path_;
    192   }
    193 };
    194 
    195 // Can't be in an anonymous namespace, due to ADL.
    196 // Instead, we use static to constain visibility to this unit.
    197 static bool operator==(const QState& a, const QState& b) {
    198   return a.queue_number == b.queue_number &&
    199       a.stop_flags == b.stop_flags &&
    200       a.queue_length == b.queue_length;
    201 }
    202 
    203 TEST_F(Mac80211MonitorTest, Ctor) {
    204   EXPECT_TRUE(IsStopped());
    205   EXPECT_EQ(kTestDeviceName, GetLinkName());
    206 }
    207 
    208 TEST_F(Mac80211MonitorTest, Start) {
    209   StartMonitor("test-phy");
    210   EXPECT_TRUE(IsRunning());
    211   EXPECT_EQ("test-phy", GetPhyName());
    212   EXPECT_EQ("/sys/kernel/debug/ieee80211/test-phy/queues",
    213             GetQueueStateFilePath().value());
    214   EXPECT_EQ("/sys/kernel/debug/ieee80211/test-phy/wake_queues",
    215             GetWakeQueuesFilePath().value());
    216   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    217 }
    218 
    219 TEST_F(Mac80211MonitorTest, Stop) {
    220   StartMonitor("dont-care-phy");
    221   EXPECT_TRUE(IsRunning());
    222   StopMonitor();
    223   EXPECT_TRUE(IsStopped());
    224 }
    225 
    226 TEST_F(Mac80211MonitorTest, UpdateConnectedState) {
    227   UpdateConnectedState(false);
    228   EXPECT_FALSE(GetIsDeviceConnected());
    229 
    230   UpdateConnectedState(true);
    231   EXPECT_TRUE(GetIsDeviceConnected());
    232 
    233   // Initial state was unknown. Ensure that we can move from true to false.
    234   UpdateConnectedState(false);
    235   EXPECT_FALSE(GetIsDeviceConnected());
    236 }
    237 
    238 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededFullMacDevice) {
    239   FakeUpSysfs();
    240   StartMonitor("dont-care-phy");
    241   UpdateConnectedState(false);
    242   EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _));
    243   ScopedMockLog log;
    244   EXPECT_CALL(log, Log(_, _, HasSubstr(": incomplete read on "))).Times(0);
    245 
    246   // In case of using device with Full-Mac support,
    247   // there is no queue state file in debugfs.
    248   DeleteQueueStateFile();
    249   WakeQueuesIfNeeded();
    250 }
    251 
    252 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRearmsTimerWhenDisconnected) {
    253   FakeUpSysfs();
    254   StartMonitor("dont-care-phy");
    255   UpdateConnectedState(false);
    256   EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _));
    257   WakeQueuesIfNeeded();
    258 }
    259 
    260 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededFailToReadQueueState) {
    261   FakeUpSysfs();
    262   StartMonitor("dont-care-phy");
    263   UpdateConnectedState(false);
    264   AllowWakeQueuesIfNeededCommonCalls();
    265   WakeQueuesIfNeeded();
    266 
    267   // In case we succeeded reading queue state before, but fail this time.
    268   ScopedMockLog log;
    269   EXPECT_CALL(log, Log(_, _, HasSubstr(": incomplete read on "))).Times(1);
    270   DeleteQueueStateFile();
    271   WakeQueuesIfNeeded();
    272 }
    273 
    274 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRearmsTimerWhenConnected) {
    275   FakeUpSysfs();
    276   StartMonitor("dont-care-phy");
    277   UpdateConnectedState(true);
    278   EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _));
    279   WakeQueuesIfNeeded();
    280 }
    281 
    282 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededWakeNeeded) {
    283   FakeUpSysfs();
    284   FakeUpStuckByPowerSaveState();
    285   StartMonitor("dont-care-phy");
    286   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    287 
    288   const time_t kNowMonotonicSeconds = GetMinimumTimeBetweenWakesSeconds();
    289   EXPECT_CALL(time(), GetSecondsMonotonic(_))
    290       .WillOnce(DoAll(SetArgumentPointee<0>(kNowMonotonicSeconds),
    291                       Return(true)));
    292   EXPECT_CALL(*this, OnRepairHandler());
    293   AllowWakeQueuesIfNeededCommonCalls();
    294   WakeQueuesIfNeeded();
    295 
    296   EXPECT_EQ(kNowMonotonicSeconds, GetLastWokeQueuesMonotonicSeconds());
    297   EXPECT_TRUE(IsWakeQueuesFileModified());
    298 }
    299 
    300 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRateLimiting) {
    301   FakeUpSysfs();
    302   FakeUpStuckByPowerSaveState();
    303   StartMonitor("dont-care-phy");
    304   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    305 
    306   EXPECT_CALL(time(), GetSecondsMonotonic(_))
    307       .WillOnce(DoAll(
    308           SetArgumentPointee<0>(GetMinimumTimeBetweenWakesSeconds() - 1),
    309           Return(true)));
    310   EXPECT_CALL(*this, OnRepairHandler()).Times(0);
    311   AllowWakeQueuesIfNeededCommonCalls();
    312   WakeQueuesIfNeeded();
    313 
    314   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    315   EXPECT_FALSE(IsWakeQueuesFileModified());
    316 }
    317 
    318 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededNotStuck) {
    319   FakeUpSysfs();
    320   FakeUpNotStuckState();
    321   StartMonitor("dont-care-phy");
    322   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    323 
    324   EXPECT_CALL(*this, OnRepairHandler()).Times(0);
    325   AllowWakeQueuesIfNeededCommonCalls();
    326   WakeQueuesIfNeeded();
    327 
    328   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    329   EXPECT_FALSE(IsWakeQueuesFileModified());
    330 }
    331 
    332 TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededStuckByDriver) {
    333   FakeUpSysfs();
    334   FakeUpStuckByDriverState();
    335   StartMonitor("dont-care-phy");
    336   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    337 
    338   EXPECT_CALL(*this, OnRepairHandler()).Times(0);
    339   AllowWakeQueuesIfNeededCommonCalls();
    340   WakeQueuesIfNeeded();
    341 
    342   EXPECT_EQ(0, GetLastWokeQueuesMonotonicSeconds());
    343   EXPECT_FALSE(IsWakeQueuesFileModified());
    344 }
    345 
    346 TEST_F(Mac80211MonitorTest, ParseQueueStateSimple) {
    347   // Single queue.
    348   EXPECT_THAT(Mac80211Monitor::ParseQueueState("00: 0x00000000/0\n"),
    349               ElementsAre(QState(0, 0, 0)));
    350 
    351   // Multiple queues, non-empty.
    352   EXPECT_THAT(
    353       Mac80211Monitor::ParseQueueState(
    354           "00: 0x00000000/10\n"
    355           "01: 0x00000000/20\n"),
    356       ElementsAre(QState(0, 0, 10), QState(1, 0, 20)));
    357 }
    358 
    359 TEST_F(Mac80211MonitorTest, ParseQueueStateStopped) {
    360   // Single queue, stopped for various reasons.
    361   EXPECT_THAT(
    362       Mac80211Monitor::ParseQueueState("00: 0x00000001/10\n"),
    363       ElementsAre(QState(0, Mac80211Monitor::kStopFlagDriver, 10)));
    364   EXPECT_THAT(
    365       Mac80211Monitor::ParseQueueState("00: 0x00000003/10\n"),
    366       ElementsAre(QState(0,
    367                          Mac80211Monitor::kStopFlagDriver |
    368                          Mac80211Monitor::kStopFlagPowerSave,
    369                          10)));
    370   EXPECT_THAT(
    371       Mac80211Monitor::ParseQueueState("00: 0x00000007/10\n"),
    372       ElementsAre(QState(0,
    373                          Mac80211Monitor::kStopFlagDriver |
    374                          Mac80211Monitor::kStopFlagPowerSave |
    375                          Mac80211Monitor::kStopFlagChannelSwitch,
    376                          10)));
    377   EXPECT_THAT(
    378       Mac80211Monitor::ParseQueueState("00: 0x0000000f/10\n"),
    379       ElementsAre(QState(0,
    380                          Mac80211Monitor::kStopFlagDriver |
    381                          Mac80211Monitor::kStopFlagPowerSave |
    382                          Mac80211Monitor::kStopFlagChannelSwitch |
    383                          Mac80211Monitor::kStopFlagAggregation,
    384                          10)));
    385   EXPECT_THAT(
    386       Mac80211Monitor::ParseQueueState("00: 0x0000001f/10\n"),
    387       ElementsAre(QState(0,
    388                          Mac80211Monitor::kStopFlagDriver |
    389                          Mac80211Monitor::kStopFlagPowerSave |
    390                          Mac80211Monitor::kStopFlagChannelSwitch |
    391                          Mac80211Monitor::kStopFlagAggregation |
    392                          Mac80211Monitor::kStopFlagSuspend,
    393                          10)));
    394   EXPECT_THAT(
    395       Mac80211Monitor::ParseQueueState("00: 0x0000003f/10\n"),
    396       ElementsAre(QState(0,
    397                          Mac80211Monitor::kStopFlagDriver |
    398                          Mac80211Monitor::kStopFlagPowerSave |
    399                          Mac80211Monitor::kStopFlagChannelSwitch |
    400                          Mac80211Monitor::kStopFlagAggregation |
    401                          Mac80211Monitor::kStopFlagSuspend |
    402                          Mac80211Monitor::kStopFlagBufferAdd,
    403                          10)));
    404   EXPECT_THAT(
    405       Mac80211Monitor::ParseQueueState("00: 0x0000007f/10\n"),
    406       ElementsAre(QState(0,
    407                          Mac80211Monitor::kStopFlagDriver |
    408                          Mac80211Monitor::kStopFlagPowerSave |
    409                          Mac80211Monitor::kStopFlagChannelSwitch |
    410                          Mac80211Monitor::kStopFlagAggregation |
    411                          Mac80211Monitor::kStopFlagSuspend |
    412                          Mac80211Monitor::kStopFlagBufferAdd |
    413                          Mac80211Monitor::kStopFlagChannelTypeChange,
    414                          10)));
    415 }
    416 
    417 TEST_F(Mac80211MonitorTest, ParseQueueStateBadInput) {
    418   // Empty input -> Empty output.
    419   EXPECT_TRUE(Mac80211Monitor::ParseQueueState("").empty());
    420 
    421   // Missing queue length for queue 0.
    422   EXPECT_THAT(
    423       Mac80211Monitor::ParseQueueState(
    424           "00: 0x00000000\n"
    425           "01: 0xffffffff/10\n"),
    426       ElementsAre(QState(1, 0xffffffff, 10)));
    427 
    428   // Missing flags for queue 0.
    429   EXPECT_THAT(
    430       Mac80211Monitor::ParseQueueState(
    431           "00: 0\n"
    432           "01: 0xffffffff/10\n"),
    433       ElementsAre(QState(1, 0xffffffff, 10)));
    434 
    435   // Bad number for queue 0.
    436   EXPECT_THAT(
    437       Mac80211Monitor::ParseQueueState(
    438           "aa: 0xabcdefgh/0\n"
    439           "01: 0xffffffff/10\n"),
    440       ElementsAre(QState(1, 0xffffffff, 10)));
    441 
    442   // Bad flags for queue 0.
    443   EXPECT_THAT(
    444       Mac80211Monitor::ParseQueueState(
    445           "00: 0xabcdefgh/0\n"
    446           "01: 0xffffffff/10\n"),
    447       ElementsAre(QState(1, 0xffffffff, 10)));
    448 
    449   // Bad length for queue 0.
    450   EXPECT_THAT(
    451       Mac80211Monitor::ParseQueueState(
    452           "00: 0x00000000/-1\n"
    453           "01: 0xffffffff/10\n"),
    454       ElementsAre(QState(1, 0xffffffff, 10)));
    455 }
    456 
    457 TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckNotStuck) {
    458   EXPECT_FALSE(CheckAreQueuesStuck({}));
    459   EXPECT_FALSE(CheckAreQueuesStuck({QState(0, 0, 0)}));
    460   // Not stuck when queue length is below limit.
    461   EXPECT_FALSE(CheckAreQueuesStuck({
    462         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1)}));
    463 }
    464 
    465 TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckSingleReason) {
    466   EXPECT_CALL(metrics(), SendEnumToUMA(
    467       Metrics::kMetricWifiStoppedTxQueueReason,
    468       Mac80211Monitor::kStopReasonDriver,
    469       Mac80211Monitor::kStopReasonMax));
    470   EXPECT_CALL(metrics(), SendEnumToUMA(
    471       Metrics::kMetricWifiStoppedTxQueueReason,
    472       Mac80211Monitor::kStopReasonPowerSave,
    473       Mac80211Monitor::kStopReasonMax));
    474   EXPECT_CALL(metrics(), SendToUMA(
    475       Metrics::kMetricWifiStoppedTxQueueLength,
    476       kQueueLengthLimit,
    477       Metrics::kMetricWifiStoppedTxQueueLengthMin,
    478       Metrics::kMetricWifiStoppedTxQueueLengthMax,
    479       Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(2);
    480   EXPECT_EQ(Mac80211Monitor::kStopFlagDriver,
    481             CheckAreQueuesStuck({
    482                 QState(0,
    483                        Mac80211Monitor::kStopFlagDriver,
    484                        kQueueLengthLimit)}));
    485   EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
    486             CheckAreQueuesStuck({
    487                 QState(0,
    488                        Mac80211Monitor::kStopFlagPowerSave,
    489                        kQueueLengthLimit)}));
    490 }
    491 
    492 TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckMultipleReasons) {
    493   EXPECT_CALL(metrics(), SendEnumToUMA(
    494       Metrics::kMetricWifiStoppedTxQueueReason,
    495       Mac80211Monitor::kStopReasonPowerSave,
    496       Mac80211Monitor::kStopReasonMax)).Times(2);
    497   EXPECT_CALL(metrics(), SendEnumToUMA(
    498       Metrics::kMetricWifiStoppedTxQueueReason,
    499       Mac80211Monitor::kStopReasonDriver,
    500       Mac80211Monitor::kStopReasonMax)).Times(2);
    501   EXPECT_CALL(metrics(), SendEnumToUMA(
    502       Metrics::kMetricWifiStoppedTxQueueReason,
    503       Mac80211Monitor::kStopReasonChannelSwitch,
    504       Mac80211Monitor::kStopReasonMax)).Times(2);
    505   EXPECT_CALL(metrics(), SendToUMA(
    506       Metrics::kMetricWifiStoppedTxQueueLength,
    507       kQueueLengthLimit,
    508       Metrics::kMetricWifiStoppedTxQueueLengthMin,
    509       Metrics::kMetricWifiStoppedTxQueueLengthMax,
    510       Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(3);
    511   EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
    512             Mac80211Monitor::kStopFlagPowerSave,
    513             CheckAreQueuesStuck({
    514                 QState(0,
    515                        Mac80211Monitor::kStopFlagDriver |
    516                        Mac80211Monitor::kStopFlagPowerSave,
    517                        kQueueLengthLimit)}));
    518   EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave |
    519             Mac80211Monitor::kStopFlagChannelSwitch,
    520             CheckAreQueuesStuck({
    521                 QState(0,
    522                        Mac80211Monitor::kStopFlagPowerSave |
    523                        Mac80211Monitor::kStopFlagChannelSwitch,
    524                        kQueueLengthLimit)}));
    525   EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
    526             Mac80211Monitor::kStopFlagChannelSwitch,
    527             CheckAreQueuesStuck({
    528                 QState(0,
    529                        Mac80211Monitor::kStopFlagDriver |
    530                        Mac80211Monitor::kStopFlagChannelSwitch,
    531                        kQueueLengthLimit)}));
    532 }
    533 
    534 TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckMultipleQueues) {
    535   EXPECT_CALL(metrics(), SendEnumToUMA(
    536       Metrics::kMetricWifiStoppedTxQueueReason,
    537       Mac80211Monitor::kStopReasonPowerSave,
    538       Mac80211Monitor::kStopReasonMax)).Times(5);
    539   EXPECT_CALL(metrics(), SendEnumToUMA(
    540       Metrics::kMetricWifiStoppedTxQueueReason,
    541       Mac80211Monitor::kStopReasonDriver,
    542       Mac80211Monitor::kStopReasonMax)).Times(2);
    543   EXPECT_CALL(metrics(), SendToUMA(
    544       Metrics::kMetricWifiStoppedTxQueueLength,
    545       kQueueLengthLimit,
    546       Metrics::kMetricWifiStoppedTxQueueLengthMin,
    547       Metrics::kMetricWifiStoppedTxQueueLengthMax,
    548       Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(5);
    549   EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
    550             CheckAreQueuesStuck({
    551                 QState(0, 0, 0),
    552                 QState(0,
    553                        Mac80211Monitor::kStopFlagPowerSave,
    554                        kQueueLengthLimit)}));
    555   EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
    556             CheckAreQueuesStuck({
    557                 QState(0,
    558                        Mac80211Monitor::kStopFlagPowerSave,
    559                        kQueueLengthLimit),
    560                 QState(0, 0, 0)}));
    561   EXPECT_EQ(Mac80211Monitor::kStopFlagPowerSave,
    562             CheckAreQueuesStuck({
    563                 QState(0,
    564                        Mac80211Monitor::kStopFlagPowerSave,
    565                        kQueueLengthLimit),
    566                 QState(0,
    567                        Mac80211Monitor::kStopFlagPowerSave,
    568                        kQueueLengthLimit)}));
    569   EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
    570             Mac80211Monitor::kStopFlagPowerSave,
    571             CheckAreQueuesStuck({
    572                 QState(0,
    573                        Mac80211Monitor::kStopFlagPowerSave,
    574                        kQueueLengthLimit),
    575                 QState(0,
    576                        Mac80211Monitor::kStopFlagDriver,
    577                        kQueueLengthLimit)}));
    578   EXPECT_EQ(Mac80211Monitor::kStopFlagDriver |
    579             Mac80211Monitor::kStopFlagPowerSave,
    580             CheckAreQueuesStuck({
    581                 QState(0, Mac80211Monitor::kStopFlagDriver, kQueueLengthLimit),
    582                 QState(0,
    583                        Mac80211Monitor::kStopFlagPowerSave,
    584                        kQueueLengthLimit)}));
    585 }
    586 
    587 TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckQueueLength) {
    588   EXPECT_CALL(metrics(), SendEnumToUMA(
    589       Metrics::kMetricWifiStoppedTxQueueReason,
    590       Mac80211Monitor::kStopReasonPowerSave,
    591       Mac80211Monitor::kStopReasonMax)).Times(4);
    592   EXPECT_CALL(metrics(), SendToUMA(
    593       Metrics::kMetricWifiStoppedTxQueueLength,
    594       kQueueLengthLimit,
    595       Metrics::kMetricWifiStoppedTxQueueLengthMin,
    596       Metrics::kMetricWifiStoppedTxQueueLengthMax,
    597       Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets)).Times(4);
    598   EXPECT_TRUE(CheckAreQueuesStuck({
    599         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
    600   EXPECT_TRUE(CheckAreQueuesStuck({
    601         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2),
    602         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1),
    603         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
    604   EXPECT_TRUE(CheckAreQueuesStuck({
    605         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit),
    606         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1),
    607         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2)}));
    608   EXPECT_TRUE(CheckAreQueuesStuck({
    609         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-1),
    610         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit),
    611         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit-2)}));
    612 }
    613 
    614 TEST_F(Mac80211MonitorTest, CheckAreQueuesStuckQueueLengthIgnoresUnstopped) {
    615   EXPECT_CALL(metrics(), SendEnumToUMA(
    616       Metrics::kMetricWifiStoppedTxQueueReason,
    617       Mac80211Monitor::kStopReasonPowerSave,
    618       Mac80211Monitor::kStopReasonMax));
    619   EXPECT_CALL(metrics(), SendToUMA(
    620       Metrics::kMetricWifiStoppedTxQueueLength,
    621       kQueueLengthLimit,
    622       Metrics::kMetricWifiStoppedTxQueueLengthMin,
    623       Metrics::kMetricWifiStoppedTxQueueLengthMax,
    624       Metrics::kMetricWifiStoppedTxQueueLengthNumBuckets));
    625   EXPECT_TRUE(CheckAreQueuesStuck({
    626         QState(0, 0, kQueueLengthLimit * 10),
    627         QState(0, Mac80211Monitor::kStopFlagPowerSave, kQueueLengthLimit)}));
    628 }
    629 
    630 }  // namespace shill
    631