shill: Allow service override of DHCP-derived IP parameters
Create new class StaticIPParameters which encapsulates all of the
property handling for RPC and storage, as well as applying parameters
to an IPConfig::Properties element. When a DHCP request succeeds
these parameters are used to selectively override values gained from
DHCP with those specified on the service.
BUG=chromium-os:23930
TEST=New unit tests -- manual testing is pending
Change-Id: I3b784f897ec6ffe0c78f2efe615d07d8f8924add
Reviewed-on: https://gerrit.chromium.org/gerrit/21448
Commit-Ready: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/static_ip_parameters_unittest.cc b/static_ip_parameters_unittest.cc
new file mode 100644
index 0000000..afc7f74
--- /dev/null
+++ b/static_ip_parameters_unittest.cc
@@ -0,0 +1,176 @@
+// Copyright (c) 2012 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 "shill/static_ip_parameters.h"
+
+#include <chromeos/dbus/service_constants.h>
+#include <gtest/gtest.h>
+
+#include "shill/ipconfig.h"
+#include "shill/mock_store.h"
+#include "shill/property_store.h"
+#include "shill/property_store_inspector.h"
+
+using std::string;
+using std::vector;
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+using testing::SetArgumentPointee;
+using testing::StrictMock;
+using testing::Test;
+
+namespace shill {
+
+namespace {
+static const char kAddress[] = "10.0.0.1";
+static const char kGateway[] = "10.0.0.254";
+static const int32 kMtu = 512;
+static const char kNameServer0[] = "10.0.1.253";
+static const char kNameServer1[] = "10.0.1.252";
+static const char kNameServers[] = "10.0.1.253,10.0.1.252";
+static const char kPeerAddress[] = "10.0.0.2";
+static const int32 kPrefixLen = 24;
+} // namespace {}
+
+class StaticIpParametersTest : public Test {
+ public:
+ StaticIpParametersTest() {}
+
+ void PopulateParams();
+ void PopulateProps();
+ void ExpectEmpty() {
+ EXPECT_TRUE(props_.address.empty());
+ EXPECT_TRUE(props_.gateway.empty());
+ EXPECT_FALSE(props_.mtu);
+ EXPECT_TRUE(props_.dns_servers.empty());
+ EXPECT_TRUE(props_.peer_address.empty());
+ EXPECT_FALSE(props_.subnet_prefix);
+ }
+ void ExpectPopulated() {
+ EXPECT_EQ(kAddress, props_.address);
+ EXPECT_EQ(kGateway, props_.gateway);
+ EXPECT_EQ(kMtu, props_.mtu);
+ EXPECT_EQ(2, props_.dns_servers.size());
+ EXPECT_EQ(kNameServer0, props_.dns_servers[0]);
+ EXPECT_EQ(kNameServer1, props_.dns_servers[1]);
+ EXPECT_EQ(kPeerAddress, props_.peer_address);
+ EXPECT_EQ(kPrefixLen, props_.subnet_prefix);
+ }
+ void Populate() {
+ props_.address = kAddress;
+ props_.gateway = kGateway;
+ props_.mtu = kMtu;
+ props_.dns_servers.push_back(kNameServer0);
+ props_.dns_servers.push_back(kNameServer1);
+ props_.peer_address = kPeerAddress;
+ props_.subnet_prefix = kPrefixLen;
+ }
+ protected:
+ StaticIPParameters static_params_;
+ IPConfig::Properties props_;
+};
+
+TEST_F(StaticIpParametersTest, InitState) {
+ EXPECT_TRUE(props_.address.empty());
+ EXPECT_TRUE(props_.gateway.empty());
+ EXPECT_FALSE(props_.mtu);
+ EXPECT_TRUE(props_.dns_servers.empty());
+ EXPECT_TRUE(props_.peer_address.empty());
+ EXPECT_FALSE(props_.subnet_prefix);
+
+ // Applying an empty set of parameters on an empty set of properties should
+ // be a no-op.
+ static_params_.ApplyTo(&props_);
+ ExpectEmpty();
+}
+
+TEST_F(StaticIpParametersTest, ApplyEmptyParameters) {
+ Populate();
+ static_params_.ApplyTo(&props_);
+ ExpectPopulated();
+}
+
+TEST_F(StaticIpParametersTest, ControlInterface) {
+ PropertyStore store;
+ static_params_.PlumbPropertyStore(&store);
+ Error error;
+ store.SetStringProperty("StaticIP.Address", kAddress, &error);
+ store.SetStringProperty("StaticIP.Gateway", kGateway, &error);
+ store.SetInt32Property("StaticIP.Mtu", kMtu, &error);
+ store.SetStringProperty("StaticIP.NameServers", kNameServers, &error);
+ store.SetStringProperty("StaticIP.PeerAddress", kPeerAddress, &error);
+ store.SetInt32Property("StaticIP.Prefixlen", kPrefixLen, &error);
+ static_params_.ApplyTo(&props_);
+ ExpectPopulated();
+
+ EXPECT_TRUE(static_params_.ContainsAddress());
+ store.ClearProperty("StaticIP.Address", &error);
+ EXPECT_FALSE(static_params_.ContainsAddress());
+ store.ClearProperty("StaticIP.Mtu", &error);
+ IPConfig::Properties props;
+ const string kTestAddress("test_address");
+ props.address = kTestAddress;
+ const int32 kTestMtu = 256;
+ props.mtu = kTestMtu;
+ static_params_.ApplyTo(&props);
+ EXPECT_EQ(kTestAddress, props.address);
+ EXPECT_EQ(kTestMtu, props.mtu);
+
+ PropertyStoreInspector inspector(&store);
+ EXPECT_FALSE(inspector.ContainsStringProperty("StaticIP.Address"));
+ string string_value;
+ EXPECT_TRUE(inspector.GetStringProperty("StaticIP.Gateway",
+ &string_value, &error));
+ EXPECT_EQ(kGateway, string_value);
+ EXPECT_FALSE(inspector.ContainsInt32Property("StaticIP.Mtu"));
+ EXPECT_TRUE(inspector.GetStringProperty("StaticIP.NameServers",
+ &string_value, &error));
+ EXPECT_EQ(kNameServers, string_value);
+ EXPECT_TRUE(inspector.GetStringProperty("StaticIP.PeerAddress",
+ &string_value, &error));
+ EXPECT_EQ(kPeerAddress, string_value);
+ int32 int_value;
+ EXPECT_TRUE(inspector.GetInt32Property("StaticIP.Prefixlen",
+ &int_value, &error));
+ EXPECT_EQ(kPrefixLen, int_value);
+}
+
+TEST_F(StaticIpParametersTest, Profile) {
+ StrictMock<MockStore> store;
+ const string kID = "storage_id";
+ EXPECT_CALL(store, GetString(kID, "StaticIP.Address", _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(string(kAddress)), Return(true)));
+ EXPECT_CALL(store, GetString(kID, "StaticIP.Gateway", _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(string(kGateway)), Return(true)));
+ EXPECT_CALL(store, GetInt(kID, "StaticIP.Mtu", _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(kMtu), Return(true)));
+ EXPECT_CALL(store, GetString(kID, "StaticIP.NameServers", _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(string(kNameServers)),
+ Return(true)));
+ EXPECT_CALL(store, GetString(kID, "StaticIP.PeerAddress", _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(string(kPeerAddress)),
+ Return(true)));
+ EXPECT_CALL(store, GetInt(kID, "StaticIP.Prefixlen", _))
+ .WillOnce(DoAll(SetArgumentPointee<2>(kPrefixLen), Return(true)));
+ static_params_.Load(&store, kID);
+ static_params_.ApplyTo(&props_);
+ ExpectPopulated();
+
+ EXPECT_CALL(store, SetString(kID, "StaticIP.Address", kAddress))
+ .WillOnce(Return(true));
+ EXPECT_CALL(store, SetString(kID, "StaticIP.Gateway", kGateway))
+ .WillOnce(Return(true));
+ EXPECT_CALL(store, SetInt(kID, "StaticIP.Mtu", kMtu))
+ .WillOnce(Return(true));
+ EXPECT_CALL(store, SetString(kID, "StaticIP.NameServers", kNameServers))
+ .WillOnce(Return(true));
+ EXPECT_CALL(store, SetString(kID, "StaticIP.PeerAddress", kPeerAddress))
+ .WillOnce(Return(true));
+ EXPECT_CALL(store, SetInt(kID, "StaticIP.Prefixlen", kPrefixLen))
+ .WillOnce(Return(true));
+ static_params_.Save(&store, kID);
+}
+
+} // namespace shill