1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/files/file_util.h"
6#include "base/files/scoped_temp_dir.h"
7#include "base/memory/scoped_ptr.h"
8#include "base/message_loop/message_loop.h"
9#include "base/path_service.h"
10#include "content/public/test/test_browser_thread.h"
11#include "extensions/browser/value_store/value_store_frontend.h"
12#include "extensions/common/extension_paths.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using content::BrowserThread;
16
17class ValueStoreFrontendTest : public testing::Test {
18 public:
19  ValueStoreFrontendTest()
20      : ui_thread_(BrowserThread::UI, base::MessageLoop::current()),
21        file_thread_(BrowserThread::FILE, base::MessageLoop::current()) {
22  }
23
24  virtual void SetUp() {
25    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
26
27    base::FilePath test_data_dir;
28    ASSERT_TRUE(PathService::Get(extensions::DIR_TEST_DATA, &test_data_dir));
29    base::FilePath src_db(test_data_dir.AppendASCII("value_store_db"));
30    db_path_ = temp_dir_.path().AppendASCII("temp_db");
31    base::CopyDirectory(src_db, db_path_, true);
32
33    ResetStorage();
34  }
35
36  virtual void TearDown() {
37    base::MessageLoop::current()->RunUntilIdle();  // wait for storage to delete
38    storage_.reset();
39  }
40
41  // Reset the value store, reloading the DB from disk.
42  void ResetStorage() {
43    storage_.reset(new ValueStoreFrontend(db_path_));
44  }
45
46  bool Get(const std::string& key, scoped_ptr<base::Value>* output) {
47    storage_->Get(key, base::Bind(&ValueStoreFrontendTest::GetAndWait,
48                                  base::Unretained(this), output));
49    base::MessageLoop::current()->Run();  // wait for GetAndWait
50    return !!output->get();
51  }
52
53 protected:
54  void GetAndWait(scoped_ptr<base::Value>* output,
55                  scoped_ptr<base::Value> result) {
56    *output = result.Pass();
57    base::MessageLoop::current()->Quit();
58  }
59
60  scoped_ptr<ValueStoreFrontend> storage_;
61  base::ScopedTempDir temp_dir_;
62  base::FilePath db_path_;
63  base::MessageLoop message_loop_;
64  content::TestBrowserThread ui_thread_;
65  content::TestBrowserThread file_thread_;
66};
67
68TEST_F(ValueStoreFrontendTest, GetExistingData) {
69  scoped_ptr<base::Value> value;
70  ASSERT_FALSE(Get("key0", &value));
71
72  // Test existing keys in the DB.
73  {
74    ASSERT_TRUE(Get("key1", &value));
75    std::string result;
76    ASSERT_TRUE(value->GetAsString(&result));
77    EXPECT_EQ("value1", result);
78  }
79
80  {
81    ASSERT_TRUE(Get("key2", &value));
82    int result;
83    ASSERT_TRUE(value->GetAsInteger(&result));
84    EXPECT_EQ(2, result);
85  }
86}
87
88TEST_F(ValueStoreFrontendTest, ChangesPersistAfterReload) {
89  storage_->Set("key0", scoped_ptr<base::Value>(new base::FundamentalValue(0)));
90  storage_->Set("key1", scoped_ptr<base::Value>(new base::StringValue("new1")));
91  storage_->Remove("key2");
92
93  // Reload the DB and test our changes.
94  ResetStorage();
95
96  scoped_ptr<base::Value> value;
97  {
98    ASSERT_TRUE(Get("key0", &value));
99    int result;
100    ASSERT_TRUE(value->GetAsInteger(&result));
101    EXPECT_EQ(0, result);
102  }
103
104  {
105    ASSERT_TRUE(Get("key1", &value));
106    std::string result;
107    ASSERT_TRUE(value->GetAsString(&result));
108    EXPECT_EQ("new1", result);
109  }
110
111  ASSERT_FALSE(Get("key2", &value));
112}
113