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/files/scoped_temp_dir.h" 6#include "base/strings/stringprintf.h" 7#include "chrome/browser/extensions/activity_log/database_string_table.h" 8#include "sql/connection.h" 9#include "sql/statement.h" 10#include "sql/transaction.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13namespace extensions { 14 15class DatabaseStringTableTest : public testing::Test { 16 protected: 17 virtual void SetUp() OVERRIDE { 18 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 19 base::FilePath db_file = temp_dir_.path().AppendASCII("StringTable.db"); 20 21 ASSERT_TRUE(db_.Open(db_file)); 22 } 23 24 virtual void TearDown() OVERRIDE { 25 db_.Close(); 26 } 27 28 base::ScopedTempDir temp_dir_; 29 sql::Connection db_; 30}; 31 32// Check that initializing the database works. 33TEST_F(DatabaseStringTableTest, Init) { 34 DatabaseStringTable table("test"); 35 table.Initialize(&db_); 36 ASSERT_TRUE(db_.DoesTableExist("test")); 37 ASSERT_TRUE(db_.DoesIndexExist("test_index")); 38} 39 40// Insert a new mapping into the table, then verify the table contents. 41TEST_F(DatabaseStringTableTest, Insert) { 42 DatabaseStringTable table("test"); 43 table.Initialize(&db_); 44 int64 id; 45 ASSERT_TRUE(table.StringToInt(&db_, "abc", &id)); 46 47 sql::Statement query( 48 db_.GetUniqueStatement("SELECT id FROM test WHERE value = 'abc'")); 49 ASSERT_TRUE(query.Step()); 50 int64 raw_id = query.ColumnInt64(0); 51 ASSERT_EQ(id, raw_id); 52} 53 54// Check that different strings are mapped to different values, and the same 55// string is mapped to the same value repeatably. 56TEST_F(DatabaseStringTableTest, InsertMultiple) { 57 DatabaseStringTable table("test"); 58 table.Initialize(&db_); 59 60 int64 id1; 61 int64 id2; 62 ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1)); 63 ASSERT_TRUE(table.StringToInt(&db_, "string2", &id2)); 64 ASSERT_NE(id1, id2); 65 66 int64 id1a; 67 ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1a)); 68 ASSERT_EQ(id1, id1a); 69} 70 71// Check that values can be read back from the database even after the 72// in-memory cache is cleared. 73TEST_F(DatabaseStringTableTest, CacheCleared) { 74 DatabaseStringTable table("test"); 75 table.Initialize(&db_); 76 77 int64 id1; 78 ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1)); 79 80 table.ClearCache(); 81 82 int64 id2; 83 ASSERT_TRUE(table.StringToInt(&db_, "string1", &id2)); 84 ASSERT_EQ(id1, id2); 85} 86 87// Check that direct database modifications are picked up after the cache is 88// cleared. 89TEST_F(DatabaseStringTableTest, DatabaseModified) { 90 DatabaseStringTable table("test"); 91 table.Initialize(&db_); 92 93 int64 id1; 94 ASSERT_TRUE(table.StringToInt(&db_, "modified", &id1)); 95 96 ASSERT_TRUE( 97 db_.Execute("UPDATE test SET id = id + 1 WHERE value = 'modified'")); 98 99 int64 id2; 100 ASSERT_TRUE(table.StringToInt(&db_, "modified", &id2)); 101 ASSERT_EQ(id1, id2); 102 103 table.ClearCache(); 104 105 int64 id3; 106 ASSERT_TRUE(table.StringToInt(&db_, "modified", &id3)); 107 ASSERT_EQ(id1 + 1, id3); 108} 109 110// Check that looking up an unknown id returns an error. 111TEST_F(DatabaseStringTableTest, BadLookup) { 112 DatabaseStringTable table("test"); 113 table.Initialize(&db_); 114 std::string value; 115 ASSERT_FALSE(table.IntToString(&db_, 1, &value)); 116} 117 118// Check looking up an inserted value, both cached and not cached. 119TEST_F(DatabaseStringTableTest, Lookup) { 120 DatabaseStringTable table("test"); 121 table.Initialize(&db_); 122 int64 id; 123 ASSERT_TRUE(table.StringToInt(&db_, "abc", &id)); 124 125 std::string value; 126 ASSERT_TRUE(table.IntToString(&db_, id, &value)); 127 ASSERT_EQ("abc", value); 128 129 table.ClearCache(); 130 value = ""; 131 ASSERT_TRUE(table.IntToString(&db_, id, &value)); 132 ASSERT_EQ("abc", value); 133} 134 135// Check that the in-memory cache for the string table does not become too 136// large, even if many items are inserted. 137TEST_F(DatabaseStringTableTest, Prune) { 138 DatabaseStringTable table("size_test"); 139 table.Initialize(&db_); 140 141 // Wrap the lookups in a transaction to improve performance. 142 sql::Transaction transaction(&db_); 143 144 transaction.Begin(); 145 for (int i = 0; i < 2000; i++) { 146 int64 id; 147 ASSERT_TRUE(table.StringToInt(&db_, base::StringPrintf("value-%d", i), 148 &id)); 149 } 150 transaction.Commit(); 151 152 // The maximum size below should correspond to kMaximumCacheSize in 153 // database_string_table.cc, with a small amount of additional slop (an entry 154 // might be inserted after doing the pruning). 155 ASSERT_LE(table.id_to_value_.size(), 1005U); 156 ASSERT_LE(table.value_to_id_.size(), 1005U); 157} 158 159} // namespace extensions 160