blob: c23ddc8ff34c1ae29d52426a6889f6d8f2d5f950 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "privetd/privetd_conf_parser.h"
#include <map>
#include <set>
#include <string>
#include <vector>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/logging.h>
#include <chromeos/strings/string_utils.h>
#include <gtest/gtest.h>
#include "privetd/security_delegate.h"
using chromeos::string_utils::Join;
using chromeos::KeyValueStore;
using std::map;
using std::string;
namespace privetd {
namespace {
const char kWiFiBootstrapMode[] = "wifi_bootstrapping_mode";
const char kGcdBootstrapMode[] = "gcd_bootstrapping_mode";
const char kConnectTimeout[] = "connect_timeout_seconds";
const char kBootstrapTimeout[] = "bootstrap_timeout_seconds";
const char kMonitorTimeout[] = "monitor_timeout_seconds";
const char kDeviceServices[] = "device_services";
const char kDeviceClass[] = "device_class";
const char kDeviceMake[] = "device_make";
const char kDeviceModel[] = "device_model";
const char kDeviceModelId[] = "device_model_id";
const char kDeviceName[] = "device_name";
const char kDeviceDescription[] = "device_description";
const char kPairingModes[] = "pairing_modes";
const char kEmbeddedCodePath[] = "embedded_code_path";
} // namespace
class PrivetdConfParserTest : public testing::Test {
public:
using ConfDict = map<string, string>;
void SetUp() override {
CHECK(temp_dir_.CreateUniqueTempDir());
temp_file_ = temp_dir_.path().Append("temp.conf");
}
bool IsValid(const ConfDict& conf_dict) {
KeyValueStore store;
FillKeyValueStore(conf_dict, &store);
PrivetdConfigParser config;
return config.Parse(store);
}
void FillKeyValueStore(const ConfDict& conf_dict, KeyValueStore* store) {
std::vector<string> file_pieces;
for (const auto& it : conf_dict) {
file_pieces.push_back(Join("=", it.first, it.second));
}
string blob{Join("\n", file_pieces)};
int expected_len = blob.length();
CHECK(expected_len == base::WriteFile(temp_file_,
blob.c_str(),
expected_len));
CHECK(store->Load(temp_file_));
}
private:
base::FilePath temp_file_;
base::ScopedTempDir temp_dir_;
};
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidTimeouts) {
EXPECT_FALSE(IsValid({{kConnectTimeout, "-1"}}));
EXPECT_FALSE(IsValid({{kConnectTimeout, "a"}}));
EXPECT_FALSE(IsValid({{kConnectTimeout, ""}}));
EXPECT_FALSE(IsValid({{kConnectTimeout, "30 430"}}));
}
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidWiFiBootstrapModes) {
EXPECT_FALSE(IsValid({{kWiFiBootstrapMode, ""}}));
EXPECT_FALSE(IsValid({{kWiFiBootstrapMode, "clown_shoes"}}));
EXPECT_FALSE(IsValid({{kWiFiBootstrapMode, "off is invalid"}}));
EXPECT_FALSE(IsValid({{kWiFiBootstrapMode, "30"}}));
}
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidGcdBootstrapModes) {
EXPECT_FALSE(IsValid({{kGcdBootstrapMode, ""}}));
EXPECT_FALSE(IsValid({{kGcdBootstrapMode, "clown_shoes"}}));
EXPECT_FALSE(IsValid({{kGcdBootstrapMode, "off is invalid"}}));
EXPECT_FALSE(IsValid({{kGcdBootstrapMode, "30"}}));
}
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidServices) {
EXPECT_FALSE(IsValid({{kDeviceServices, "_a,b"}}));
}
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidDeviceClass) {
EXPECT_FALSE(IsValid({{kDeviceClass, ""}}));
EXPECT_FALSE(IsValid({{kDeviceClass, "a"}}));
EXPECT_FALSE(IsValid({{kDeviceClass, "aaaa"}}));
}
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidModelId) {
EXPECT_FALSE(IsValid({{kDeviceModelId, ""}}));
EXPECT_FALSE(IsValid({{kDeviceModelId, "a"}}));
EXPECT_FALSE(IsValid({{kDeviceModelId, "bb"}}));
EXPECT_FALSE(IsValid({{kDeviceModelId, "cccc"}}));
}
TEST_F(PrivetdConfParserTest, ShouldRejectInvalidName) {
EXPECT_FALSE(IsValid({{kDeviceName, ""}}));
}
TEST_F(PrivetdConfParserTest, ShouldParseSettings) {
const std::set<std::string> kExpectedWiFiInterfaces{"eth1", "clown shoes"};
const uint32_t kExpectedConnectTimeout{1};
const uint32_t kExpectedBootstrapTimeout{2};
const uint32_t kExpectedMonitorTimeout{3};
const std::set<std::string> kExpectedDeviceServices{"a", "b", "xwz"};
static const char kExpectedDeviceClass[]{"BB"};
static const char kExpectedDeviceMake[]{"testMade"};
static const char kExpectedDeviceModel[]{"testModel"};
static const char kExpectedDeviceModelId[]{"BBB"};
static const char kExpectedDeviceName[]{"testDevice"};
static const char kExpectedDeviceDescription[]{"testDescription"};
const std::set<PairingType> kExpectedPairingModes{PairingType::kEmbeddedCode,
PairingType::kPinCode};
static const char kExpectedEmbeddedCodePath[]{"123ABC"};
const ConfDict conf_dict{
{kWiFiBootstrapMode, "automatic"},
{kGcdBootstrapMode, "automatic"},
{kWiFiBootstrapInterfaces, Join(",", kExpectedWiFiInterfaces)},
{kConnectTimeout, std::to_string(kExpectedConnectTimeout)},
{kBootstrapTimeout, std::to_string(kExpectedBootstrapTimeout)},
{kMonitorTimeout, std::to_string(kExpectedMonitorTimeout)},
{kDeviceServices, Join(",", kExpectedDeviceServices)},
{kDeviceClass, kExpectedDeviceClass},
{kDeviceMake, kExpectedDeviceMake},
{kDeviceModel, kExpectedDeviceModel},
{kDeviceModelId, kExpectedDeviceModelId},
{kDeviceName, kExpectedDeviceName},
{kDeviceDescription, kExpectedDeviceDescription},
{kPairingModes, "pinCode"},
{kEmbeddedCodePath, kExpectedEmbeddedCodePath},
};
KeyValueStore store;
FillKeyValueStore(conf_dict, &store);
PrivetdConfigParser parser;
EXPECT_TRUE(parser.Parse(store));
EXPECT_EQ(WiFiBootstrapMode::kAutomatic, parser.wifi_bootstrap_mode());
EXPECT_EQ(GcdBootstrapMode::kAutomatic, parser.gcd_bootstrap_mode());
EXPECT_EQ(kExpectedWiFiInterfaces, parser.automatic_wifi_interfaces());
EXPECT_EQ(kExpectedConnectTimeout, parser.connect_timeout_seconds());
EXPECT_EQ(kExpectedBootstrapTimeout, parser.bootstrap_timeout_seconds());
EXPECT_EQ(kExpectedMonitorTimeout, parser.monitor_timeout_seconds());
EXPECT_EQ(kExpectedDeviceServices, parser.device_services());
EXPECT_EQ(kExpectedDeviceClass, parser.device_class());
EXPECT_EQ(kExpectedDeviceMake, parser.device_make());
EXPECT_EQ(kExpectedDeviceModel, parser.device_model());
EXPECT_EQ(kExpectedDeviceModelId, parser.device_model_id());
EXPECT_EQ(kExpectedDeviceName, parser.device_name());
EXPECT_EQ(kExpectedDeviceDescription, parser.device_description());
EXPECT_EQ(kExpectedPairingModes, parser.pairing_modes());
EXPECT_EQ(kExpectedEmbeddedCodePath, parser.embedded_code_path().value());
}
TEST_F(PrivetdConfParserTest, CriticalDefaults) {
PrivetdConfigParser parser;
EXPECT_EQ(WiFiBootstrapMode::kDisabled, parser.wifi_bootstrap_mode());
EXPECT_EQ(GcdBootstrapMode::kDisabled, parser.gcd_bootstrap_mode());
EXPECT_GT(parser.connect_timeout_seconds(), 0);
EXPECT_GT(parser.bootstrap_timeout_seconds(), 0);
EXPECT_GT(parser.monitor_timeout_seconds(), 0);
EXPECT_EQ(2, parser.device_class().size());
EXPECT_FALSE(parser.device_make().empty());
EXPECT_FALSE(parser.device_model().empty());
EXPECT_EQ(3, parser.device_model_id().size());
EXPECT_FALSE(parser.device_name().empty());
EXPECT_EQ(std::set<PairingType>{PairingType::kPinCode},
parser.pairing_modes());
EXPECT_TRUE(parser.embedded_code_path().empty());
}
} // namespace privetd