• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
Mac80211MonitorTest()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   }
~Mac80211MonitorTest()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.
time()74   MockTime& time() { return time_; }
event_dispatcher()75   MockEventDispatcher& event_dispatcher() { return event_dispatcher_; }
metrics()76   MockMetrics& metrics() { return metrics_; }
77 
78   // Complex fixture methods.
AllowWakeQueuesIfNeededCommonCalls()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   }
FakeUpNotStuckState()89   void FakeUpNotStuckState() {
90     FakeUpQueueFiles("00: 0x00000000/10\n");
91   }
FakeUpStuckByDriverState()92   void FakeUpStuckByDriverState() {
93     FakeUpQueueFiles("00: 0x00000001/10\n");
94   }
FakeUpStuckByPowerSaveState()95   void FakeUpStuckByPowerSaveState() {
96     FakeUpQueueFiles("00: 0x00000002/10\n");
97   }
FakeUpSysfs()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   }
DeleteQueueStateFile()106   void DeleteQueueStateFile() {
107     fake_queue_state_file_path_.clear();
108     PlumbFakeSysfs();
109   }
IsRunning() const110   bool IsRunning() const {
111     return mac80211_monitor_.is_running_ &&
112         !mac80211_monitor_.check_queues_callback_.IsCancelled();
113   }
IsStopped() const114   bool IsStopped() const {
115     return !mac80211_monitor_.is_running_ &&
116         mac80211_monitor_.check_queues_callback_.IsCancelled();
117   }
IsWakeQueuesFileModified() const118   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.
GetIsDeviceConnected() const127   bool GetIsDeviceConnected() const {
128     return mac80211_monitor_.is_device_connected_;
129   }
GetLastWokeQueuesMonotonicSeconds() const130   time_t GetLastWokeQueuesMonotonicSeconds() const {
131     return mac80211_monitor_.last_woke_queues_monotonic_seconds_;
132   }
GetLinkName() const133   const string& GetLinkName() const {
134     return mac80211_monitor_.link_name_;
135   }
GetMinimumTimeBetweenWakesSeconds() const136   time_t GetMinimumTimeBetweenWakesSeconds() const {
137     return Mac80211Monitor::kMinimumTimeBetweenWakesSeconds;
138   }
GetPhyName() const139   const string& GetPhyName() const {
140     return mac80211_monitor_.phy_name_;
141   }
GetQueueStateFilePath() const142   const base::FilePath& GetQueueStateFilePath() const {
143     return mac80211_monitor_.queue_state_file_path_;
144   }
GetWakeQueuesFilePath() const145   const base::FilePath& GetWakeQueuesFilePath() const {
146     return mac80211_monitor_.wake_queues_file_path_;
147   }
148 
149   // Pass-through methods to Mac80211Monitor methods.
StartMonitor(const string & phy_name)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   }
StopMonitor()160   void StopMonitor() {
161     mac80211_monitor_.Stop();
162   }
CheckAreQueuesStuck(const vector<QState> & queue_states)163   uint32_t CheckAreQueuesStuck(const vector<QState>& queue_states) {
164     return mac80211_monitor_.CheckAreQueuesStuck(queue_states);
165   }
UpdateConnectedState(bool new_state)166   void UpdateConnectedState(bool new_state) {
167     mac80211_monitor_.UpdateConnectedState(new_state);
168   }
WakeQueuesIfNeeded()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 
FakeUpQueueFiles(const string & queue_state_string)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   }
PlumbFakeSysfs()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.
operator ==(const QState & a,const QState & b)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 
TEST_F(Mac80211MonitorTest,Ctor)203 TEST_F(Mac80211MonitorTest, Ctor) {
204   EXPECT_TRUE(IsStopped());
205   EXPECT_EQ(kTestDeviceName, GetLinkName());
206 }
207 
TEST_F(Mac80211MonitorTest,Start)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 
TEST_F(Mac80211MonitorTest,Stop)219 TEST_F(Mac80211MonitorTest, Stop) {
220   StartMonitor("dont-care-phy");
221   EXPECT_TRUE(IsRunning());
222   StopMonitor();
223   EXPECT_TRUE(IsStopped());
224 }
225 
TEST_F(Mac80211MonitorTest,UpdateConnectedState)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededFullMacDevice)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededRearmsTimerWhenDisconnected)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededFailToReadQueueState)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededRearmsTimerWhenConnected)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededWakeNeeded)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededRateLimiting)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededNotStuck)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 
TEST_F(Mac80211MonitorTest,WakeQueuesIfNeededStuckByDriver)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 
TEST_F(Mac80211MonitorTest,ParseQueueStateSimple)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 
TEST_F(Mac80211MonitorTest,ParseQueueStateStopped)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 
TEST_F(Mac80211MonitorTest,ParseQueueStateBadInput)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 
TEST_F(Mac80211MonitorTest,CheckAreQueuesStuckNotStuck)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 
TEST_F(Mac80211MonitorTest,CheckAreQueuesStuckSingleReason)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 
TEST_F(Mac80211MonitorTest,CheckAreQueuesStuckMultipleReasons)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 
TEST_F(Mac80211MonitorTest,CheckAreQueuesStuckMultipleQueues)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 
TEST_F(Mac80211MonitorTest,CheckAreQueuesStuckQueueLength)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 
TEST_F(Mac80211MonitorTest,CheckAreQueuesStuckQueueLengthIgnoresUnstopped)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