Home | History | Annotate | Download | only in sessions
      1 // Copyright (c) 2011 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/file_util.h"
      6 #include "base/files/scoped_temp_dir.h"
      7 #include "base/stl_util.h"
      8 #include "base/strings/string_util.h"
      9 #include "chrome/browser/sessions/session_backend.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 namespace {
     13 
     14 typedef std::vector<SessionCommand*> SessionCommands;
     15 
     16 struct TestData {
     17   SessionCommand::id_type command_id;
     18   std::string data;
     19 };
     20 
     21 SessionCommand* CreateCommandFromData(const TestData& data) {
     22   SessionCommand* command =
     23       new SessionCommand(
     24           data.command_id,
     25           static_cast<SessionCommand::size_type>(data.data.size()));
     26   if (!data.data.empty())
     27     memcpy(command->contents(), data.data.c_str(), data.data.size());
     28   return command;
     29 }
     30 
     31 }  // namespace
     32 
     33 class SessionBackendTest : public testing::Test {
     34  protected:
     35   virtual void SetUp() {
     36     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     37     path_ = temp_dir_.path().Append(FILE_PATH_LITERAL("SessionTestDirs"));
     38     file_util::CreateDirectory(path_);
     39   }
     40 
     41   void AssertCommandEqualsData(const TestData& data, SessionCommand* command) {
     42     EXPECT_EQ(data.command_id, command->id());
     43     EXPECT_EQ(data.data.size(), command->size());
     44     EXPECT_TRUE(
     45         memcmp(command->contents(), data.data.c_str(), command->size()) == 0);
     46   }
     47 
     48   // Path used in testing.
     49   base::FilePath path_;
     50   base::ScopedTempDir temp_dir_;
     51 };
     52 
     53 TEST_F(SessionBackendTest, SimpleReadWrite) {
     54   scoped_refptr<SessionBackend> backend(
     55       new SessionBackend(BaseSessionService::SESSION_RESTORE, path_));
     56   struct TestData data = { 1,  "a" };
     57   std::vector<SessionCommand*> commands;
     58   commands.push_back(CreateCommandFromData(data));
     59   backend->AppendCommands(new SessionCommands(commands), false);
     60   commands.clear();
     61 
     62   // Read it back in.
     63   backend = NULL;
     64   backend = new SessionBackend(BaseSessionService::SESSION_RESTORE, path_);
     65   backend->ReadLastSessionCommandsImpl(&commands);
     66 
     67   ASSERT_EQ(1U, commands.size());
     68   AssertCommandEqualsData(data, commands[0]);
     69 
     70   STLDeleteElements(&commands);
     71 
     72   backend = NULL;
     73   backend = new SessionBackend(BaseSessionService::SESSION_RESTORE, path_);
     74   backend->ReadLastSessionCommandsImpl(&commands);
     75 
     76   ASSERT_EQ(0U, commands.size());
     77 
     78   // Make sure we can delete.
     79   backend->DeleteLastSession();
     80   backend->ReadLastSessionCommandsImpl(&commands);
     81   ASSERT_EQ(0U, commands.size());
     82 }
     83 
     84 TEST_F(SessionBackendTest, RandomData) {
     85   struct TestData data[] = {
     86     { 1,  "a" },
     87     { 2,  "ab" },
     88     { 3,  "abc" },
     89     { 4,  "abcd" },
     90     { 5,  "abcde" },
     91     { 6,  "abcdef" },
     92     { 7,  "abcdefg" },
     93     { 8,  "abcdefgh" },
     94     { 9,  "abcdefghi" },
     95     { 10, "abcdefghij" },
     96     { 11, "abcdefghijk" },
     97     { 12, "abcdefghijkl" },
     98     { 13, "abcdefghijklm" },
     99   };
    100 
    101   for (size_t i = 0; i < arraysize(data); ++i) {
    102     scoped_refptr<SessionBackend> backend(
    103         new SessionBackend(BaseSessionService::SESSION_RESTORE, path_));
    104     std::vector<SessionCommand*> commands;
    105     if (i != 0) {
    106       // Read previous data.
    107       backend->ReadLastSessionCommandsImpl(&commands);
    108       ASSERT_EQ(i, commands.size());
    109       for (std::vector<SessionCommand*>::iterator j = commands.begin();
    110            j != commands.end(); ++j) {
    111         AssertCommandEqualsData(data[j - commands.begin()], *j);
    112       }
    113       backend->AppendCommands(new SessionCommands(commands), false);
    114       commands.clear();
    115     }
    116     commands.push_back(CreateCommandFromData(data[i]));
    117     backend->AppendCommands(new SessionCommands(commands), false);
    118   }
    119 }
    120 
    121 TEST_F(SessionBackendTest, BigData) {
    122   struct TestData data[] = {
    123     { 1,  "a" },
    124     { 2,  "ab" },
    125   };
    126 
    127   scoped_refptr<SessionBackend> backend(
    128       new SessionBackend(BaseSessionService::SESSION_RESTORE, path_));
    129   std::vector<SessionCommand*> commands;
    130   commands.push_back(CreateCommandFromData(data[0]));
    131   const SessionCommand::size_type big_size =
    132       SessionBackend::kFileReadBufferSize + 100;
    133   const SessionCommand::id_type big_id = 50;
    134   SessionCommand* big_command = new SessionCommand(big_id, big_size);
    135   reinterpret_cast<char*>(big_command->contents())[0] = 'a';
    136   reinterpret_cast<char*>(big_command->contents())[big_size - 1] = 'z';
    137   commands.push_back(big_command);
    138   commands.push_back(CreateCommandFromData(data[1]));
    139   backend->AppendCommands(new SessionCommands(commands), false);
    140   commands.clear();
    141 
    142   backend = NULL;
    143   backend = new SessionBackend(BaseSessionService::SESSION_RESTORE, path_);
    144   commands.clear();
    145   backend->ReadLastSessionCommandsImpl(&commands);
    146   ASSERT_EQ(3U, commands.size());
    147   AssertCommandEqualsData(data[0], commands[0]);
    148   AssertCommandEqualsData(data[1], commands[2]);
    149 
    150   EXPECT_EQ(big_id, commands[1]->id());
    151   ASSERT_EQ(big_size, commands[1]->size());
    152   EXPECT_EQ('a', reinterpret_cast<char*>(commands[1]->contents())[0]);
    153   EXPECT_EQ('z',
    154             reinterpret_cast<char*>(commands[1]->contents())[big_size - 1]);
    155   STLDeleteElements(&commands);
    156 }
    157 
    158 // Bug 132037: This test causes an assertion error on Windows.
    159 #if defined(OS_WIN) && !defined(NDEBUG)
    160 #define MAYBE_EmptyCommand DISABLED_EmptyCommand
    161 #else
    162 #define MAYBE_EmptyCommand EmptyCommand
    163 #endif
    164 TEST_F(SessionBackendTest, MAYBE_EmptyCommand) {
    165   TestData empty_command;
    166   empty_command.command_id = 1;
    167   scoped_refptr<SessionBackend> backend(
    168       new SessionBackend(BaseSessionService::SESSION_RESTORE, path_));
    169   std::vector<SessionCommand*>* empty_commands =
    170       new std::vector<SessionCommand*>();
    171   empty_commands->push_back(CreateCommandFromData(empty_command));
    172   backend->AppendCommands(empty_commands, true);
    173   backend->MoveCurrentSessionToLastSession();
    174 
    175   std::vector<SessionCommand*> commands;
    176   backend->ReadLastSessionCommandsImpl(&commands);
    177   ASSERT_EQ(1U, commands.size());
    178   AssertCommandEqualsData(empty_command, commands[0]);
    179   STLDeleteElements(&commands);
    180 }
    181 
    182 // Writes a command, appends another command with reset to true, then reads
    183 // making sure we only get back the second command.
    184 TEST_F(SessionBackendTest, Truncate) {
    185   scoped_refptr<SessionBackend> backend(
    186       new SessionBackend(BaseSessionService::SESSION_RESTORE, path_));
    187   struct TestData first_data = { 1,  "a" };
    188   std::vector<SessionCommand*> commands;
    189   commands.push_back(CreateCommandFromData(first_data));
    190   backend->AppendCommands(new SessionCommands(commands), false);
    191   commands.clear();
    192 
    193   // Write another command, this time resetting the file when appending.
    194   struct TestData second_data = { 2,  "b" };
    195   commands.push_back(CreateCommandFromData(second_data));
    196   backend->AppendCommands(new SessionCommands(commands), true);
    197   commands.clear();
    198 
    199   // Read it back in.
    200   backend = NULL;
    201   backend = new SessionBackend(BaseSessionService::SESSION_RESTORE, path_);
    202   backend->ReadLastSessionCommandsImpl(&commands);
    203 
    204   // And make sure we get back the expected data.
    205   ASSERT_EQ(1U, commands.size());
    206   AssertCommandEqualsData(second_data, commands[0]);
    207 
    208   STLDeleteElements(&commands);
    209 }
    210