190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/basictypes.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind.h"
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/ref_counted.h"
109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/run_loop.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/app_list/search/common/dictionary_data_store.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/app_list/search/history_data.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/app_list/search/history_data_store.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/test/test_browser_thread.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace app_list {
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace test {
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string GetDataContent(const HistoryData::Data& data) {
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string str = std::string("p:") + data.primary + ";s:";
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool first = true;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (HistoryData::SecondaryDeque::const_iterator it = data.secondary.begin();
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != data.secondary.end(); ++it) {
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (first)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      first = false;
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      str += ',';
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    str += *it;
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return str;
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class HistoryDataStoreTest : public testing::Test {
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistoryDataStoreTest()
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : ui_thread_(content::BrowserThread::UI, &message_loop_) {}
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~HistoryDataStoreTest() {}
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // testing::Test overrides:
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Release |store_| while ui loop is still running.
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    store_ = NULL;
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OpenStore(const std::string& file_name) {
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    data_file_ = temp_dir_.path().AppendASCII(file_name);
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    store_ = new HistoryDataStore(scoped_refptr<DictionaryDataStore>(
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        new DictionaryDataStore(data_file_)));
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Load();
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void Flush() {
648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    store_->Flush(DictionaryDataStore::OnFlushedCallback());
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void Load() {
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    store_->Load(base::Bind(&HistoryDataStoreTest::OnRead,
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            base::Unretained(this)));
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    run_loop_.reset(new base::RunLoop);
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    run_loop_->Run();
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    run_loop_.reset();
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void WriteDataFile(const std::string& file_name,
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     const std::string& data) {
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    base::WriteFile(
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        temp_dir_.path().AppendASCII(file_name), data.c_str(), data.size());
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistoryDataStore* store() { return store_.get(); }
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const HistoryData::Associations& associations() const {
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return associations_;
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OnRead(scoped_ptr<HistoryData::Associations> associations) {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    associations_.clear();
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (associations)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      associations->swap(associations_);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (run_loop_)
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      run_loop_->Quit();
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::MessageLoopForUI message_loop_;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  content::TestBrowserThread ui_thread_;
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ScopedTempDir temp_dir_;
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath data_file_;
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<HistoryDataStore> store_;
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistoryData::Associations associations_;
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HistoryDataStoreTest);
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(HistoryDataStoreTest, NewFile) {
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OpenStore("new_data_file.json");
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(associations().empty());
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(HistoryDataStoreTest, BadFile) {
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kDataFile[] = "invalid_data_file";
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteDataFile(kDataFile, "invalid json");
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OpenStore(kDataFile);
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(associations().empty());
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(HistoryDataStoreTest, GoodFile) {
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kDataFile[] = "good_data_file.json";
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kGoodJson[] = "{"
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "\"version\": \"1\","
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "\"associations\": {"
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          "\"query\": {"
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             "\"p\": \"primary\","
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             "\"s\": [\"secondary1\",\"secondary2\"],"
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             "\"t\": \"123\""
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          "}"
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        "}"
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "}";
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WriteDataFile(kDataFile, kGoodJson);
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OpenStore(kDataFile);
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_FALSE(associations().empty());
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, associations().size());
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistoryData::Associations::const_iterator it = associations().find("query");
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(it != associations().end());
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ("p:primary;s:secondary1,secondary2", GetDataContent(it->second));
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(HistoryDataStoreTest, Change) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kDataFile[] = "change_test.json";
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OpenStore(kDataFile);
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(associations().empty());
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const char kQuery[] = "query";
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const base::Time now = base::Time::Now();
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  store()->SetPrimary(kQuery, "primary");
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  store()->SetUpdateTime(kQuery, now);
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Flush();
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Load();
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, associations().size());
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistoryData::Associations::const_iterator it = associations().find(kQuery);
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(it != associations().end());
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ("primary", it->second.primary);
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(0u, it->second.secondary.size());
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(now, it->second.update_time);
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  HistoryData::SecondaryDeque secondary;
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  secondary.push_back("s1");
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  secondary.push_back("s2");
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  store()->SetSecondary(kQuery, secondary);
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Flush();
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Load();
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(1u, associations().size());
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  it = associations().find(kQuery);
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(it != associations().end());
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ("p:primary;s:s1,s2", GetDataContent(it->second));
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(now, it->second.update_time);
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  store()->Delete(kQuery);
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Flush();
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Load();
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(associations().empty());
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace test
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace app_list
183