blob: 665cba97fcf5848023c71e8f11f21ae865440911 [file] [log] [blame]
Peter Qiuf0731732014-11-11 09:46:41 -08001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "apmanager/config.h"
6
Peter Qiufb39ba42014-11-21 09:09:59 -08007#include <string>
8
Peter Qiuf0731732014-11-11 09:46:41 -08009#include <base/strings/string_util.h>
10#include <base/strings/stringprintf.h>
11#include <chromeos/dbus/service_constants.h>
12#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
Peter Qiufb39ba42014-11-21 09:09:59 -080015#include "apmanager/mock_device.h"
16#include "apmanager/mock_manager.h"
17
Peter Qiu8e785b92014-11-24 10:01:08 -080018using ::testing::_;
Peter Qiufb39ba42014-11-21 09:09:59 -080019using ::testing::Mock;
20using ::testing::Return;
Peter Qiu8e785b92014-11-24 10:01:08 -080021using ::testing::SetArgumentPointee;
Peter Qiuf0731732014-11-11 09:46:41 -080022namespace apmanager {
23
24namespace {
25
26const char kServicePath[] = "/manager/services/0";
27const char kSsid[] = "TestSsid";
28const char kInterface[] = "uap0";
Peter Qiu68303292014-12-10 10:42:13 -080029const char kBridgeInterface[] = "br0";
Peter Qiubfd410e2015-01-09 15:14:20 -080030const char kControlInterfacePath[] = "/var/run/apmanager/hostapd/ctrl_iface";
Peter Qiuf0731732014-11-11 09:46:41 -080031const char kPassphrase[] = "Passphrase";
Peter Qiu8e785b92014-11-24 10:01:08 -080032const char k24GHzHTCapab[] = "[LDPC SMPS-STATIC GF SHORT-GI-20]";
33const char k5GHzHTCapab[] =
34 "[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]";
35
Peter Qiuf0731732014-11-11 09:46:41 -080036const uint16_t k24GHzChannel = 6;
37const uint16_t k5GHzChannel = 36;
38
39const char kExpected80211gConfigContent[] = "ssid=TestSsid\n"
40 "channel=6\n"
Peter Qiuf0731732014-11-11 09:46:41 -080041 "interface=uap0\n"
Peter Qiu8e785b92014-11-24 10:01:08 -080042 "hw_mode=g\n"
Peter Qiuf0731732014-11-11 09:46:41 -080043 "driver=nl80211\n"
44 "fragm_threshold=2346\n"
45 "rts_threshold=2347\n";
46
Peter Qiu68303292014-12-10 10:42:13 -080047const char kExpected80211gBridgeConfigContent[] = "ssid=TestSsid\n"
48 "bridge=br0\n"
49 "channel=6\n"
50 "interface=uap0\n"
51 "hw_mode=g\n"
52 "driver=nl80211\n"
53 "fragm_threshold=2346\n"
54 "rts_threshold=2347\n";
55
Peter Qiubfd410e2015-01-09 15:14:20 -080056const char kExpected80211gCtrlIfaceConfigContent[] =
57 "ssid=TestSsid\n"
58 "channel=6\n"
59 "interface=uap0\n"
60 "hw_mode=g\n"
61 "ctrl_interface=/var/run/apmanager/hostapd/ctrl_iface\n"
62 "ctrl_interface_group=apmanager\n"
63 "driver=nl80211\n"
64 "fragm_threshold=2346\n"
65 "rts_threshold=2347\n";
66
Peter Qiu8e785b92014-11-24 10:01:08 -080067const char kExpected80211n5GHzConfigContent[] =
68 "ssid=TestSsid\n"
69 "channel=36\n"
70 "interface=uap0\n"
71 "ieee80211n=1\n"
72 "ht_capab=[LDPC HT40+ SMPS-STATIC GF SHORT-GI-20 SHORT-GI-40]\n"
73 "hw_mode=a\n"
74 "driver=nl80211\n"
75 "fragm_threshold=2346\n"
76 "rts_threshold=2347\n";
Peter Qiuf0731732014-11-11 09:46:41 -080077
Peter Qiu8e785b92014-11-24 10:01:08 -080078const char kExpected80211n24GHzConfigContent[] =
79 "ssid=TestSsid\n"
80 "channel=6\n"
81 "interface=uap0\n"
82 "ieee80211n=1\n"
83 "ht_capab=[LDPC SMPS-STATIC GF SHORT-GI-20]\n"
84 "hw_mode=g\n"
85 "driver=nl80211\n"
86 "fragm_threshold=2346\n"
87 "rts_threshold=2347\n";
Peter Qiuf0731732014-11-11 09:46:41 -080088
89const char kExpectedRsnConfigContent[] = "ssid=TestSsid\n"
90 "channel=6\n"
Peter Qiuf0731732014-11-11 09:46:41 -080091 "interface=uap0\n"
Peter Qiu8e785b92014-11-24 10:01:08 -080092 "hw_mode=g\n"
Peter Qiuf0731732014-11-11 09:46:41 -080093 "wpa=2\n"
94 "rsn_pairwise=CCMP\n"
95 "wpa_key_mgmt=WPA-PSK\n"
96 "wpa_passphrase=Passphrase\n"
97 "driver=nl80211\n"
98 "fragm_threshold=2346\n"
99 "rts_threshold=2347\n";
100
101} // namespace
102
103class ConfigTest : public testing::Test {
104 public:
Peter Qiufb39ba42014-11-21 09:09:59 -0800105 ConfigTest() : config_(&manager_, kServicePath) {}
106
107 void SetupDevice(const std::string& interface) {
108 // Setup mock device.
Peter Qiu8e785b92014-11-24 10:01:08 -0800109 device_ = new MockDevice();
110 device_->SetPreferredApInterface(interface);
Peter Qiufb39ba42014-11-21 09:09:59 -0800111 EXPECT_CALL(manager_, GetDeviceFromInterfaceName(interface))
Peter Qiu8e785b92014-11-24 10:01:08 -0800112 .WillRepeatedly(Return(device_));
Peter Qiufb39ba42014-11-21 09:09:59 -0800113 }
Peter Qiuf0731732014-11-11 09:46:41 -0800114
115 protected:
116 Config config_;
Peter Qiufb39ba42014-11-21 09:09:59 -0800117 MockManager manager_;
Peter Qiu8e785b92014-11-24 10:01:08 -0800118 scoped_refptr<MockDevice> device_;
Peter Qiuf0731732014-11-11 09:46:41 -0800119};
120
Peter Qiu376e4042014-11-13 09:40:28 -0800121MATCHER_P(IsConfigErrorStartingWith, message, "") {
Peter Qiuf0731732014-11-11 09:46:41 -0800122 return arg != nullptr &&
123 arg->GetDomain() == chromeos::errors::dbus::kDomain &&
124 arg->GetCode() == kConfigError &&
Peter Qiu376e4042014-11-13 09:40:28 -0800125 StartsWithASCII(arg->GetMessage(), message, false);
Peter Qiuf0731732014-11-11 09:46:41 -0800126}
127
Peter Qiu8e785b92014-11-24 10:01:08 -0800128TEST_F(ConfigTest, GetFrequencyFromChannel) {
129 uint32_t frequency;
130 // Invalid channel.
131 EXPECT_FALSE(Config::GetFrequencyFromChannel(0, &frequency));
132 EXPECT_FALSE(Config::GetFrequencyFromChannel(166, &frequency));
133 EXPECT_FALSE(Config::GetFrequencyFromChannel(14, &frequency));
134 EXPECT_FALSE(Config::GetFrequencyFromChannel(33, &frequency));
135
136 // Valid channel.
137 const uint32_t kChannel1Frequency = 2412;
138 const uint32_t kChannel13Frequency = 2472;
139 const uint32_t kChannel34Frequency = 5170;
140 const uint32_t kChannel165Frequency = 5825;
141 EXPECT_TRUE(Config::GetFrequencyFromChannel(1, &frequency));
142 EXPECT_EQ(kChannel1Frequency, frequency);
143 EXPECT_TRUE(Config::GetFrequencyFromChannel(13, &frequency));
144 EXPECT_EQ(kChannel13Frequency, frequency);
145 EXPECT_TRUE(Config::GetFrequencyFromChannel(34, &frequency));
146 EXPECT_EQ(kChannel34Frequency, frequency);
147 EXPECT_TRUE(Config::GetFrequencyFromChannel(165, &frequency));
148 EXPECT_EQ(kChannel165Frequency, frequency);
149}
150
Peter Qiu68303292014-12-10 10:42:13 -0800151TEST_F(ConfigTest, ValidateSsid) {
152 chromeos::ErrorPtr error;
153 // SSID must contain between 1 and 32 characters.
154 EXPECT_TRUE(config_.ValidateSsid(&error, "s"));
155 EXPECT_TRUE(config_.ValidateSsid(&error, std::string(32, 'c')));
156 EXPECT_FALSE(config_.ValidateSsid(&error, ""));
157 EXPECT_FALSE(config_.ValidateSsid(&error, std::string(33, 'c')));
158}
159
160TEST_F(ConfigTest, ValidateSecurityMode) {
161 chromeos::ErrorPtr error;
162 EXPECT_TRUE(config_.ValidateSecurityMode(&error, kSecurityModeNone));
163 EXPECT_TRUE(config_.ValidateSecurityMode(&error, kSecurityModeRSN));
164 EXPECT_FALSE(config_.ValidateSecurityMode(&error, "InvalidSecurityMode"));
165}
166
167TEST_F(ConfigTest, ValidatePassphrase) {
168 chromeos::ErrorPtr error;
169 // Passpharse must contain between 8 and 63 characters.
170 EXPECT_TRUE(config_.ValidatePassphrase(&error, std::string(8, 'c')));
171 EXPECT_TRUE(config_.ValidatePassphrase(&error, std::string(63, 'c')));
172 EXPECT_FALSE(config_.ValidatePassphrase(&error, std::string(7, 'c')));
173 EXPECT_FALSE(config_.ValidatePassphrase(&error, std::string(64, 'c')));
174}
175
176TEST_F(ConfigTest, ValidateHwMode) {
177 chromeos::ErrorPtr error;
178 EXPECT_TRUE(config_.ValidateHwMode(&error, kHwMode80211a));
179 EXPECT_TRUE(config_.ValidateHwMode(&error, kHwMode80211b));
180 EXPECT_TRUE(config_.ValidateHwMode(&error, kHwMode80211g));
181 EXPECT_TRUE(config_.ValidateHwMode(&error, kHwMode80211n));
182 EXPECT_TRUE(config_.ValidateHwMode(&error, kHwMode80211ac));
183 EXPECT_FALSE(config_.ValidateSecurityMode(&error, "InvalidHwMode"));
184}
185
186TEST_F(ConfigTest, ValidateOperationMode) {
187 chromeos::ErrorPtr error;
188 EXPECT_TRUE(config_.ValidateOperationMode(&error, kOperationModeServer));
189 EXPECT_TRUE(config_.ValidateOperationMode(&error, kOperationModeBridge));
190 EXPECT_FALSE(config_.ValidateOperationMode(&error, "InvalidMode"));
191}
192
193TEST_F(ConfigTest, ValidateChannel) {
194 chromeos::ErrorPtr error;
195 EXPECT_TRUE(config_.ValidateChannel(&error, 1));
196 EXPECT_TRUE(config_.ValidateChannel(&error, 13));
197 EXPECT_TRUE(config_.ValidateChannel(&error, 34));
198 EXPECT_TRUE(config_.ValidateChannel(&error, 165));
199 EXPECT_FALSE(config_.ValidateChannel(&error, 0));
200 EXPECT_FALSE(config_.ValidateChannel(&error, 14));
201 EXPECT_FALSE(config_.ValidateChannel(&error, 33));
202 EXPECT_FALSE(config_.ValidateChannel(&error, 166));
203}
204
Peter Qiuf0731732014-11-11 09:46:41 -0800205TEST_F(ConfigTest, NoSsid) {
206 config_.SetChannel(k24GHzChannel);
207 config_.SetHwMode(kHwMode80211g);
208 config_.SetInterfaceName(kInterface);
209
210 std::string config_content;
211 chromeos::ErrorPtr error;
212 EXPECT_FALSE(config_.GenerateConfigFile(&error, &config_content));
Peter Qiu376e4042014-11-13 09:40:28 -0800213 EXPECT_THAT(error, IsConfigErrorStartingWith("SSID not specified"));
Peter Qiuf0731732014-11-11 09:46:41 -0800214}
215
Peter Qiufb39ba42014-11-21 09:09:59 -0800216TEST_F(ConfigTest, NoInterface) {
217 // Basic 80211.g configuration.
218 config_.SetSsid(kSsid);
219 config_.SetChannel(k24GHzChannel);
220 config_.SetHwMode(kHwMode80211g);
221
222 // No device available, fail to generate config file.
223 chromeos::ErrorPtr error;
224 std::string config_content;
225 EXPECT_CALL(manager_, GetAvailableDevice()).WillOnce(Return(nullptr));
226 EXPECT_FALSE(config_.GenerateConfigFile(&error, &config_content));
227 EXPECT_THAT(error, IsConfigErrorStartingWith("No device available"));
228 Mock::VerifyAndClearExpectations(&manager_);
229
230 // Device available, config file should be generated without any problem.
231 scoped_refptr<MockDevice> device = new MockDevice();
232 device->SetPreferredApInterface(kInterface);
233 chromeos::ErrorPtr error1;
234 EXPECT_CALL(manager_, GetAvailableDevice()).WillOnce(Return(device));
235 EXPECT_TRUE(config_.GenerateConfigFile(&error1, &config_content));
236 EXPECT_NE(std::string::npos, config_content.find(
237 kExpected80211gConfigContent))
238 << "Expected to find the following config...\n"
239 << kExpected80211gConfigContent << "..within content...\n"
240 << config_content;
241 EXPECT_EQ(nullptr, error1.get());
242 Mock::VerifyAndClearExpectations(&manager_);
243}
244
Peter Qiu68303292014-12-10 10:42:13 -0800245TEST_F(ConfigTest, InvalidInterface) {
246 // Basic 80211.g configuration.
247 config_.SetSsid(kSsid);
248 config_.SetChannel(k24GHzChannel);
249 config_.SetHwMode(kHwMode80211g);
250 config_.SetInterfaceName(kInterface);
251
252 // No device available, fail to generate config file.
253 chromeos::ErrorPtr error;
254 std::string config_content;
255 EXPECT_CALL(manager_, GetDeviceFromInterfaceName(kInterface))
256 .WillOnce(Return(nullptr));
257 EXPECT_FALSE(config_.GenerateConfigFile(&error, &config_content));
258 EXPECT_THAT(error,
259 IsConfigErrorStartingWith(
260 "Unable to find device for the specified interface"));
261 Mock::VerifyAndClearExpectations(&manager_);
262}
263
264TEST_F(ConfigTest, BridgeMode) {
265 config_.SetSsid(kSsid);
266 config_.SetChannel(k24GHzChannel);
267 config_.SetHwMode(kHwMode80211g);
268 config_.SetInterfaceName(kInterface);
269 config_.SetOperationMode(kOperationModeBridge);
270
271 // Bridge interface required for bridge mode.
272 chromeos::ErrorPtr error;
273 std::string config_content;
274 EXPECT_FALSE(config_.GenerateConfigFile(&error, &config_content));
275 EXPECT_THAT(error,
276 IsConfigErrorStartingWith("Bridge interface not specified"));
277
278 // Set bridge interface, config file should be generated without error.
279 config_.SetBridgeInterface(kBridgeInterface);
280 // Setup mock device.
281 SetupDevice(kInterface);
282 chromeos::ErrorPtr error1;
283 std::string config_content1;
284 EXPECT_TRUE(config_.GenerateConfigFile(&error1, &config_content1));
285 EXPECT_NE(std::string::npos, config_content1.find(
286 kExpected80211gBridgeConfigContent))
287 << "Expected to find the following config...\n"
288 << kExpected80211gBridgeConfigContent << "..within content...\n"
289 << config_content1;
290 EXPECT_EQ(nullptr, error1.get());
291}
292
Peter Qiuf0731732014-11-11 09:46:41 -0800293TEST_F(ConfigTest, 80211gConfig) {
294 config_.SetSsid(kSsid);
295 config_.SetChannel(k24GHzChannel);
296 config_.SetHwMode(kHwMode80211g);
297 config_.SetInterfaceName(kInterface);
298
Peter Qiufb39ba42014-11-21 09:09:59 -0800299 // Setup mock device.
300 SetupDevice(kInterface);
301
Peter Qiuf0731732014-11-11 09:46:41 -0800302 std::string config_content;
303 chromeos::ErrorPtr error;
304 EXPECT_TRUE(config_.GenerateConfigFile(&error, &config_content));
305 EXPECT_NE(std::string::npos, config_content.find(
306 kExpected80211gConfigContent))
307 << "Expected to find the following config...\n"
308 << kExpected80211gConfigContent << "..within content...\n"
309 << config_content;
310 EXPECT_EQ(nullptr, error.get());
311}
312
Peter Qiubfd410e2015-01-09 15:14:20 -0800313TEST_F(ConfigTest, 80211gConfigWithControlInterface) {
314 config_.SetSsid(kSsid);
315 config_.SetChannel(k24GHzChannel);
316 config_.SetHwMode(kHwMode80211g);
317 config_.SetInterfaceName(kInterface);
318 config_.set_control_interface(kControlInterfacePath);
319
320 // Setup mock device.
321 SetupDevice(kInterface);
322
323 std::string config_content;
324 chromeos::ErrorPtr error;
325 EXPECT_TRUE(config_.GenerateConfigFile(&error, &config_content));
326 EXPECT_NE(std::string::npos, config_content.find(
327 kExpected80211gCtrlIfaceConfigContent))
328 << "Expected to find the following config...\n"
329 << kExpected80211gCtrlIfaceConfigContent << "..within content...\n"
330 << config_content;
331 EXPECT_EQ(nullptr, error.get());
332}
333
Peter Qiuf0731732014-11-11 09:46:41 -0800334TEST_F(ConfigTest, 80211nConfig) {
335 config_.SetSsid(kSsid);
336 config_.SetHwMode(kHwMode80211n);
337 config_.SetInterfaceName(kInterface);
338
Peter Qiufb39ba42014-11-21 09:09:59 -0800339 // Setup mock device.
340 SetupDevice(kInterface);
341
Peter Qiuf0731732014-11-11 09:46:41 -0800342 // 5GHz channel.
343 config_.SetChannel(k5GHzChannel);
344 std::string ghz5_config_content;
345 chromeos::ErrorPtr error;
Peter Qiu8e785b92014-11-24 10:01:08 -0800346 std::string ht_capab_5ghz(k5GHzHTCapab);
347 EXPECT_CALL(*device_.get(), GetHTCapability(k5GHzChannel, _))
348 .WillOnce(DoAll(SetArgumentPointee<1>(ht_capab_5ghz), Return(true)));
Peter Qiuf0731732014-11-11 09:46:41 -0800349 EXPECT_TRUE(config_.GenerateConfigFile(&error, &ghz5_config_content));
350 EXPECT_NE(std::string::npos, ghz5_config_content.find(
351 kExpected80211n5GHzConfigContent))
352 << "Expected to find the following config...\n"
353 << kExpected80211n5GHzConfigContent << "..within content...\n"
354 << ghz5_config_content;
355 EXPECT_EQ(nullptr, error.get());
Peter Qiu8e785b92014-11-24 10:01:08 -0800356 Mock::VerifyAndClearExpectations(device_.get());
Peter Qiuf0731732014-11-11 09:46:41 -0800357
358 // 2.4GHz channel.
359 config_.SetChannel(k24GHzChannel);
360 std::string ghz24_config_content;
361 chromeos::ErrorPtr error1;
Peter Qiu8e785b92014-11-24 10:01:08 -0800362 std::string ht_capab_24ghz(k24GHzHTCapab);
363 EXPECT_CALL(*device_.get(), GetHTCapability(k24GHzChannel, _))
364 .WillOnce(DoAll(SetArgumentPointee<1>(ht_capab_24ghz), Return(true)));
Peter Qiuf0731732014-11-11 09:46:41 -0800365 EXPECT_TRUE(config_.GenerateConfigFile(&error1, &ghz24_config_content));
366 EXPECT_NE(std::string::npos, ghz24_config_content.find(
367 kExpected80211n24GHzConfigContent))
368 << "Expected to find the following config...\n"
369 << kExpected80211n24GHzConfigContent << "..within content...\n"
370 << ghz24_config_content;
371 EXPECT_EQ(nullptr, error.get());
Peter Qiu8e785b92014-11-24 10:01:08 -0800372 Mock::VerifyAndClearExpectations(device_.get());
Peter Qiuf0731732014-11-11 09:46:41 -0800373}
374
375TEST_F(ConfigTest, RsnConfig) {
376 config_.SetSsid(kSsid);
377 config_.SetChannel(k24GHzChannel);
378 config_.SetHwMode(kHwMode80211g);
379 config_.SetInterfaceName(kInterface);
380 config_.SetSecurityMode(kSecurityModeRSN);
381
Peter Qiufb39ba42014-11-21 09:09:59 -0800382 // Setup mock device.
383 SetupDevice(kInterface);
384
Peter Qiuf0731732014-11-11 09:46:41 -0800385 // Failed due to no passphrase specified.
386 std::string config_content;
387 chromeos::ErrorPtr error;
388 EXPECT_FALSE(config_.GenerateConfigFile(&error, &config_content));
Peter Qiu376e4042014-11-13 09:40:28 -0800389 EXPECT_THAT(error, IsConfigErrorStartingWith(
Peter Qiuf0731732014-11-11 09:46:41 -0800390 base::StringPrintf("Passphrase not set for security mode: %s",
391 kSecurityModeRSN)));
392
393 chromeos::ErrorPtr error1;
394 config_.SetPassphrase(kPassphrase);
395 EXPECT_TRUE(config_.GenerateConfigFile(&error1, &config_content));
396 EXPECT_NE(std::string::npos, config_content.find(
397 kExpectedRsnConfigContent))
398 << "Expected to find the following config...\n"
399 << kExpectedRsnConfigContent << "..within content...\n"
400 << config_content;
401 EXPECT_EQ(nullptr, error1.get());
402}
403
404} // namespace apmanager