history_data_store_unittest.cc revision 9ab5563a3196760eb381d102cbb2bc0f7abc6a50
1// Copyright 2013 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/basictypes.h"
6#include "base/bind.h"
7#include "base/file_util.h"
8#include "base/files/scoped_temp_dir.h"
9#include "base/memory/ref_counted.h"
10#include "base/message_loop/message_loop.h"
11#include "base/run_loop.h"
12#include "chrome/browser/ui/app_list/search/history_data.h"
13#include "chrome/browser/ui/app_list/search/history_data_store.h"
14#include "content/public/test/test_browser_thread.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace app_list {
18namespace test {
19
20namespace {
21
22std::string GetDataContent(const HistoryData::Data& data) {
23  std::string str = std::string("p:") + data.primary + ";s:";
24  bool first = true;
25  for (HistoryData::SecondaryDeque::const_iterator it = data.secondary.begin();
26       it != data.secondary.end(); ++it) {
27    if (first)
28      first = false;
29    else
30      str += ',';
31
32    str += *it;
33  }
34
35  return str;
36}
37
38}  // namespace
39
40class HistoryDataStoreTest : public testing::Test {
41 public:
42  HistoryDataStoreTest()
43      : ui_thread_(content::BrowserThread::UI, &message_loop_) {}
44  virtual ~HistoryDataStoreTest() {}
45
46  // testing::Test overrides:
47  virtual void SetUp() OVERRIDE {
48    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
49  }
50  virtual void TearDown() OVERRIDE {
51    // Release |store_| while ui loop is still running.
52    store_ = NULL;
53  }
54
55  void OpenStore(const std::string& file_name) {
56    data_file_ = temp_dir_.path().AppendASCII(file_name);
57    store_ = new HistoryDataStore(data_file_);
58    Load();
59  }
60
61  void Flush() {
62    store_->Flush(HistoryDataStore::OnFlushedCallback());
63  }
64
65  void Load() {
66    store_->Load(base::Bind(&HistoryDataStoreTest::OnRead,
67                            base::Unretained(this)));
68    run_loop_.reset(new base::RunLoop);
69    run_loop_->Run();
70    run_loop_.reset();
71  }
72
73  void WriteDataFile(const std::string& file_name,
74                     const std::string& data) {
75    file_util::WriteFile(
76        temp_dir_.path().AppendASCII(file_name), data.c_str(), data.size());
77  }
78
79  HistoryDataStore* store() { return store_.get(); }
80  const HistoryData::Associations& associations() const {
81    return associations_;
82  }
83
84 private:
85  void OnRead(scoped_ptr<HistoryData::Associations> associations) {
86    associations_.clear();
87    if (associations)
88      associations->swap(associations_);
89
90    if (run_loop_)
91      run_loop_->Quit();
92  }
93
94  base::MessageLoopForUI message_loop_;
95  content::TestBrowserThread ui_thread_;
96  base::ScopedTempDir temp_dir_;
97  base::FilePath data_file_;
98  scoped_ptr<base::RunLoop> run_loop_;
99
100  scoped_refptr<HistoryDataStore> store_;
101  HistoryData::Associations associations_;
102
103  DISALLOW_COPY_AND_ASSIGN(HistoryDataStoreTest);
104};
105
106TEST_F(HistoryDataStoreTest, NewFile) {
107  OpenStore("new_data_file.json");
108  EXPECT_TRUE(associations().empty());
109}
110
111TEST_F(HistoryDataStoreTest, BadFile) {
112  const char kDataFile[] = "invalid_data_file";
113  WriteDataFile(kDataFile, "invalid json");
114
115  OpenStore(kDataFile);
116  EXPECT_TRUE(associations().empty());
117}
118
119TEST_F(HistoryDataStoreTest, GoodFile) {
120  const char kDataFile[] = "good_data_file.json";
121  const char kGoodJson[] = "{"
122      "\"version\": \"1\","
123      "\"associations\": {"
124          "\"query\": {"
125             "\"p\": \"primary\","
126             "\"s\": [\"secondary1\",\"secondary2\"],"
127             "\"t\": \"123\""
128          "}"
129        "}"
130      "}";
131  WriteDataFile(kDataFile, kGoodJson);
132
133  OpenStore(kDataFile);
134  EXPECT_FALSE(associations().empty());
135  EXPECT_EQ(1u, associations().size());
136
137  HistoryData::Associations::const_iterator it = associations().find("query");
138  EXPECT_TRUE(it != associations().end());
139  EXPECT_EQ("p:primary;s:secondary1,secondary2", GetDataContent(it->second));
140}
141
142TEST_F(HistoryDataStoreTest, Change) {
143  const char kDataFile[] = "change_test.json";
144
145  OpenStore(kDataFile);
146  EXPECT_TRUE(associations().empty());
147
148  const char kQuery[] = "query";
149  const base::Time now = base::Time::Now();
150  store()->SetPrimary(kQuery, "primary");
151  store()->SetUpdateTime(kQuery, now);
152  Flush();
153  Load();
154  EXPECT_EQ(1u, associations().size());
155  HistoryData::Associations::const_iterator it = associations().find(kQuery);
156  EXPECT_TRUE(it != associations().end());
157  EXPECT_EQ("primary", it->second.primary);
158  EXPECT_EQ(0u, it->second.secondary.size());
159  EXPECT_EQ(now, it->second.update_time);
160
161  HistoryData::SecondaryDeque secondary;
162  secondary.push_back("s1");
163  secondary.push_back("s2");
164  store()->SetSecondary(kQuery, secondary);
165  Flush();
166  Load();
167  EXPECT_EQ(1u, associations().size());
168  it = associations().find(kQuery);
169  EXPECT_TRUE(it != associations().end());
170  EXPECT_EQ("p:primary;s:s1,s2", GetDataContent(it->second));
171  EXPECT_EQ(now, it->second.update_time);
172
173  store()->Delete(kQuery);
174  Flush();
175  Load();
176  EXPECT_TRUE(associations().empty());
177}
178
179}  // namespace test
180}  // namespace app_list
181