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/key_value_store_unittest.cc b/key_value_store_unittest.cc
index 5848957..e11cff8 100644
--- a/key_value_store_unittest.cc
+++ b/key_value_store_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <gtest/gtest.h>
 
+using std::string;
 using testing::Test;
 
 namespace shill {
@@ -18,29 +19,60 @@
   KeyValueStore store_;
 };
 
-TEST_F(KeyValueStoreTest, LookupBool) {
-  EXPECT_FALSE(store_.LookupBool("foo", false));
-  store_.SetBool("foo", true);
-  EXPECT_TRUE(store_.LookupBool("foo", false));
-  EXPECT_TRUE(store_.LookupBool("moo", true));
-  store_.SetBool("moo", false);
-  EXPECT_FALSE(store_.LookupBool("moo", true));
+TEST_F(KeyValueStoreTest, Bool) {
+  const string kKey("foo");
+  const bool kDefaultValue = true;
+  const bool kValue = false;
+  EXPECT_FALSE(store_.ContainsBool(kKey));
+  EXPECT_EQ(kDefaultValue, store_.LookupBool(kKey, kDefaultValue));
+  store_.SetBool(kKey, kValue);
+  EXPECT_TRUE(store_.ContainsBool(kKey));
+  EXPECT_EQ(kValue, store_.LookupBool(kKey, kDefaultValue));
+  EXPECT_EQ(kValue, store_.GetBool(kKey));
 }
 
-TEST_F(KeyValueStoreTest, LookupString) {
-  EXPECT_EQ("bar", store_.LookupString("foo", "bar"));
-  store_.SetString("foo", "zoo");
-  EXPECT_EQ("zoo", store_.LookupString("foo", "bar"));
+TEST_F(KeyValueStoreTest, Int) {
+  const string kKey("foo");
+  const int kValue = 456;
+  EXPECT_FALSE(store_.ContainsInt(kKey));
+  store_.SetInt(kKey, kValue);
+  EXPECT_TRUE(store_.ContainsInt(kKey));
+  EXPECT_EQ(kValue, store_.GetInt(kKey));
+  store_.RemoveInt(kKey);
+  EXPECT_FALSE(store_.ContainsInt(kKey));
 }
 
-TEST_F(KeyValueStoreTest, RemoveString) {
-  const std::string kKey("foo");
-  store_.SetString(kKey, "zoo");
-  EXPECT_EQ("zoo", store_.LookupString(kKey, "bar"));
+TEST_F(KeyValueStoreTest, String) {
+  const string kKey("foo");
+  const string kDefaultValue("bar");
+  const string kValue("baz");
+  EXPECT_FALSE(store_.ContainsString(kKey));
+  EXPECT_EQ(kDefaultValue, store_.LookupString(kKey, kDefaultValue));
+  store_.SetString(kKey, kValue);
+  EXPECT_TRUE(store_.ContainsString(kKey));
+  EXPECT_EQ(kValue, store_.LookupString(kKey, kDefaultValue));
+  EXPECT_EQ(kValue, store_.GetString(kKey));
   store_.RemoveString(kKey);
-  EXPECT_EQ("bar", store_.LookupString(kKey, "bar"));
+  EXPECT_FALSE(store_.ContainsString(kKey));
+  EXPECT_EQ(kDefaultValue, store_.LookupString(kKey, kDefaultValue));
+}
+
+TEST_F(KeyValueStoreTest, Uint) {
+  const string kKey("foo");
+  const int32 kValue = 456;
+  EXPECT_FALSE(store_.ContainsUint(kKey));
+  store_.SetUint(kKey, kValue);
+  EXPECT_TRUE(store_.ContainsUint(kKey));
+  EXPECT_EQ(kValue, store_.GetUint(kKey));
+}
+
+TEST_F(KeyValueStoreTest, DoubleRemove) {
+  const string kKey("foo");
   // Make sure we don't get an exception/infinite loop if we do a
-  // "RemoveString()" when the key does not exist.
+  // "Remove()" when the key does not exist.
+  store_.RemoveInt(kKey);
+  store_.RemoveInt(kKey);
+  store_.RemoveString(kKey);
   store_.RemoveString(kKey);
 }