Chromium Code Reviews| Index: sql/mojo/vfs_unittest.cc |
| diff --git a/sql/mojo/vfs_unittest.cc b/sql/mojo/vfs_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..cbe0476e4f83029ffe071ce6bbd66b8f8ffba0c2 |
| --- /dev/null |
| +++ b/sql/mojo/vfs_unittest.cc |
| @@ -0,0 +1,313 @@ |
| +// Copyright 2015 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/filesystem/public/interfaces/file_system.mojom.h" |
| +#include "mojo/application/public/cpp/application_impl.h" |
| +#include "mojo/application/public/cpp/application_test_base.h" |
| +#include "mojo/util/capture_util.h" |
| +#include "sql/mojo/enable_mojo_fs.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "third_party/sqlite/sqlite3.h" |
| + |
| +namespace base { |
| + |
| +// This deleter lets us be safe with sqlite3 objects, which aren't really the |
| +// structs, but slabs of new uint8_t[size]. |
| +template <> |
| +struct DefaultDeleter<sqlite3_file> { |
| + inline void operator()(sqlite3_file* ptr) const { |
| + // Why don't we call file->pMethods->xClose() here? Because it's not |
| + // guaranteed to be valid. sqlite3_file "objects" can be in partially |
| + // initialized states. |
| + delete [] reinterpret_cast<uint8_t*>(ptr); |
| + } |
| +}; |
| + |
| +} // namespace base |
| + |
| +namespace sql { |
| + |
| +const char kFileName[] = "TestingDatabase.db"; |
| + |
| +class VFSTest : public mojo::test::ApplicationTestBase { |
| + public: |
| + VFSTest() {} |
| + ~VFSTest() override {} |
| + |
| + sqlite3_vfs* vfs() { |
| + return sqlite3_vfs_find(NULL); |
| + } |
| + |
| + scoped_ptr<sqlite3_file> MakeFile() { |
| + return scoped_ptr<sqlite3_file>(reinterpret_cast<sqlite3_file*>( |
| + new uint8_t[vfs()->szOsFile])); |
| + } |
| + |
| + void SetUp() override { |
| + mojo::test::ApplicationTestBase::SetUp(); |
| + |
| + mojo::URLRequestPtr request(mojo::URLRequest::New()); |
| + request->url = mojo::String::From("mojo:filesystem"); |
| + application_impl()->ConnectToService(request.Pass(), &files_); |
| + |
| + filesystem::FileError error = filesystem::FILE_ERROR_FAILED; |
| + filesystem::DirectoryPtr directory; |
| + files_->OpenFileSystem("temp", GetProxy(&directory), mojo::Capture(&error)); |
| + ASSERT_TRUE(files_.WaitForIncomingResponse()); |
| + ASSERT_EQ(filesystem::FILE_ERROR_OK, error); |
| + |
| + vfs_.reset(new ScopedMojoFilesystemVFS(directory.Pass())); |
| + } |
| + |
| + void TearDown() override { |
| + vfs_.reset(); |
| + mojo::test::ApplicationTestBase::TearDown(); |
| + } |
| + |
| + private: |
| + filesystem::FileSystemPtr files_; |
| + scoped_ptr<ScopedMojoFilesystemVFS> vfs_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(VFSTest); |
| +}; |
| + |
| +TEST_F(VFSTest, TestInstalled) { |
| + EXPECT_EQ("mojo", vfs()->zName); |
| +} |
| + |
| +TEST_F(VFSTest, ExclusiveOpen) { |
| + // Opening a non-existent file exclusively should work. |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_CREATE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + // Opening it a second time exclusively shouldn't. |
| + scoped_ptr<sqlite3_file> file2(MakeFile()); |
| + rc = vfs()->xOpen(vfs(), kFileName, file2.get(), |
| + SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_CREATE, |
| + &out_flags); |
| + EXPECT_NE(SQLITE_OK, rc); |
| + |
| + file->pMethods->xClose(file.get()); |
| +} |
| + |
| +TEST_F(VFSTest, NonexclusiveOpen) { |
| + // Opening a non-existent file exclusively should work. |
|
Scott Hess - ex-Googler
2015/06/17 19:32:58
s/exclusively//;
|
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + 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.
|
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + // 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.
|
| + scoped_ptr<sqlite3_file> file2(MakeFile()); |
| + rc = vfs()->xOpen(vfs(), kFileName, file2.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + file->pMethods->xClose(file.get()); |
| + file->pMethods->xClose(file2.get()); |
| +} |
| + |
| +TEST_F(VFSTest, DeleteOnClose) { |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen( |
| + vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + file->pMethods->xClose(file.get()); |
| + } |
| + |
| + // The file shouldn't exist now. |
| + int result = 0; |
| + vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| + EXPECT_FALSE(result); |
| +} |
| + |
| +TEST_F(VFSTest, TestNonExistence) { |
| + // We shouldn't have a file exist yet in a fresh directory. |
| + int result = 0; |
| + vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| + EXPECT_FALSE(result); |
| +} |
| + |
| +TEST_F(VFSTest, TestExistence) { |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| + |
| + int result = 0; |
| + vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| + EXPECT_TRUE(result); |
| +} |
| + |
| +TEST_F(VFSTest, TestDelete) { |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| + |
| + int result = 0; |
| + vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| + EXPECT_TRUE(result); |
| + |
| + vfs()->xDelete(vfs(), kFileName, 0); |
| + |
| + vfs()->xAccess(vfs(), kFileName, SQLITE_ACCESS_EXISTS, &result); |
| + EXPECT_FALSE(result); |
| +} |
| + |
| +TEST_F(VFSTest, TestWriteAndRead) { |
| + const char kBuffer[] = "One Two Three Four Five Six Seven"; |
| + const int kBufferSize = arraysize(kBuffer); |
| + |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + for (int i = 0; i < 10; ++i) { |
| + rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, |
| + i * kBufferSize); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + } |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| + |
| + // Expect that the size of the file is 10 * arraysize(kBuffer); |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + sqlite_int64 size; |
| + rc = file->pMethods->xFileSize(file.get(), &size); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + EXPECT_EQ(10 * kBufferSize, size); |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| + |
| + // We should be able to read things back. |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + char data_buffer[kBufferSize]; |
| + for (int i = 0; i < 10; ++i) { |
| + rc = file->pMethods->xRead(file.get(), data_buffer, kBufferSize, |
| + i * kBufferSize); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + EXPECT_TRUE(strncmp(kBuffer, &data_buffer[0], kBufferSize) == 0); |
| + } |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| +} |
| + |
| +TEST_F(VFSTest, PartialRead) { |
| + const char kBuffer[] = "One Two Three Four Five Six Seven"; |
| + const int kBufferSize = arraysize(kBuffer); |
| + |
| + // Write the data once. |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, 0); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| + |
| + // Now attempt to read kBufferSize + 5 from a file sized to kBufferSize. |
| + { |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + 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.
|
| + rc = file->pMethods->xRead(file.get(), data_buffer, kBufferSize + 5, 0); |
| + EXPECT_EQ(SQLITE_IOERR_SHORT_READ, rc); |
| + |
| + const char kBufferWithFiveNulls[] = |
| + "One Two Three Four Five Six Seven\0\0\0\0\0"; |
| + 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.
|
| + EXPECT_TRUE(strncmp(kBufferWithFiveNulls, &data_buffer[0], |
| + kBufferWithFiveNullsSize) == 0); |
| + |
| + file->pMethods->xClose(file.get()); |
| + } |
| +} |
| + |
| +TEST_F(VFSTest, Truncate) { |
| + const char kBuffer[] = "One Two Three Four Five Six Seven"; |
| + const int kBufferSize = arraysize(kBuffer); |
| + const int kCharsToThree = 13; |
| + |
| + scoped_ptr<sqlite3_file> file(MakeFile()); |
| + int out_flags; |
| + int rc = vfs()->xOpen(vfs(), kFileName, file.get(), |
| + SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, |
| + &out_flags); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + rc = file->pMethods->xWrite(file.get(), kBuffer, kBufferSize, 0); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + sqlite_int64 size; |
| + rc = file->pMethods->xFileSize(file.get(), &size); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + EXPECT_EQ(kBufferSize, size); |
| + |
| + rc = file->pMethods->xTruncate(file.get(), kCharsToThree); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + |
| + rc = file->pMethods->xFileSize(file.get(), &size); |
| + EXPECT_EQ(SQLITE_OK, rc); |
| + EXPECT_EQ(kCharsToThree, size); |
| + |
| + file->pMethods->xClose(file.get()); |
| +} |
| + |
| +} // namespace sql |