Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2016, 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 <functional>
     18 #include <memory>
     19 #include <vector>
     20 
     21 #include <linux/netlink.h>
     22 #include <linux/nl80211.h>
     23 
     24 #include <gtest/gtest.h>
     25 
     26 #include "wificond/scanning/scan_result.h"
     27 #include "wificond/scanning/scan_utils.h"
     28 #include "wificond/tests/mock_netlink_manager.h"
     29 
     30 using std::bind;
     31 using std::placeholders::_1;
     32 using std::placeholders::_2;
     33 using std::unique_ptr;
     34 using std::vector;
     35 using testing::AllOf;
     36 using testing::Invoke;
     37 using testing::NiceMock;
     38 using testing::Not;
     39 using testing::Return;
     40 using testing::_;
     41 
     42 using com::android::server::wifi::wificond::NativeScanResult;
     43 
     44 namespace android {
     45 namespace wificond {
     46 
     47 namespace {
     48 
     49 constexpr uint32_t kFakeInterfaceIndex = 12;
     50 constexpr uint32_t kFakeScheduledScanIntervalMs = 20000;
     51 constexpr uint32_t kFakeSequenceNumber = 1984;
     52 constexpr int kFakeErrorCode = EIO;
     53 constexpr int32_t kFakeRssiThreshold = -80;
     54 constexpr bool kFakeUseRandomMAC = true;
     55 
     56 // Currently, control messages are only created by the kernel and sent to us.
     57 // Therefore NL80211Packet doesn't have corresponding constructor.
     58 // For test we manually create control messages using this helper function.
     59 NL80211Packet CreateControlMessageError(int error_code) {
     60   vector<uint8_t> data;
     61   data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0);
     62   // Initialize length field.
     63   nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data());
     64   nl_header->nlmsg_len = data.size();
     65   nl_header->nlmsg_type = NLMSG_ERROR;
     66   nl_header->nlmsg_seq = kFakeSequenceNumber;
     67   nl_header->nlmsg_pid = getpid();
     68   int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN);
     69   *error_field = -error_code;
     70 
     71   return NL80211Packet(data);
     72 }
     73 
     74 NL80211Packet CreateControlMessageAck() {
     75   return CreateControlMessageError(0);
     76 }
     77 
     78 // This is a helper function to mock the behavior of NetlinkManager::
     79 // SendMessageAndGetResponses() when we expect a single packet response.
     80 // |request_message| and |response| are mapped to existing parameters of
     81 // SendMessageAndGetResponses().
     82 // |mock_response| and |mock_return value| are additional parameters used
     83 // for specifying expected results,
     84 bool AppendMessageAndReturn(
     85     NL80211Packet& mock_response,
     86     bool mock_return_value,
     87     const NL80211Packet& request_message,
     88     vector<std::unique_ptr<const NL80211Packet>>* response) {
     89   response->push_back(std::make_unique<NL80211Packet>(mock_response));
     90   return mock_return_value;
     91 }
     92 
     93 }  // namespace
     94 
     95 class ScanUtilsTest : public ::testing::Test {
     96  protected:
     97   virtual void SetUp() {
     98     ON_CALL(netlink_manager_,
     99             SendMessageAndGetResponses(_, _)).WillByDefault(Return(true));
    100   }
    101 
    102   NiceMock<MockNetlinkManager> netlink_manager_;
    103   ScanUtils scan_utils_{&netlink_manager_};
    104 };
    105 
    106 MATCHER_P(DoesNL80211PacketMatchCommand, command,
    107           "Check if the netlink packet matches |command|") {
    108   return arg.GetCommand() == command;
    109 }
    110 
    111 MATCHER_P(DoesNL80211PacketHaveAttribute, attr,
    112           "Check if the netlink packet has atttribute |attr|") {
    113   return arg.HasAttribute(attr);
    114 }
    115 
    116 TEST_F(ScanUtilsTest, CanGetScanResult) {
    117   vector<NativeScanResult> scan_results;
    118   EXPECT_CALL(
    119       netlink_manager_,
    120       SendMessageAndGetResponses(
    121           DoesNL80211PacketMatchCommand(NL80211_CMD_GET_SCAN), _));
    122 
    123   // We don't use EXPECT_TRUE here because we need to mock a complete
    124   // response for NL80211_CMD_GET_SCAN to satisfy the parsing code called
    125   // by GetScanResult.
    126   // TODO(b/34231002): Mock response for NL80211_CMD_GET_SCAN.
    127   // TODO(b/34231420): Add validation of interface index.
    128   scan_utils_.GetScanResult(kFakeInterfaceIndex, &scan_results);
    129 }
    130 
    131 TEST_F(ScanUtilsTest, CanSendScanRequest) {
    132   NL80211Packet response = CreateControlMessageAck();
    133   EXPECT_CALL(
    134       netlink_manager_,
    135       SendMessageAndGetResponses(
    136           DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
    137               WillOnce(Invoke(bind(
    138                   AppendMessageAndReturn, response, true, _1, _2)));
    139 
    140   int errno_ignored;
    141   EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {},
    142                                &errno_ignored));
    143   // TODO(b/34231420): Add validation of requested scan ssids, threshold,
    144   // and frequencies.
    145 }
    146 
    147 TEST_F(ScanUtilsTest, CanHandleScanRequestFailure) {
    148   NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
    149   EXPECT_CALL(
    150       netlink_manager_,
    151       SendMessageAndGetResponses(
    152           DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
    153               WillOnce(Invoke(bind(
    154                   AppendMessageAndReturn, response, true, _1, _2)));
    155   int error_code;
    156   EXPECT_FALSE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC, {}, {},
    157                                 &error_code));
    158   EXPECT_EQ(kFakeErrorCode, error_code);
    159 }
    160 
    161 TEST_F(ScanUtilsTest, CanSendSchedScanRequest) {
    162   NL80211Packet response = CreateControlMessageAck();
    163   EXPECT_CALL(
    164       netlink_manager_,
    165        SendMessageAndGetResponses(
    166            DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
    167               WillOnce(Invoke(bind(
    168                   AppendMessageAndReturn, response, true, _1, _2)));
    169   int errno_ignored;
    170   EXPECT_TRUE(scan_utils_.StartScheduledScan(
    171       kFakeInterfaceIndex,
    172       SchedScanIntervalSetting(),
    173       kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored));
    174   // TODO(b/34231420): Add validation of requested scan ssids, threshold,
    175   // and frequencies.
    176 }
    177 
    178 TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) {
    179   NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
    180   EXPECT_CALL(
    181       netlink_manager_,
    182        SendMessageAndGetResponses(
    183            DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
    184               WillOnce(Invoke(bind(
    185                   AppendMessageAndReturn, response, true, _1, _2)));
    186   int error_code;
    187   EXPECT_FALSE(scan_utils_.StartScheduledScan(
    188       kFakeInterfaceIndex,
    189       SchedScanIntervalSetting(),
    190       kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &error_code));
    191   EXPECT_EQ(kFakeErrorCode, error_code);
    192 }
    193 
    194 TEST_F(ScanUtilsTest, CanSpecifyScanPlansForSchedScanRequest) {
    195   EXPECT_CALL(
    196       netlink_manager_,
    197        SendMessageAndGetResponses(
    198            AllOf(
    199                DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
    200                DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_PLANS),
    201                Not(DoesNL80211PacketHaveAttribute(
    202                    NL80211_ATTR_SCHED_SCAN_INTERVAL))),
    203            _));
    204   int errno_ignored;
    205   SchedScanIntervalSetting interval_setting{
    206       {{kFakeScheduledScanIntervalMs, 10 /* repeated times */}},
    207       kFakeScheduledScanIntervalMs * 3 /* interval for infinite scans */};
    208 
    209   scan_utils_.StartScheduledScan(
    210       kFakeInterfaceIndex,
    211       interval_setting,
    212       kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored);
    213 }
    214 
    215 TEST_F(ScanUtilsTest, CanSpecifySingleIntervalForSchedScanRequest) {
    216   EXPECT_CALL(
    217       netlink_manager_,
    218        SendMessageAndGetResponses(
    219            AllOf(
    220                DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
    221                DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_INTERVAL),
    222                Not(DoesNL80211PacketHaveAttribute(
    223                    NL80211_ATTR_SCHED_SCAN_PLANS))),
    224            _));
    225   int errno_ignored;
    226   SchedScanIntervalSetting interval_setting{{}, kFakeScheduledScanIntervalMs};
    227 
    228   scan_utils_.StartScheduledScan(
    229       kFakeInterfaceIndex,
    230       interval_setting,
    231       kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored);
    232 }
    233 
    234 TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) {
    235   constexpr uint64_t kLastSeenTimestampNanoSeconds = 123456;
    236   constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
    237   NL80211NestedAttr bss(NL80211_ATTR_BSS);
    238   bss.AddAttribute(
    239       NL80211Attr<uint64_t>(NL80211_BSS_LAST_SEEN_BOOTTIME,
    240                             kLastSeenTimestampNanoSeconds));
    241   bss.AddAttribute(
    242       NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
    243   uint64_t timestamp_microseconds;
    244   EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
    245       bss, &timestamp_microseconds));
    246   EXPECT_EQ(kLastSeenTimestampNanoSeconds/1000, timestamp_microseconds);
    247 }
    248 
    249 TEST_F(ScanUtilsTest, CanHandleMissingLastSeenSinceBootNetlinkAttribute) {
    250   constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
    251   NL80211NestedAttr bss(NL80211_ATTR_BSS);
    252   bss.AddAttribute(
    253       NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
    254   uint64_t timestamp_microseconds;
    255   EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
    256       bss, &timestamp_microseconds));
    257   EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds);
    258 }
    259 
    260 // Probe TSF is newer.
    261 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1) {
    262   constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 654321;
    263   constexpr uint64_t kBssTsfTimestampMicroSeconds =
    264       kBssBeaconTsfTimestampMicroSeconds + 2000;
    265   NL80211NestedAttr bss(NL80211_ATTR_BSS);
    266   bss.AddAttribute(
    267       NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF,
    268                             kBssBeaconTsfTimestampMicroSeconds));
    269   bss.AddAttribute(
    270       NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
    271   uint64_t timestamp_microseconds;
    272   EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
    273       bss, &timestamp_microseconds));
    274   EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds);
    275 }
    276 
    277 // Beacon TSF is newer.
    278 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2) {
    279   constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
    280   constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds =
    281       kBssTsfTimestampMicroSeconds + 2000;
    282   NL80211NestedAttr bss(NL80211_ATTR_BSS);
    283   bss.AddAttribute(
    284       NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF,
    285                             kBssBeaconTsfTimestampMicroSeconds));
    286   bss.AddAttribute(
    287       NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
    288   uint64_t timestamp_microseconds;
    289   EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
    290       bss, &timestamp_microseconds));
    291   EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds);
    292 }
    293 
    294 }  // namespace wificond
    295 }  // namespace android
    296