blob: 9fc9ec48fe395b608425cdc44174c52b4b0bfa96 [file] [log] [blame]
// Copyright 2011 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 "components/sessions/core/session_backend.h"
#include <stddef.h>
#include <utility>
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sessions {
namespace {
typedef std::vector<std::unique_ptr<sessions::SessionCommand>> SessionCommands;
struct TestData {
sessions::SessionCommand::id_type command_id;
std::string data;
};
std::unique_ptr<sessions::SessionCommand> CreateCommandFromData(
const TestData& data) {
std::unique_ptr<sessions::SessionCommand> command =
std::make_unique<sessions::SessionCommand>(
data.command_id,
static_cast<sessions::SessionCommand::size_type>(data.data.size()));
if (!data.data.empty())
memcpy(command->contents(), data.data.c_str(), data.data.size());
return command;
}
} // namespace
class SessionBackendTest : public testing::Test {
protected:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
path_ = temp_dir_.GetPath().Append(FILE_PATH_LITERAL("SessionTestDirs"));
base::CreateDirectory(path_);
}
void AssertCommandEqualsData(const TestData& data,
sessions::SessionCommand* command) {
EXPECT_EQ(data.command_id, command->id());
EXPECT_EQ(data.data.size(), command->size());
EXPECT_TRUE(
memcmp(command->contents(), data.data.c_str(), command->size()) == 0);
}
// Path used in testing.
base::FilePath path_;
base::ScopedTempDir temp_dir_;
};
TEST_F(SessionBackendTest, SimpleReadWrite) {
scoped_refptr<SessionBackend> backend(
new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE, path_));
struct TestData data = { 1, "a" };
SessionCommands commands;
commands.push_back(CreateCommandFromData(data));
backend->AppendCommands(std::move(commands), false);
ASSERT_TRUE(commands.empty());
// Read it back in.
backend = nullptr;
backend = new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE,
path_);
backend->ReadLastSessionCommandsImpl(&commands);
ASSERT_EQ(1U, commands.size());
AssertCommandEqualsData(data, commands[0].get());
commands.clear();
backend = nullptr;
backend = new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE,
path_);
backend->ReadLastSessionCommandsImpl(&commands);
ASSERT_EQ(0U, commands.size());
// Make sure we can delete.
backend->DeleteLastSession();
backend->ReadLastSessionCommandsImpl(&commands);
ASSERT_EQ(0U, commands.size());
}
TEST_F(SessionBackendTest, RandomData) {
struct TestData data[] = {
{ 1, "a" },
{ 2, "ab" },
{ 3, "abc" },
{ 4, "abcd" },
{ 5, "abcde" },
{ 6, "abcdef" },
{ 7, "abcdefg" },
{ 8, "abcdefgh" },
{ 9, "abcdefghi" },
{ 10, "abcdefghij" },
{ 11, "abcdefghijk" },
{ 12, "abcdefghijkl" },
{ 13, "abcdefghijklm" },
};
for (size_t i = 0; i < base::size(data); ++i) {
scoped_refptr<SessionBackend> backend(
new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE,
path_));
SessionCommands commands;
if (i != 0) {
// Read previous data.
backend->ReadLastSessionCommandsImpl(&commands);
ASSERT_EQ(i, commands.size());
for (auto j = commands.begin(); j != commands.end(); ++j)
AssertCommandEqualsData(data[j - commands.begin()], j->get());
backend->AppendCommands(std::move(commands), false);
}
commands.push_back(CreateCommandFromData(data[i]));
backend->AppendCommands(std::move(commands), false);
}
}
TEST_F(SessionBackendTest, BigData) {
struct TestData data[] = {
{ 1, "a" },
{ 2, "ab" },
};
scoped_refptr<SessionBackend> backend(
new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE, path_));
std::vector<std::unique_ptr<sessions::SessionCommand>> commands;
commands.push_back(CreateCommandFromData(data[0]));
const sessions::SessionCommand::size_type big_size =
SessionBackend::kFileReadBufferSize + 100;
const sessions::SessionCommand::id_type big_id = 50;
std::unique_ptr<sessions::SessionCommand> big_command =
std::make_unique<sessions::SessionCommand>(big_id, big_size);
reinterpret_cast<char*>(big_command->contents())[0] = 'a';
reinterpret_cast<char*>(big_command->contents())[big_size - 1] = 'z';
commands.push_back(std::move(big_command));
commands.push_back(CreateCommandFromData(data[1]));
backend->AppendCommands(std::move(commands), false);
backend = nullptr;
backend = new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE,
path_);
backend->ReadLastSessionCommandsImpl(&commands);
ASSERT_EQ(3U, commands.size());
AssertCommandEqualsData(data[0], commands[0].get());
AssertCommandEqualsData(data[1], commands[2].get());
EXPECT_EQ(big_id, commands[1]->id());
ASSERT_EQ(big_size, commands[1]->size());
EXPECT_EQ('a', reinterpret_cast<char*>(commands[1]->contents())[0]);
EXPECT_EQ('z',
reinterpret_cast<char*>(commands[1]->contents())[big_size - 1]);
commands.clear();
}
TEST_F(SessionBackendTest, EmptyCommand) {
TestData empty_command;
empty_command.command_id = 1;
scoped_refptr<SessionBackend> backend(
new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE, path_));
SessionCommands empty_commands;
empty_commands.push_back(CreateCommandFromData(empty_command));
backend->AppendCommands(std::move(empty_commands), true);
backend->MoveCurrentSessionToLastSession();
SessionCommands commands;
backend->ReadLastSessionCommandsImpl(&commands);
ASSERT_EQ(1U, commands.size());
AssertCommandEqualsData(empty_command, commands[0].get());
commands.clear();
}
// Writes a command, appends another command with reset to true, then reads
// making sure we only get back the second command.
TEST_F(SessionBackendTest, Truncate) {
scoped_refptr<SessionBackend> backend(
new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE, path_));
struct TestData first_data = { 1, "a" };
SessionCommands commands;
commands.push_back(CreateCommandFromData(first_data));
backend->AppendCommands(std::move(commands), false);
// Write another command, this time resetting the file when appending.
struct TestData second_data = { 2, "b" };
commands.push_back(CreateCommandFromData(second_data));
backend->AppendCommands(std::move(commands), true);
// Read it back in.
backend = nullptr;
backend = new SessionBackend(sessions::BaseSessionService::SESSION_RESTORE,
path_);
backend->ReadLastSessionCommandsImpl(&commands);
// And make sure we get back the expected data.
ASSERT_EQ(1U, commands.size());
AssertCommandEqualsData(second_data, commands[0].get());
commands.clear();
}
} // namespace sessions