[shill] Profiles need to own their own storage

We're moving to a model where we rely on the StoreInterface
implementation to maintain profile state, instead of managing
a list of Service objects manually.  Thus, we need to allow
Profile to own its own StoreInterface.

BUG=chromium-os:17253
TEST=unit

Change-Id: Ie62462686ecf598efeac08a2d3180cd372430bb9
Reviewed-on: http://gerrit.chromium.org/gerrit/9916
Commit-Ready: Chris Masone <cmasone@chromium.org>
Reviewed-by: Chris Masone <cmasone@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
diff --git a/key_file_store_unittest.cc b/key_file_store_unittest.cc
index d69d479..c6e014b 100644
--- a/key_file_store_unittest.cc
+++ b/key_file_store_unittest.cc
@@ -28,7 +28,8 @@
 
   virtual void SetUp() {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    store_.set_path(temp_dir_.path().Append("test-key-file-store"));
+    test_file_ = temp_dir_.path().Append("test-key-file-store");
+    store_.set_path(test_file_);
   }
 
   virtual void TearDown() {
@@ -39,9 +40,13 @@
  protected:
   string ReadKeyFile();
   void WriteKeyFile(string data);
+  bool OpenCheckClose(const string &group,
+                      const string &key,
+                      const string &expected_value);
 
   GLib glib_;  // Use real GLib for testing KeyFileStore.
   ScopedTempDir temp_dir_;
+  FilePath test_file_;
   KeyFileStore store_;
 };
 
@@ -439,6 +444,58 @@
             ReadKeyFile());
 }
 
+TEST_F(KeyFileStoreTest, PersistAcrossClose) {
+  static const char kGroup[] = "string-group";
+  static const char kKey1[] = "test-string";
+  static const char kValue1[] = "foo";
+  static const char kKey2[] = "empty-string";
+  static const char kValue2[] = "";
+  ASSERT_TRUE(store_.Open());
+  ASSERT_TRUE(store_.SetString(kGroup, kKey1, kValue1));
+  ASSERT_TRUE(store_.Close());
+  ASSERT_TRUE(store_.Open());
+  ASSERT_TRUE(store_.SetString(kGroup, kKey2, kValue2));
+  string value;
+  ASSERT_TRUE(store_.GetString(kGroup, kKey1, &value));
+  ASSERT_EQ(kValue1, value);
+  ASSERT_TRUE(store_.GetString(kGroup, kKey2, &value));
+  ASSERT_EQ(kValue2, value);
+  ASSERT_TRUE(store_.Close());
+}
+
+bool KeyFileStoreTest::OpenCheckClose(const string &group,
+                                      const string &key,
+                                      const string &expected_value) {
+  KeyFileStore store(&glib_);
+  store.set_path(test_file_);
+  EXPECT_TRUE(store.Open());
+  string value;
+  bool could_get = store.GetString(group, key, &value);
+  store.set_path(FilePath(""));  // Don't persist to disk.
+  store.Close();
+  return could_get && expected_value == value;
+}
+
+TEST_F(KeyFileStoreTest, Flush) {
+  static const char kGroup[] = "string-group";
+  static const char kKey1[] = "test-string";
+  static const char kValue1[] = "foo";
+  static const char kKey2[] = "empty-string";
+  static const char kValue2[] = "";
+  ASSERT_TRUE(store_.Open());
+  ASSERT_TRUE(store_.SetString(kGroup, kKey1, kValue1));
+  ASSERT_TRUE(store_.Flush());
+  ASSERT_TRUE(OpenCheckClose(kGroup, kKey1, kValue1));
+
+  ASSERT_TRUE(store_.SetString(kGroup, kKey2, kValue2));
+  ASSERT_TRUE(store_.Flush());
+  ASSERT_TRUE(OpenCheckClose(kGroup, kKey2, kValue2));
+
+  EXPECT_TRUE(store_.DeleteKey(kGroup, kKey1));
+  ASSERT_TRUE(store_.Flush());
+  ASSERT_FALSE(OpenCheckClose(kGroup, kKey1, kValue1));
+}
+
 TEST_F(KeyFileStoreTest, Combo) {
   static const char kGroupA[] = "square";
   static const char kGroupB[] = "circle";