blob: 2fcbbe0a229e6f13f38ca2f63a3a3ad32dcc92dc [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <stdint.h>
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/activity_log/database_string_table.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "sql/transaction.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
class DatabaseStringTableTest : public testing::Test {
protected:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
base::FilePath db_file = temp_dir_.GetPath().AppendASCII("StringTable.db");
ASSERT_TRUE(db_.Open(db_file));
}
void TearDown() override { db_.Close(); }
base::ScopedTempDir temp_dir_;
sql::Database db_;
};
// Check that initializing the database works.
TEST_F(DatabaseStringTableTest, Init) {
DatabaseStringTable table("test");
table.Initialize(&db_);
ASSERT_TRUE(db_.DoesTableExist("test"));
ASSERT_TRUE(db_.DoesIndexExist("test_index"));
}
// Insert a new mapping into the table, then verify the table contents.
TEST_F(DatabaseStringTableTest, Insert) {
DatabaseStringTable table("test");
table.Initialize(&db_);
int64_t id;
ASSERT_TRUE(table.StringToInt(&db_, "abc", &id));
sql::Statement query(
db_.GetUniqueStatement("SELECT id FROM test WHERE value = 'abc'"));
ASSERT_TRUE(query.Step());
int64_t raw_id = query.ColumnInt64(0);
ASSERT_EQ(id, raw_id);
}
// Check that different strings are mapped to different values, and the same
// string is mapped to the same value repeatably.
TEST_F(DatabaseStringTableTest, InsertMultiple) {
DatabaseStringTable table("test");
table.Initialize(&db_);
int64_t id1;
int64_t id2;
ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1));
ASSERT_TRUE(table.StringToInt(&db_, "string2", &id2));
ASSERT_NE(id1, id2);
int64_t id1a;
ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1a));
ASSERT_EQ(id1, id1a);
}
// Check that values can be read back from the database even after the
// in-memory cache is cleared.
TEST_F(DatabaseStringTableTest, CacheCleared) {
DatabaseStringTable table("test");
table.Initialize(&db_);
int64_t id1;
ASSERT_TRUE(table.StringToInt(&db_, "string1", &id1));
table.ClearCache();
int64_t id2;
ASSERT_TRUE(table.StringToInt(&db_, "string1", &id2));
ASSERT_EQ(id1, id2);
}
// Check that direct database modifications are picked up after the cache is
// cleared.
TEST_F(DatabaseStringTableTest, DatabaseModified) {
DatabaseStringTable table("test");
table.Initialize(&db_);
int64_t id1;
ASSERT_TRUE(table.StringToInt(&db_, "modified", &id1));
ASSERT_TRUE(
db_.Execute("UPDATE test SET id = id + 1 WHERE value = 'modified'"));
int64_t id2;
ASSERT_TRUE(table.StringToInt(&db_, "modified", &id2));
ASSERT_EQ(id1, id2);
table.ClearCache();
int64_t id3;
ASSERT_TRUE(table.StringToInt(&db_, "modified", &id3));
ASSERT_EQ(id1 + 1, id3);
}
// Check that looking up an unknown id returns an error.
TEST_F(DatabaseStringTableTest, BadLookup) {
DatabaseStringTable table("test");
table.Initialize(&db_);
std::string value;
ASSERT_FALSE(table.IntToString(&db_, 1, &value));
}
// Check looking up an inserted value, both cached and not cached.
TEST_F(DatabaseStringTableTest, Lookup) {
DatabaseStringTable table("test");
table.Initialize(&db_);
int64_t id;
ASSERT_TRUE(table.StringToInt(&db_, "abc", &id));
std::string value;
ASSERT_TRUE(table.IntToString(&db_, id, &value));
ASSERT_EQ("abc", value);
table.ClearCache();
value = "";
ASSERT_TRUE(table.IntToString(&db_, id, &value));
ASSERT_EQ("abc", value);
}
// Check that the in-memory cache for the string table does not become too
// large, even if many items are inserted.
TEST_F(DatabaseStringTableTest, Prune) {
DatabaseStringTable table("size_test");
table.Initialize(&db_);
// Wrap the lookups in a transaction to improve performance.
sql::Transaction transaction(&db_);
transaction.Begin();
for (int i = 0; i < 2000; i++) {
int64_t id;
ASSERT_TRUE(table.StringToInt(&db_, base::StringPrintf("value-%d", i),
&id));
}
transaction.Commit();
// The maximum size below should correspond to kMaximumCacheSize in
// database_string_table.cc, with a small amount of additional slop (an entry
// might be inserted after doing the pruning).
ASSERT_LE(table.id_to_value_.size(), 1005U);
ASSERT_LE(table.value_to_id_.size(), 1005U);
}
} // namespace extensions