OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 "components/filesystem/public/interfaces/file_system.mojom.h" |
| 6 #include "mojo/application/public/cpp/application_impl.h" |
| 7 #include "mojo/application/public/cpp/application_test_base.h" |
| 8 #include "mojo/util/capture_util.h" |
| 9 #include "sql/mojo/mojo_vfs.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 #include "third_party/sqlite/sqlite3.h" |
| 12 |
| 13 namespace base { |
| 14 |
| 15 // This deleter lets us be safe with sqlite3 objects, which aren't really the |
| 16 // structs, but slabs of new uint8_t[size]. |
| 17 template <> |
| 18 struct DefaultDeleter<sqlite3_file> { |
| 19 inline void operator()(sqlite3_file* ptr) const { |
| 20 // Why don't we call file->pMethods->xClose() here? Because it's not |
| 21 // guaranteed to be valid. sqlite3_file "objects" can be in partially |
| 22 // initialized states. |
| 23 delete [] reinterpret_cast<uint8_t*>(ptr); |
| 24 } |
| 25 }; |
| 26 |
| 27 } // namespace base |
| 28 |
| 29 namespace sql { |
| 30 |
| 31 const char kFileName[] = "TestingDatabase.db"; |
| 32 |
| 33 class VFSTest : public mojo::test::ApplicationTestBase { |
| 34 public: |
| 35 VFSTest() {} |
| 36 ~VFSTest() override {} |
| 37 |
| 38 sqlite3_vfs* vfs() { |
| 39 return sqlite3_vfs_find(NULL); |
| 40 } |
| 41 |
| 42 scoped_ptr<sqlite3_file> MakeFile() { |
| 43 return scoped_ptr<sqlite3_file>(reinterpret_cast<sqlite3_file*>( |
| 44 new uint8_t[vfs()->szOsFile])); |
| 45 } |
| 46 |
| 47 void SetUp() override { |
| 48 mojo::test::ApplicationTestBase::SetUp(); |
| 49 |
| 50 mojo::URLRequestPtr request(mojo::URLRequest::New()); |
| 51 request->url = mojo::String::From("mojo:filesystem"); |
| 52 application_impl()->ConnectToService(request.Pass(), &files_); |
| 53 |
| 54 filesystem::FileError error = filesystem::FILE_ERROR_FAILED; |
| 55 filesystem::DirectoryPtr directory; |
| 56 files_->OpenFileSystem("temp", GetProxy(&directory), mojo::Capture(&error)); |
| 57 ASSERT_TRUE(files_.WaitForIncomingResponse()); |
| 58 ASSERT_EQ(filesystem::FILE_ERROR_OK, error); |
| 59 |
| 60 vfs_.reset(new ScopedMojoFilesystemVFS(directory.Pass())); |
| 61 } |
| 62 |
| 63 void TearDown() override { |
| 64 vfs_.reset(); |
| 65 mojo::test::ApplicationTestBase::TearDown(); |
| 66 } |
| 67 |
| 68 private: |
| 69 filesystem::FileSystemPtr files_; |
| 70 scoped_ptr<ScopedMojoFilesystemVFS> vfs_; |
| 71 |
| 72 DISALLOW_COPY_AND_ASSIGN(VFSTest); |
| 73 }; |
| 74 |
| 75 TEST_F(VFSTest, TestInstalled) { |
| 76 EXPECT_EQ("mojo", vfs()->zName); |
| 77 } |
| 78 |
| 79 TEST_F(VFSTest, ExclusiveOpen) { |
| 80 // Opening a non-existent file exclusively should work. |
| 81 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 82 int out_flags; |
| 83 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 84 SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_CREATE, |
| 85 &out_flags); |
| 86 EXPECT_EQ(SQLITE_OK, rc); |
| 87 |
| 88 // Opening it a second time exclusively shouldn't. |
| 89 scoped_ptr<sqlite3_file> file2(MakeFile()); |
| 90 rc = vfs()->xOpen(vfs(), kFileName, file2.get(), |
| 91 SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_CREATE, |
| 92 &out_flags); |
| 93 EXPECT_NE(SQLITE_OK, rc); |
| 94 |
| 95 file->pMethods->xClose(file.get()); |
| 96 } |
| 97 |
| 98 TEST_F(VFSTest, NonexclusiveOpen) { |
| 99 // Opening a non-existent file should work. |
| 100 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 101 int out_flags; |
| 102 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 103 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 104 &out_flags); |
| 105 EXPECT_EQ(SQLITE_OK, rc); |
| 106 |
| 107 // Opening it a second time should work. |
| 108 scoped_ptr<sqlite3_file> file2(MakeFile()); |
| 109 rc = vfs()->xOpen(vfs(), kFileName, file2.get(), |
| 110 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 111 &out_flags); |
| 112 EXPECT_EQ(SQLITE_OK, rc); |
| 113 |
| 114 file->pMethods->xClose(file.get()); |
| 115 file->pMethods->xClose(file2.get()); |
| 116 } |
| 117 |
| 118 TEST_F(VFSTest, DeleteOnClose) { |
| 119 { |
| 120 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 121 int out_flags; |
| 122 int rc = vfs()->xOpen( |
| 123 vfs(), kFileName, file.get(), |
| 124 SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 125 &out_flags); |
| 126 EXPECT_EQ(SQLITE_OK, rc); |
| 127 file->pMethods->xClose(file.get()); |
| 128 } |
| 129 |
| 130 // The file shouldn't exist now. |
| 131 int result = 0; |
| 132 vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| 133 EXPECT_FALSE(result); |
| 134 } |
| 135 |
| 136 TEST_F(VFSTest, TestNonExistence) { |
| 137 // We shouldn't have a file exist yet in a fresh directory. |
| 138 int result = 0; |
| 139 vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| 140 EXPECT_FALSE(result); |
| 141 } |
| 142 |
| 143 TEST_F(VFSTest, TestExistence) { |
| 144 { |
| 145 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 146 int out_flags; |
| 147 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 148 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 149 &out_flags); |
| 150 EXPECT_EQ(SQLITE_OK, rc); |
| 151 |
| 152 file->pMethods->xClose(file.get()); |
| 153 } |
| 154 |
| 155 int result = 0; |
| 156 vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| 157 EXPECT_TRUE(result); |
| 158 } |
| 159 |
| 160 TEST_F(VFSTest, TestDelete) { |
| 161 { |
| 162 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 163 int out_flags; |
| 164 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 165 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 166 &out_flags); |
| 167 EXPECT_EQ(SQLITE_OK, rc); |
| 168 |
| 169 file->pMethods->xClose(file.get()); |
| 170 } |
| 171 |
| 172 int result = 0; |
| 173 vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| 174 EXPECT_TRUE(result); |
| 175 |
| 176 vfs()->xDelete(vfs(), kFileName, 0); |
| 177 |
| 178 vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| 179 EXPECT_FALSE(result); |
| 180 } |
| 181 |
| 182 TEST_F(VFSTest, TestWriteAndRead) { |
| 183 const char kBuffer[] = "One Two Three Four Five Six Seven"; |
| 184 const int kBufferSize = arraysize(kBuffer); |
| 185 |
| 186 { |
| 187 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 188 int out_flags; |
| 189 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 190 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 191 &out_flags); |
| 192 EXPECT_EQ(SQLITE_OK, rc); |
| 193 |
| 194 for (int i = 0; i < 10; ++i) { |
| 195 rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, |
| 196 i * kBufferSize); |
| 197 EXPECT_EQ(SQLITE_OK, rc); |
| 198 } |
| 199 |
| 200 file->pMethods->xClose(file.get()); |
| 201 } |
| 202 |
| 203 // Expect that the size of the file is 10 * arraysize(kBuffer); |
| 204 { |
| 205 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 206 int out_flags; |
| 207 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 208 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 209 &out_flags); |
| 210 EXPECT_EQ(SQLITE_OK, rc); |
| 211 |
| 212 sqlite_int64 size; |
| 213 rc = file->pMethods->xFileSize(file.get(), &size); |
| 214 EXPECT_EQ(SQLITE_OK, rc); |
| 215 EXPECT_EQ(10 * kBufferSize, size); |
| 216 |
| 217 file->pMethods->xClose(file.get()); |
| 218 } |
| 219 |
| 220 // We should be able to read things back. |
| 221 { |
| 222 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 223 int out_flags; |
| 224 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 225 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 226 &out_flags); |
| 227 EXPECT_EQ(SQLITE_OK, rc); |
| 228 |
| 229 char data_buffer[kBufferSize]; |
| 230 memset(data_buffer, '8', kBufferSize); |
| 231 for (int i = 0; i < 10; ++i) { |
| 232 rc = file->pMethods->xRead(file.get(), data_buffer, kBufferSize, |
| 233 i * kBufferSize); |
| 234 EXPECT_EQ(SQLITE_OK, rc); |
| 235 EXPECT_TRUE(strncmp(kBuffer, &data_buffer[0], kBufferSize) == 0); |
| 236 } |
| 237 |
| 238 file->pMethods->xClose(file.get()); |
| 239 } |
| 240 } |
| 241 |
| 242 TEST_F(VFSTest, PartialRead) { |
| 243 const char kBuffer[] = "One Two Three Four Five Six Seven"; |
| 244 const int kBufferSize = arraysize(kBuffer); |
| 245 |
| 246 // Write the data once. |
| 247 { |
| 248 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 249 int out_flags; |
| 250 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 251 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 252 &out_flags); |
| 253 EXPECT_EQ(SQLITE_OK, rc); |
| 254 |
| 255 rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, 0); |
| 256 EXPECT_EQ(SQLITE_OK, rc); |
| 257 |
| 258 file->pMethods->xClose(file.get()); |
| 259 } |
| 260 |
| 261 // Now attempt to read kBufferSize + 5 from a file sized to kBufferSize. |
| 262 { |
| 263 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 264 int out_flags; |
| 265 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 266 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 267 &out_flags); |
| 268 EXPECT_EQ(SQLITE_OK, rc); |
| 269 |
| 270 const char kBufferWithFiveNulls[] = |
| 271 "One Two Three Four Five Six Seven\0\0\0\0\0"; |
| 272 const int kBufferWithFiveNullsSize = arraysize(kBufferWithFiveNulls); |
| 273 |
| 274 char data_buffer[kBufferWithFiveNullsSize]; |
| 275 memset(data_buffer, '8', kBufferWithFiveNullsSize); |
| 276 rc = file->pMethods->xRead(file.get(), data_buffer, |
| 277 kBufferWithFiveNullsSize, 0); |
| 278 EXPECT_EQ(SQLITE_IOERR_SHORT_READ, rc); |
| 279 |
| 280 EXPECT_TRUE(strncmp(kBufferWithFiveNulls, &data_buffer[0], |
| 281 kBufferWithFiveNullsSize) == 0); |
| 282 |
| 283 file->pMethods->xClose(file.get()); |
| 284 } |
| 285 } |
| 286 |
| 287 TEST_F(VFSTest, Truncate) { |
| 288 const char kBuffer[] = "One Two Three Four Five Six Seven"; |
| 289 const int kBufferSize = arraysize(kBuffer); |
| 290 const int kCharsToThree = 13; |
| 291 |
| 292 scoped_ptr<sqlite3_file> file(MakeFile()); |
| 293 int out_flags; |
| 294 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| 295 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| 296 &out_flags); |
| 297 EXPECT_EQ(SQLITE_OK, rc); |
| 298 |
| 299 rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, 0); |
| 300 EXPECT_EQ(SQLITE_OK, rc); |
| 301 |
| 302 sqlite_int64 size; |
| 303 rc = file->pMethods->xFileSize(file.get(), &size); |
| 304 EXPECT_EQ(SQLITE_OK, rc); |
| 305 EXPECT_EQ(kBufferSize, size); |
| 306 |
| 307 rc = file->pMethods->xTruncate(file.get(), kCharsToThree); |
| 308 EXPECT_EQ(SQLITE_OK, rc); |
| 309 |
| 310 rc = file->pMethods->xFileSize(file.get(), &size); |
| 311 EXPECT_EQ(SQLITE_OK, rc); |
| 312 EXPECT_EQ(kCharsToThree, size); |
| 313 |
| 314 file->pMethods->xClose(file.get()); |
| 315 } |
| 316 |
| 317 } // namespace sql |
OLD | NEW |