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
31using std::string;
32using std::vector;
33using ::testing::_;
34using ::testing::AnyNumber;
35using ::testing::DoAll;
36using ::testing::ElementsAre;
37using ::testing::HasSubstr;
38using ::testing::Return;
39using ::testing::SetArgumentPointee;
40using ::testing::StrictMock;
41
42namespace shill {
43
44namespace {
45
46const char kTestDeviceName[] = "test-dev";
47const char kJunkData[] = "junk data";
48
49}  // namespace
50
51typedef Mac80211Monitor::QueueState QState;
52
53class 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.
197static 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
203TEST_F(Mac80211MonitorTest, Ctor) {
204  EXPECT_TRUE(IsStopped());
205  EXPECT_EQ(kTestDeviceName, GetLinkName());
206}
207
208TEST_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
219TEST_F(Mac80211MonitorTest, Stop) {
220  StartMonitor("dont-care-phy");
221  EXPECT_TRUE(IsRunning());
222  StopMonitor();
223  EXPECT_TRUE(IsStopped());
224}
225
226TEST_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
238TEST_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
252TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRearmsTimerWhenDisconnected) {
253  FakeUpSysfs();
254  StartMonitor("dont-care-phy");
255  UpdateConnectedState(false);
256  EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _));
257  WakeQueuesIfNeeded();
258}
259
260TEST_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
274TEST_F(Mac80211MonitorTest, WakeQueuesIfNeededRearmsTimerWhenConnected) {
275  FakeUpSysfs();
276  StartMonitor("dont-care-phy");
277  UpdateConnectedState(true);
278  EXPECT_CALL(event_dispatcher(), PostDelayedTask(_, _));
279  WakeQueuesIfNeeded();
280}
281
282TEST_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
300TEST_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
318TEST_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
332TEST_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
346TEST_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
359TEST_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
417TEST_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
457TEST_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
465TEST_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
492TEST_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
534TEST_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
587TEST_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
614TEST_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