shortcuts_database_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/scoped_temp_dir.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/shortcuts_database.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace history {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ShortcutsDatabaseTestInfo {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string guid;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string title;  // The text that orginally was searched for.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string contents;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string contents_class;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string description;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string description_class;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int typed_count;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int days_from_now;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} shortcut_test_db[] = {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "BD85DBA2-8C29-49F9-84AE-48E1E90880DF",
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://www.google.com/", "goog",
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Google", "0,1,4,0", "Google", "0,3,4,1", 100, 1 },
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "BD85DBA2-8C29-49F9-84AE-48E1E90880E0",
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://slashdot.org/", "slash",
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "slashdot.org", "0,3,5,1",
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Slashdot - News for nerds, stuff that matters", "0,2,5,0", 100, 0},
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { "BD85DBA2-8C29-49F9-84AE-48E1E90880E1",
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "http://slashdot.org/", "news",
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "slashdot.org", "0,1",
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Slashdot - News for nerds, stuff that matters", "0,0,11,2,15,0", 5, 0},
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ShortcutsDatabaseTest : public testing::Test {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetUp();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TearDown();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearDB();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t CountRecords() const;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsBackend::Shortcut ShortcutFromTestInfo(
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ShortcutsDatabaseTestInfo& info);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddAll();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ShortcutsDatabase> db_;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShortcutsDatabaseTest::SetUp() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_.reset(new TestingProfile());
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_ = new ShortcutsDatabase(profile_.get());
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(db_->Init());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearDB();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShortcutsDatabaseTest::TearDown() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_ = NULL;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShortcutsDatabaseTest::ClearDB() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s(db_->db_.GetUniqueStatement("DELETE FROM omni_box_shortcuts"));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(s.Run());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ShortcutsDatabaseTest::CountRecords() const {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->db_.GetUniqueStatement(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SELECT count(*) FROM omni_box_shortcuts"));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(s.Step());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<size_t>(s.ColumnInt(0));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ShortcutsBackend::Shortcut ShortcutsDatabaseTest::ShortcutFromTestInfo(
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ShortcutsDatabaseTestInfo& info) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ShortcutsBackend::Shortcut(info.guid, ASCIIToUTF16(info.title),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL(info.url), ASCIIToUTF16(info.contents),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AutocompleteMatch::ClassificationsFromString(info.contents_class),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASCIIToUTF16(info.description),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AutocompleteMatch::ClassificationsFromString(info.description_class),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Time::Now() - base::TimeDelta::FromDays(info.days_from_now),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info.typed_count);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShortcutsDatabaseTest::AddAll() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearDB();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(shortcut_test_db); ++i) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    db_->AddShortcut(ShortcutFromTestInfo(shortcut_test_db[i]));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(arraysize(shortcut_test_db), CountRecords());
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ShortcutsDatabaseTest, AddShortcut) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClearDB();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, CountRecords());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->AddShortcut(ShortcutFromTestInfo(shortcut_test_db[0])));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, CountRecords());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->AddShortcut(ShortcutFromTestInfo(shortcut_test_db[1])));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, CountRecords());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->AddShortcut(ShortcutFromTestInfo(shortcut_test_db[2])));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, CountRecords());
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ShortcutsDatabaseTest, UpdateShortcut) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAll();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsBackend::Shortcut shortcut(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShortcutFromTestInfo(shortcut_test_db[1]));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shortcut.contents = ASCIIToUTF16("gro.todhsals");
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->UpdateShortcut(shortcut));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap shortcuts;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap::iterator it =
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shortcuts.find(shortcut.id);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it != shortcuts.end());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it->second.contents == shortcut.contents);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ShortcutsDatabaseTest, DeleteShortcutsWithIds) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAll();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> shortcut_ids;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shortcut_ids.push_back(shortcut_test_db[0].guid);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  shortcut_ids.push_back(shortcut_test_db[2].guid);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->DeleteShortcutsWithIds(shortcut_ids));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(arraysize(shortcut_test_db) - 2, CountRecords());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap shortcuts;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap::iterator it =
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shortcuts.find(shortcut_test_db[0].guid);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it == shortcuts.end());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it = shortcuts.find(shortcut_test_db[1].guid);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it != shortcuts.end());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it = shortcuts.find(shortcut_test_db[2].guid);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it == shortcuts.end());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ShortcutsDatabaseTest, DeleteShortcutsWithUrl) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAll();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->DeleteShortcutsWithUrl("http://slashdot.org/"));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(arraysize(shortcut_test_db) - 2, CountRecords());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap shortcuts;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap::iterator it =
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shortcuts.find(shortcut_test_db[0].guid);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it != shortcuts.end());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it = shortcuts.find(shortcut_test_db[1].guid);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it == shortcuts.end());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  it = shortcuts.find(shortcut_test_db[2].guid);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(it == shortcuts.end());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ShortcutsDatabaseTest, LoadShortcuts) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAll();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap shortcuts;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(shortcut_test_db); ++i) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE(base::StringPrintf("Looking for shortcut #%d",
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<int>(i)));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(shortcuts.find(shortcut_test_db[i].guid) != shortcuts.end());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ShortcutsDatabaseTest, DeleteAllShortcuts) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddAll();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShortcutsDatabase::GuidToShortcutMap shortcuts;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(arraysize(shortcut_test_db), shortcuts.size());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->DeleteAllShortcuts());
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(db_->LoadShortcuts(&shortcuts));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, shortcuts.size());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace history
193