update_engine: Multi-level |PrefsInterface::CreateSubKey()|
Currently, |PrefsInterface::CreateSubKey()| is limited to always provide
a namespace and subpref, but this can be generalized to a multi-level
namespace alongside a supplied key.
BUG=chromium:928805
TEST=FEATURES=test emerge-$B update_engine
Change-Id: Ib81e93e8319714caa85cd2fe6495d3cb9b0e82ed
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/2195623
Tested-by: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Andrew Lassalle <andrewlassalle@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
Commit-Queue: Jae Hoon Kim <kimjae@chromium.org>
diff --git a/common/prefs.cc b/common/prefs.cc
index 6a33037..6db01b7 100644
--- a/common/prefs.cc
+++ b/common/prefs.cc
@@ -28,11 +28,27 @@
#include "update_engine/common/utils.h"
using std::string;
+using std::vector;
namespace chromeos_update_engine {
const char kKeySeparator = '/';
+namespace {
+
+void DeleteEmptyDirectories(const base::FilePath& path) {
+ base::FileEnumerator path_enum(
+ path, false /* recursive */, base::FileEnumerator::DIRECTORIES);
+ for (base::FilePath dir_path = path_enum.Next(); !dir_path.empty();
+ dir_path = path_enum.Next()) {
+ DeleteEmptyDirectories(dir_path);
+ if (base::IsDirectoryEmpty(dir_path))
+ base::DeleteFile(dir_path, false);
+ }
+}
+
+} // namespace
+
bool PrefsBase::GetString(const string& key, string* value) const {
return storage_->GetKey(key, value);
}
@@ -108,11 +124,8 @@
observers_for_key.erase(observer_it);
}
-string PrefsInterface::CreateSubKey(const string& name_space,
- const string& sub_pref,
- const string& key) {
- return base::JoinString({name_space, sub_pref, key},
- string(1, kKeySeparator));
+string PrefsInterface::CreateSubKey(const vector<string>& ns_and_key) {
+ return base::JoinString(ns_and_key, string(1, kKeySeparator));
}
// Prefs
@@ -124,23 +137,7 @@
bool Prefs::FileStorage::Init(const base::FilePath& prefs_dir) {
prefs_dir_ = prefs_dir;
// Delete empty directories. Ignore errors when deleting empty directories.
- base::FileEnumerator namespace_enum(
- prefs_dir_, false /* recursive */, base::FileEnumerator::DIRECTORIES);
- for (base::FilePath namespace_path = namespace_enum.Next();
- !namespace_path.empty();
- namespace_path = namespace_enum.Next()) {
- base::FileEnumerator sub_pref_enum(namespace_path,
- false /* recursive */,
- base::FileEnumerator::DIRECTORIES);
- for (base::FilePath sub_pref_path = sub_pref_enum.Next();
- !sub_pref_path.empty();
- sub_pref_path = sub_pref_enum.Next()) {
- if (base::IsDirectoryEmpty(sub_pref_path))
- base::DeleteFile(sub_pref_path, false);
- }
- if (base::IsDirectoryEmpty(namespace_path))
- base::DeleteFile(namespace_path, false);
- }
+ DeleteEmptyDirectories(prefs_dir_);
return true;
}
diff --git a/common/prefs_interface.h b/common/prefs_interface.h
index b559697..3aad480 100644
--- a/common/prefs_interface.h
+++ b/common/prefs_interface.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <string>
+#include <vector>
namespace chromeos_update_engine {
@@ -80,9 +81,7 @@
virtual bool Delete(const std::string& key) = 0;
// Creates a key which is part of a sub preference.
- static std::string CreateSubKey(const std::string& name_space,
- const std::string& sub_pref,
- const std::string& key);
+ static std::string CreateSubKey(const std::vector<std::string>& ns_with_key);
// Add an observer to watch whenever the given |key| is modified. The
// OnPrefSet() and OnPrefDelete() methods will be called whenever any of the
diff --git a/common/prefs_unittest.cc b/common/prefs_unittest.cc
index f226949..24a62b5 100644
--- a/common/prefs_unittest.cc
+++ b/common/prefs_unittest.cc
@@ -62,17 +62,27 @@
TEST(Prefs, Init) {
Prefs prefs;
- const string name_space = "ns";
+ const string ns1 = "ns1";
+ const string ns2A = "ns2A";
+ const string ns2B = "ns2B";
const string sub_pref = "sp";
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- base::FilePath namespace_path = temp_dir.GetPath().Append(name_space);
+ auto ns1_path = temp_dir.GetPath().Append(ns1);
+ auto ns2A_path = ns1_path.Append(ns2A);
+ auto ns2B_path = ns1_path.Append(ns2B);
+ auto sub_pref_path = ns2A_path.Append(sub_pref);
- EXPECT_TRUE(base::CreateDirectory(namespace_path.Append(sub_pref)));
- EXPECT_TRUE(base::PathExists(namespace_path.Append(sub_pref)));
+ EXPECT_TRUE(base::CreateDirectory(ns2B_path));
+ EXPECT_TRUE(base::PathExists(ns2B_path));
+
+ EXPECT_TRUE(base::CreateDirectory(sub_pref_path));
+ EXPECT_TRUE(base::PathExists(sub_pref_path));
+
+ EXPECT_TRUE(base::PathExists(ns1_path));
ASSERT_TRUE(prefs.Init(temp_dir.GetPath()));
- EXPECT_FALSE(base::PathExists(namespace_path));
+ EXPECT_FALSE(base::PathExists(ns1_path));
}
TEST_F(PrefsTest, GetFileNameForKey) {
@@ -99,9 +109,9 @@
const string sub_pref2 = "sp2";
const string sub_key = "sk";
- EXPECT_EQ(PrefsInterface::CreateSubKey(name_space, sub_pref1, sub_key),
+ EXPECT_EQ(PrefsInterface::CreateSubKey({name_space, sub_pref1, sub_key}),
"ns/sp1/sk");
- EXPECT_EQ(PrefsInterface::CreateSubKey(name_space, sub_pref2, sub_key),
+ EXPECT_EQ(PrefsInterface::CreateSubKey({name_space, sub_pref2, sub_key}),
"ns/sp2/sk");
}
@@ -312,8 +322,8 @@
const string sub_pref = "sp";
const string sub_key1 = "sk1";
const string sub_key2 = "sk2";
- auto key1 = prefs_.CreateSubKey(name_space, sub_pref, sub_key1);
- auto key2 = prefs_.CreateSubKey(name_space, sub_pref, sub_key2);
+ auto key1 = prefs_.CreateSubKey({name_space, sub_pref, sub_key1});
+ auto key2 = prefs_.CreateSubKey({name_space, sub_pref, sub_key2});
base::FilePath sub_pref_path = prefs_dir_.Append(name_space).Append(sub_pref);
ASSERT_TRUE(prefs_.SetInt64(key1, 0));
@@ -350,7 +360,7 @@
prefs_.Delete(kKey);
testing::Mock::VerifyAndClearExpectations(&mock_obserser);
- auto key1 = prefs_.CreateSubKey("ns", "sp1", "key1");
+ auto key1 = prefs_.CreateSubKey({"ns", "sp1", "key1"});
prefs_.AddObserver(key1, &mock_obserser);
EXPECT_CALL(mock_obserser, OnPrefSet(key1));
@@ -424,7 +434,7 @@
EXPECT_FALSE(prefs_.Exists(kKey));
EXPECT_TRUE(prefs_.Delete(kKey));
- auto key = prefs_.CreateSubKey("ns", "sp", "sk");
+ auto key = prefs_.CreateSubKey({"ns", "sp", "sk"});
ASSERT_TRUE(prefs_.SetInt64(key, 0));
EXPECT_TRUE(prefs_.Exists(key));
EXPECT_TRUE(prefs_.Delete(kKey));