#include "sql/meta_table.h"
#include <stdint.h>
#include <string>
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "sql/database.h"
#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sql {
namespace {
class SQLMetaTableTest : public testing::Test {
public:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
ASSERT_TRUE(
db_.Open(temp_dir_.GetPath().AppendASCII("meta_table_test.sqlite")));
}
protected:
base::ScopedTempDir temp_dir_;
Database db_{test::kTestTag};
};
TEST_F(SQLMetaTableTest, DoesTableExist) {
EXPECT_FALSE(MetaTable::DoesTableExist(&db_));
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
}
EXPECT_TRUE(MetaTable::DoesTableExist(&db_));
}
TEST_F(SQLMetaTableTest, DeleteTableForTesting) {
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
EXPECT_TRUE(MetaTable::DeleteTableForTesting(&db_));
EXPECT_FALSE(MetaTable::DoesTableExist(&db_));
}
TEST_F(SQLMetaTableTest, RazeIfIncompatiblePreservesDatabasesWithoutMetadata) {
EXPECT_TRUE(db_.Execute("CREATE TABLE data(id INTEGER PRIMARY KEY)"));
ASSERT_TRUE(db_.DoesTableExist("data"));
EXPECT_EQ(RazeIfIncompatibleResult::kCompatible,
MetaTable::RazeIfIncompatible(&db_, 1,
1));
EXPECT_TRUE(db_.DoesTableExist("data"));
}
TEST_F(SQLMetaTableTest, RazeIfIncompatibleRazesIncompatiblyOldTables) {
constexpr int kWrittenVersion = 1;
constexpr int kCompatibleVersion = 1;
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, kWrittenVersion, kCompatibleVersion));
EXPECT_TRUE(db_.Execute("CREATE TABLE data(id INTEGER PRIMARY KEY)"));
ASSERT_TRUE(db_.DoesTableExist("data"));
}
EXPECT_EQ(
RazeIfIncompatibleResult::kRazedSuccessfully,
MetaTable::RazeIfIncompatible(&db_, kWrittenVersion + 1,
kWrittenVersion + 1));
EXPECT_FALSE(db_.DoesTableExist("data"));
}
TEST_F(SQLMetaTableTest, RazeIfIncompatibleRazesIncompatiblyNewTables) {
constexpr int kCompatibleVersion = 2;
constexpr int kWrittenVersion = 3;
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, kWrittenVersion, kCompatibleVersion));
EXPECT_TRUE(db_.Execute("CREATE TABLE data(id INTEGER PRIMARY KEY)"));
ASSERT_TRUE(db_.DoesTableExist("data"));
}
EXPECT_EQ(RazeIfIncompatibleResult::kRazedSuccessfully,
MetaTable::RazeIfIncompatible(
&db_, MetaTable::kNoLowestSupportedVersion,
kCompatibleVersion - 1));
EXPECT_FALSE(db_.DoesTableExist("data"));
}
TEST_F(SQLMetaTableTest, RazeIfIncompatibleDoesntRazeWhenItShouldnt) {
constexpr int kVersion = 2;
{
MetaTable meta_table;
EXPECT_TRUE(
meta_table.Init(&db_, kVersion, kVersion - 1));
EXPECT_TRUE(db_.Execute("CREATE TABLE data(id INTEGER PRIMARY KEY)"));
EXPECT_TRUE(db_.DoesTableExist("data"));
}
EXPECT_EQ(RazeIfIncompatibleResult::kCompatible,
MetaTable::RazeIfIncompatible(&db_, kVersion,
kVersion));
EXPECT_TRUE(db_.DoesTableExist("data"))
<< "Table should still exist if the database version is exactly right.";
EXPECT_EQ(RazeIfIncompatibleResult::kCompatible,
MetaTable::RazeIfIncompatible(&db_, kVersion - 1,
kVersion));
EXPECT_TRUE(db_.DoesTableExist("data"))
<< "... or if the lower bound is less than the actual version";
EXPECT_EQ(
RazeIfIncompatibleResult::kCompatible,
MetaTable::RazeIfIncompatible(&db_, MetaTable::kNoLowestSupportedVersion,
kVersion));
EXPECT_TRUE(db_.DoesTableExist("data"))
<< "... or if the lower bound is not set";
EXPECT_EQ(
RazeIfIncompatibleResult::kCompatible,
MetaTable::RazeIfIncompatible(&db_, MetaTable::kNoLowestSupportedVersion,
kVersion - 1));
EXPECT_TRUE(db_.DoesTableExist("data"))
<< "... even if the current version exactly matches the written "
"database's least compatible version.";
}
TEST_F(SQLMetaTableTest, VersionNumber) {
constexpr int kVersionFirst = 2;
constexpr int kCompatVersionFirst = kVersionFirst - 1;
constexpr int kVersionSecond = 4;
constexpr int kCompatVersionSecond = kVersionSecond - 1;
constexpr int kVersionThird = 6;
constexpr int kCompatVersionThird = kVersionThird - 1;
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, kVersionFirst, kCompatVersionFirst));
EXPECT_EQ(kVersionFirst, meta_table.GetVersionNumber());
EXPECT_EQ(kCompatVersionFirst, meta_table.GetCompatibleVersionNumber());
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, kVersionSecond, kCompatVersionSecond));
EXPECT_EQ(kVersionFirst, meta_table.GetVersionNumber());
EXPECT_EQ(kCompatVersionFirst, meta_table.GetCompatibleVersionNumber());
EXPECT_TRUE(meta_table.SetVersionNumber(kVersionSecond));
EXPECT_TRUE(meta_table.SetCompatibleVersionNumber(kCompatVersionSecond));
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, kVersionThird, kCompatVersionThird));
EXPECT_EQ(kVersionSecond, meta_table.GetVersionNumber());
EXPECT_EQ(kCompatVersionSecond, meta_table.GetCompatibleVersionNumber());
}
}
TEST_F(SQLMetaTableTest, StringValue) {
static const char kKey[] = "String Key";
const std::string kFirstValue("First Value");
const std::string kSecondValue("Second Value");
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
std::string value;
EXPECT_FALSE(meta_table.GetValue(kKey, &value));
EXPECT_TRUE(meta_table.SetValue(kKey, kFirstValue));
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kFirstValue, value);
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
std::string value;
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kFirstValue, value);
EXPECT_TRUE(meta_table.SetValue(kKey, kSecondValue));
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
std::string value;
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kSecondValue, value);
}
}
TEST_F(SQLMetaTableTest, IntValue) {
static const char kKey[] = "Int Key";
constexpr int kFirstValue = 17;
constexpr int kSecondValue = 23;
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
int value;
EXPECT_FALSE(meta_table.GetValue(kKey, &value));
EXPECT_TRUE(meta_table.SetValue(kKey, kFirstValue));
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kFirstValue, value);
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
int value;
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kFirstValue, value);
EXPECT_TRUE(meta_table.SetValue(kKey, kSecondValue));
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
int value;
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kSecondValue, value);
}
}
TEST_F(SQLMetaTableTest, Int64Value) {
static const char kKey[] = "Int Key";
const int64_t kFirstValue = 5000000017LL;
const int64_t kSecondValue = 5000000023LL;
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
int64_t value;
EXPECT_FALSE(meta_table.GetValue(kKey, &value));
EXPECT_TRUE(meta_table.SetValue(kKey, kFirstValue));
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kFirstValue, value);
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
int64_t value;
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kFirstValue, value);
EXPECT_TRUE(meta_table.SetValue(kKey, kSecondValue));
}
{
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
int64_t value;
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kSecondValue, value);
}
}
TEST_F(SQLMetaTableTest, DeleteKey) {
static const char kKey[] = "String Key";
const std::string kValue("String Value");
MetaTable meta_table;
EXPECT_TRUE(meta_table.Init(&db_, 1, 1));
std::string value;
EXPECT_FALSE(meta_table.GetValue(kKey, &value));
EXPECT_TRUE(meta_table.SetValue(kKey, kValue));
EXPECT_TRUE(meta_table.GetValue(kKey, &value));
EXPECT_EQ(kValue, value);
EXPECT_TRUE(meta_table.DeleteKey(kKey));
EXPECT_FALSE(meta_table.GetValue(kKey, &value));
}
}
}