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