1edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo// Use of this source code is governed by a BSD-style license that can be 3edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo// found in the LICENSE file. 4edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/key_value_store.h> 6edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 7edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo#include <map> 8edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo#include <string> 935babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp#include <vector> 10edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 11edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo#include <base/files/file_util.h> 12edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo#include <base/files/scoped_temp_dir.h> 139ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat#include <base/logging.h> 14edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo#include <base/strings/string_util.h> 159ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/map_utils.h> 16edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo#include <gtest/gtest.h> 17edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 18edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymousing base::FilePath; 19edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymousing base::ReadFileToString; 20edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymousing std::map; 21edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymousing std::string; 2235babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kempusing std::vector; 23edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 249ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 25edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 26edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymoclass KeyValueStoreTest : public ::testing::Test { 27edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo protected: 289ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat // Returns the value from |store_| corresponding to |key|, or an empty string 299ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat // if the key is not present. Crashes if the store returns an empty value. 309ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat string GetNonemptyStringValue(const string& key) { 319ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat string value; 329ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat if (store_.GetString(key, &value)) 339ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat CHECK(!value.empty()); 349ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat return value; 359ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat } 369ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 37edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo KeyValueStore store_; // KeyValueStore under test. 38edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo}; 39edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 40665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex DeymoTEST_F(KeyValueStoreTest, LoadAndSaveFromFile) { 41665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo base::ScopedTempDir temp_dir_; 42665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo CHECK(temp_dir_.CreateUniqueTempDir()); 43665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo base::FilePath temp_file_ = temp_dir_.path().Append("temp.conf"); 44665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo base::FilePath saved_temp_file_ = temp_dir_.path().Append("saved_temp.conf"); 45665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo 46665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo string blob = "A=B\n# Comment\n"; 47edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo ASSERT_EQ(blob.size(), base::WriteFile(temp_file_, blob.data(), blob.size())); 489ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat ASSERT_TRUE(store_.Load(temp_file_)); 49edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 50665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo string value; 51665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.GetString("A", &value)); 52665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_EQ("B", value); 53665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo 54665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo ASSERT_TRUE(store_.Save(saved_temp_file_)); 55edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo string read_blob; 56665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo ASSERT_TRUE(ReadFileToString(FilePath(saved_temp_file_), &read_blob)); 57edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_EQ("A=B\n", read_blob); 58edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo} 59edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 60665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex DeymoTEST_F(KeyValueStoreTest, CommentsAreIgnored) { 61665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString( 62665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo "# comment\nA=B\n\n\n#another=comment\n # leading spaces\n")); 63665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_EQ("A=B\n", store_.SaveToString()); 64665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo} 65edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 66665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex DeymoTEST_F(KeyValueStoreTest, EmptyTest) { 67665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString("")); 68665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_EQ("", store_.SaveToString()); 69edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo} 70edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 71edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex DeymoTEST_F(KeyValueStoreTest, LoadAndReloadTest) { 72665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString( 73665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo "A=B\nC=\nFOO=BAR=BAZ\nBAR=BAX\nMISSING=NEWLINE")); 74edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 7505d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko map<string, string> expected = {{"A", "B"}, 7605d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {"C", ""}, 7705d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {"FOO", "BAR=BAZ"}, 7805d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {"BAR", "BAX"}, 7905d29044d14a60775ed6c51c75a414eb0cb50347Alex Vakulenko {"MISSING", "NEWLINE"}}; 80edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 819ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat // Test expected values. 82edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo string value; 83edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo for (const auto& it : expected) { 84edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(store_.GetString(it.first, &value)); 85edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_EQ(it.second, value) << "Testing key: " << it.first; 86edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo } 87edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 88edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo // Save, load and test again. 89edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo KeyValueStore new_store; 90665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo ASSERT_TRUE(new_store.LoadFromString(store_.SaveToString())); 91edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 92edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo for (const auto& it : expected) { 93edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(new_store.GetString(it.first, &value)) << "key: " << it.first; 94edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_EQ(it.second, value) << "key: " << it.first; 95edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo } 96edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo} 97edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 98edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex DeymoTEST_F(KeyValueStoreTest, SimpleBooleanTest) { 99edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo bool result; 100edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_FALSE(store_.GetBoolean("A", &result)); 101edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 102edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo store_.SetBoolean("A", true); 103edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(store_.GetBoolean("A", &result)); 104edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(result); 105edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 106edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo store_.SetBoolean("A", false); 107edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(store_.GetBoolean("A", &result)); 108edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_FALSE(result); 109edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo} 110edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 111edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex DeymoTEST_F(KeyValueStoreTest, BooleanParsingTest) { 112edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo string blob = "TRUE=true\nfalse=false\nvar=false\nDONT_SHOUT=TRUE\n"; 113665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString(blob)); 114edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 115edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo map<string, bool> expected = { 116edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo {"TRUE", true}, {"false", false}, {"var", false}}; 117edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo bool value; 118edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_FALSE(store_.GetBoolean("DONT_SHOUT", &value)); 119edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo string str_value; 120edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(store_.GetString("DONT_SHOUT", &str_value)); 121edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 1229ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat // Test expected values. 123edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo for (const auto& it : expected) { 124edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_TRUE(store_.GetBoolean(it.first, &value)) << "key: " << it.first; 125edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo EXPECT_EQ(it.second, value) << "key: " << it.first; 126edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo } 127edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo} 128edf1a2bc4b7741b7ad1e689d7dcbf99a6d95f0adAlex Deymo 1299ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel EratTEST_F(KeyValueStoreTest, TrimWhitespaceAroundKey) { 130665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString(" a=1\nb =2\n c =3\n")); 1319ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1329ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("1", GetNonemptyStringValue("a")); 1339ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("2", GetNonemptyStringValue("b")); 1349ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("3", GetNonemptyStringValue("c")); 1359ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1369ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat // Keys should also be trimmed when setting new values. 1379ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat store_.SetString(" foo ", "4"); 1389ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("4", GetNonemptyStringValue("foo")); 1399ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1409ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat store_.SetBoolean(" bar ", true); 1419ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat bool value = false; 1429ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat ASSERT_TRUE(store_.GetBoolean("bar", &value)); 1439ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_TRUE(value); 1449ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat} 1459ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1469ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel EratTEST_F(KeyValueStoreTest, IgnoreWhitespaceLine) { 147665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString("a=1\n \t \nb=2")); 1489ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1499ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("1", GetNonemptyStringValue("a")); 1509ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("2", GetNonemptyStringValue("b")); 1519ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat} 1529ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1539ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel EratTEST_F(KeyValueStoreTest, RejectEmptyKeys) { 154665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_FALSE(store_.LoadFromString("=1")); 155665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_FALSE(store_.LoadFromString(" =2")); 1569ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1579ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat // Trying to set an empty (after trimming) key should fail an assert. 1589ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_DEATH(store_.SetString(" ", "3"), ""); 1599ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_DEATH(store_.SetBoolean(" ", "4"), ""); 1609ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat} 1619ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1629ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel EratTEST_F(KeyValueStoreTest, RejectBogusLines) { 163665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_FALSE(store_.LoadFromString("a=1\nbogus\nb=2")); 1649ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat} 1659ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1669ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel EratTEST_F(KeyValueStoreTest, MultilineValue) { 167665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_TRUE(store_.LoadFromString("a=foo\nb=bar\\\n baz \\ \nc=3\n")); 1689ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1699ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("foo", GetNonemptyStringValue("a")); 1709ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("bar baz \\ ", GetNonemptyStringValue("b")); 1719ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat EXPECT_EQ("3", GetNonemptyStringValue("c")); 1729ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat} 1739ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 1749ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel EratTEST_F(KeyValueStoreTest, UnterminatedMultilineValue) { 175665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_FALSE(store_.LoadFromString("a=foo\\")); 176665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_FALSE(store_.LoadFromString("a=foo\\\n")); 177665bc53fdf6b4b4ffd3d24f60e6a573ca52828a1Alex Deymo EXPECT_FALSE(store_.LoadFromString("a=foo\\\n\n# blah\n")); 1789ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat} 1799ee4e717de43a6d76a7ddde9a2718e71bdfb7de9Daniel Erat 18035babde85282fd18ce13a5b1c680d0e549a9c03eAaron KempTEST_F(KeyValueStoreTest, GetKeys) { 18135babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp map<string, string> entries = { 18235babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp {"1", "apple"}, {"2", "banana"}, {"3", "cherry"} 18335babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp }; 18435babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp for (const auto& it : entries) { 18535babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp store_.SetString(it.first, it.second); 18635babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp } 18735babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp 18835babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp vector<string> keys = GetMapKeysAsVector(entries); 18935babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp EXPECT_EQ(keys, store_.GetKeys()); 19035babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp} 19135babde85282fd18ce13a5b1c680d0e549a9c03eAaron Kemp 1929ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 193