Chromium Code Reviews| 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/enable_mojo_fs.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 exclusively should work. | |
|
Scott Hess - ex-Googler
2015/06/17 19:32:58
s/exclusively//;
| |
| 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, | |
|
Scott Hess - ex-Googler
2015/06/17 19:32:58
Seems to be an excess space left of the |. Also b
Elliot Glaysher
2015/06/17 21:59:35
Done.
| |
| 104 &out_flags); | |
| 105 EXPECT_EQ(SQLITE_OK, rc); | |
| 106 | |
| 107 // Opening it a second time exclusively shouldn't. | |
|
Scott Hess - ex-Googler
2015/06/17 19:32:58
"second time should work."
Elliot Glaysher
2015/06/17 21:59:35
Done.
| |
| 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 for (int i = 0; i < 10; ++i) { | |
| 231 rc = file->pMethods->xRead(file.get(), data_buffer, kBufferSize, | |
| 232 i * kBufferSize); | |
| 233 EXPECT_EQ(SQLITE_OK, rc); | |
| 234 EXPECT_TRUE(strncmp(kBuffer, &data_buffer[0], kBufferSize) == 0); | |
| 235 } | |
| 236 | |
| 237 file->pMethods->xClose(file.get()); | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 TEST_F(VFSTest, PartialRead) { | |
| 242 const char kBuffer[] = "One Two Three Four Five Six Seven"; | |
| 243 const int kBufferSize = arraysize(kBuffer); | |
| 244 | |
| 245 // Write the data once. | |
| 246 { | |
| 247 scoped_ptr<sqlite3_file> file(MakeFile()); | |
| 248 int out_flags; | |
| 249 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), | |
| 250 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, | |
| 251 &out_flags); | |
| 252 EXPECT_EQ(SQLITE_OK, rc); | |
| 253 | |
| 254 rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, 0); | |
| 255 EXPECT_EQ(SQLITE_OK, rc); | |
| 256 | |
| 257 file->pMethods->xClose(file.get()); | |
| 258 } | |
| 259 | |
| 260 // Now attempt to read kBufferSize + 5 from a file sized to kBufferSize. | |
| 261 { | |
| 262 scoped_ptr<sqlite3_file> file(MakeFile()); | |
| 263 int out_flags; | |
| 264 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), | |
| 265 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, | |
| 266 &out_flags); | |
| 267 EXPECT_EQ(SQLITE_OK, rc); | |
| 268 | |
| 269 char data_buffer[kBufferSize + 5]; | |
|
Scott Hess - ex-Googler
2015/06/17 19:32:58
Suggest pre-filling the buffer with something that
Elliot Glaysher
2015/06/17 21:59:35
Done.
| |
| 270 rc = file->pMethods->xRead(file.get(), data_buffer, kBufferSize + 5, 0); | |
| 271 EXPECT_EQ(SQLITE_IOERR_SHORT_READ, rc); | |
| 272 | |
| 273 const char kBufferWithFiveNulls[] = | |
| 274 "One Two Three Four Five Six Seven\0\0\0\0\0"; | |
| 275 const int kBufferWithFiveNullsSize = arraysize(kBuffer); | |
|
Scott Hess - ex-Googler
2015/06/17 19:32:58
kBufferWithFiveNullsSize might make a good size fo
Elliot Glaysher
2015/06/17 21:59:35
Done.
| |
| 276 EXPECT_TRUE(strncmp(kBufferWithFiveNulls, &data_buffer[0], | |
| 277 kBufferWithFiveNullsSize) == 0); | |
| 278 | |
| 279 file->pMethods->xClose(file.get()); | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 TEST_F(VFSTest, Truncate) { | |
| 284 const char kBuffer[] = "One Two Three Four Five Six Seven"; | |
| 285 const int kBufferSize = arraysize(kBuffer); | |
| 286 const int kCharsToThree = 13; | |
| 287 | |
| 288 scoped_ptr<sqlite3_file> file(MakeFile()); | |
| 289 int out_flags; | |
| 290 int rc = vfs()->xOpen(vfs(), kFileName, file.get(), | |
| 291 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, | |
| 292 &out_flags); | |
| 293 EXPECT_EQ(SQLITE_OK, rc); | |
| 294 | |
| 295 rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, 0); | |
| 296 EXPECT_EQ(SQLITE_OK, rc); | |
| 297 | |
| 298 sqlite_int64 size; | |
| 299 rc = file->pMethods->xFileSize(file.get(), &size); | |
| 300 EXPECT_EQ(SQLITE_OK, rc); | |
| 301 EXPECT_EQ(kBufferSize, size); | |
| 302 | |
| 303 rc = file->pMethods->xTruncate(file.get(), kCharsToThree); | |
| 304 EXPECT_EQ(SQLITE_OK, rc); | |
| 305 | |
| 306 rc = file->pMethods->xFileSize(file.get(), &size); | |
| 307 EXPECT_EQ(SQLITE_OK, rc); | |
| 308 EXPECT_EQ(kCharsToThree, size); | |
| 309 | |
| 310 file->pMethods->xClose(file.get()); | |
| 311 } | |
| 312 | |
| 313 } // namespace sql | |
| OLD | NEW |