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