This source file includes following definitions.
- Wait
- OnTimeOut
- OnHistoryDataLoadedFromStore
- Wait
- OnTimeOut
- OnFlushed
- SetUp
- TearDown
- CreateHistory
- Flush
- GetKnownResults
- GetResultType
- history
- associations
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/app_list/search/history.h"
#include "chrome/browser/ui/app_list/search/history_data.h"
#include "chrome/browser/ui/app_list/search/history_data_observer.h"
#include "chrome/browser/ui/app_list/search/history_data_store.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace app_list {
namespace test {
namespace {
const size_t kMaxPrimary = 3;
const size_t kMaxSecondary = 2;
class HistoryDataLoadWaiter : public HistoryDataObserver {
public:
explicit HistoryDataLoadWaiter(HistoryData* data) : data_(data) {}
virtual ~HistoryDataLoadWaiter() {}
void Wait(int timeout_ms) {
data_->AddObserver(this);
timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(timeout_ms),
this,
&HistoryDataLoadWaiter::OnTimeOut);
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
data_->RemoveObserver(this);
}
private:
void OnTimeOut() {
run_loop_->Quit();
}
virtual void OnHistoryDataLoadedFromStore() OVERRIDE {
run_loop_->Quit();
}
HistoryData* data_;
scoped_ptr<base::RunLoop> run_loop_;
base::OneShotTimer<HistoryDataLoadWaiter> timer_;
DISALLOW_COPY_AND_ASSIGN(HistoryDataLoadWaiter);
};
class StoreFlushWaiter {
public:
explicit StoreFlushWaiter(HistoryDataStore* store) : store_(store) {}
~StoreFlushWaiter() {}
void Wait(int timeout_ms) {
store_->Flush(
base::Bind(&StoreFlushWaiter::OnFlushed, base::Unretained(this)));
timer_.Start(FROM_HERE,
base::TimeDelta::FromMilliseconds(timeout_ms),
this,
&StoreFlushWaiter::OnTimeOut);
run_loop_.reset(new base::RunLoop);
run_loop_->Run();
}
private:
void OnTimeOut() {
run_loop_->Quit();
}
void OnFlushed() {
run_loop_->Quit();
}
HistoryDataStore* store_;
scoped_ptr<base::RunLoop> run_loop_;
base::OneShotTimer<StoreFlushWaiter> timer_;
DISALLOW_COPY_AND_ASSIGN(StoreFlushWaiter);
};
}
class SearchHistoryTest : public testing::Test {
public:
SearchHistoryTest()
: ui_thread_(content::BrowserThread::UI, &message_loop_) {}
virtual ~SearchHistoryTest() {}
virtual void SetUp() OVERRIDE {
profile_.reset(new TestingProfile);
CreateHistory();
}
virtual void TearDown() OVERRIDE {
Flush();
}
void CreateHistory() {
history_.reset(new History(profile_.get()));
history_->data_->RemoveObserver(history_.get());
history_->data_.reset(
new HistoryData(history_->store_.get(), kMaxPrimary, kMaxSecondary));
history_->data_->AddObserver(history_.get());
HistoryDataLoadWaiter waiter(history_->data_.get());
waiter.Wait(1000);
ASSERT_TRUE(history_->IsReady());
}
void Flush() {
StoreFlushWaiter waiter(history_->store_.get());
waiter.Wait(1000);
}
size_t GetKnownResults(const std::string& query) {
known_results_ = history()->GetKnownResults(query).Pass();
return known_results_->size();
}
KnownResultType GetResultType(const std::string& result_id) {
return known_results_->find(result_id) != known_results_->end()
? (*known_results_.get())[result_id]
: UNKNOWN_RESULT;
}
History* history() { return history_.get(); }
const HistoryData::Associations& associations() const {
return history_->data_->associations();
}
private:
base::MessageLoopForUI message_loop_;
content::TestBrowserThread ui_thread_;
scoped_ptr<TestingProfile> profile_;
scoped_ptr<History> history_;
scoped_ptr<KnownResults> known_results_;
DISALLOW_COPY_AND_ASSIGN(SearchHistoryTest);
};
TEST_F(SearchHistoryTest, Persistence) {
EXPECT_EQ(0u, GetKnownResults("cal"));
history()->AddLaunchEvent("cal", "calendar");
EXPECT_EQ(1u, GetKnownResults("cal"));
Flush();
CreateHistory();
EXPECT_EQ(1u, GetKnownResults("cal"));
}
TEST_F(SearchHistoryTest, PerfectAndPrefixMatch) {
const char kQuery[] = "cal";
const char kQueryPrefix[] = "c";
const char kPrimary[] = "calendar";
const char kSecondary[] = "calculator";
history()->AddLaunchEvent(kQuery, kPrimary);
history()->AddLaunchEvent(kQuery, kSecondary);
EXPECT_EQ(2u, GetKnownResults(kQuery));
EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
EXPECT_EQ(2u, GetKnownResults(kQueryPrefix));
EXPECT_EQ(PREFIX_PRIMARY, GetResultType(kPrimary));
EXPECT_EQ(PREFIX_SECONDARY, GetResultType(kSecondary));
}
TEST_F(SearchHistoryTest, StickyPrimary) {
const char kQuery[] = "cal";
const char kPrimary[] = "calendar";
const char kSecondary[] = "calculator";
const char kOther[] = "other";
history()->AddLaunchEvent(kQuery, kPrimary);
history()->AddLaunchEvent(kQuery, kSecondary);
EXPECT_EQ(2u, GetKnownResults(kQuery));
EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
history()->AddLaunchEvent(kQuery, kPrimary);
history()->AddLaunchEvent(kQuery, kSecondary);
history()->AddLaunchEvent(kQuery, kPrimary);
history()->AddLaunchEvent(kQuery, kSecondary);
history()->AddLaunchEvent(kQuery, kPrimary);
history()->AddLaunchEvent(kQuery, kSecondary);
history()->AddLaunchEvent(kQuery, kOther);
history()->AddLaunchEvent(kQuery, kSecondary);
history()->AddLaunchEvent(kQuery, kOther);
history()->AddLaunchEvent(kQuery, kSecondary);
history()->AddLaunchEvent(kQuery, kOther);
EXPECT_EQ(3u, GetKnownResults(kQuery));
EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kOther));
}
TEST_F(SearchHistoryTest, PromoteSecondary) {
const char kQuery[] = "cal";
const char kPrimary[] = "calendar";
const char kSecondary[] = "calculator";
history()->AddLaunchEvent(kQuery, kPrimary);
history()->AddLaunchEvent(kQuery, kSecondary);
EXPECT_EQ(2u, GetKnownResults(kQuery));
EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kPrimary));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kSecondary));
history()->AddLaunchEvent(kQuery, kSecondary);
EXPECT_EQ(2u, GetKnownResults(kQuery));
EXPECT_EQ(PERFECT_PRIMARY, GetResultType(kSecondary));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType(kPrimary));
}
TEST_F(SearchHistoryTest, MaxPrimary) {
for (size_t i = 0; i < kMaxPrimary; ++i) {
std::string query = base::StringPrintf("%d", static_cast<int>(i));
history()->AddLaunchEvent(query, "app");
}
EXPECT_EQ(kMaxPrimary, associations().size());
EXPECT_TRUE(associations().find("0") != associations().end());
EXPECT_TRUE(associations().find("1") != associations().end());
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(25));
history()->AddLaunchEvent("0", "app");
history()->AddLaunchEvent("extra", "app");
EXPECT_EQ(kMaxPrimary, associations().size());
EXPECT_FALSE(associations().find("1") != associations().end());
EXPECT_TRUE(associations().find("0") != associations().end());
}
TEST_F(SearchHistoryTest, MaxSecondary) {
const char kQuery[] = "query";
history()->AddLaunchEvent(kQuery, "primary");
for (size_t i = 0; i < kMaxSecondary; ++i) {
std::string result_id = base::StringPrintf("%d", static_cast<int>(i));
history()->AddLaunchEvent(kQuery, result_id);
}
EXPECT_EQ(kMaxSecondary + 1, GetKnownResults(kQuery));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType("0"));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType("1"));
history()->AddLaunchEvent(kQuery, "0");
history()->AddLaunchEvent(kQuery, "extra");
EXPECT_EQ(kMaxSecondary + 1, GetKnownResults(kQuery));
EXPECT_EQ(UNKNOWN_RESULT, GetResultType("1"));
EXPECT_EQ(PERFECT_SECONDARY, GetResultType("0"));
}
}
}