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.
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"
15 // This deleter lets us be safe with sqlite3 objects, which aren't really the
16 // structs, but slabs of new uint8_t[size].
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
);
31 const char kFileName
[] = "TestingDatabase.db";
33 class VFSTest
: public mojo::test::ApplicationTestBase
,
34 public filesystem::FileSystemClient
{
36 VFSTest() : binding_(this) {}
37 ~VFSTest() override
{}
40 return sqlite3_vfs_find(NULL
);
43 scoped_ptr
<sqlite3_file
> MakeFile() {
44 return scoped_ptr
<sqlite3_file
>(reinterpret_cast<sqlite3_file
*>(
45 new uint8_t[vfs()->szOsFile
]));
48 void SetUp() override
{
49 mojo::test::ApplicationTestBase::SetUp();
51 mojo::URLRequestPtr
request(mojo::URLRequest::New());
52 request
->url
= mojo::String::From("mojo:filesystem");
53 application_impl()->ConnectToService(request
.Pass(), &files_
);
55 filesystem::FileSystemClientPtr client
;
56 binding_
.Bind(GetProxy(&client
));
58 filesystem::FileError error
= filesystem::FILE_ERROR_FAILED
;
59 filesystem::DirectoryPtr directory
;
60 files_
->OpenFileSystem("temp", GetProxy(&directory
), client
.Pass(),
61 mojo::Capture(&error
));
62 ASSERT_TRUE(files_
.WaitForIncomingResponse());
63 ASSERT_EQ(filesystem::FILE_ERROR_OK
, error
);
65 vfs_
.reset(new ScopedMojoFilesystemVFS(directory
.Pass()));
68 void TearDown() override
{
70 mojo::test::ApplicationTestBase::TearDown();
73 void OnFileSystemShutdown() override
{
77 filesystem::FileSystemPtr files_
;
78 scoped_ptr
<ScopedMojoFilesystemVFS
> vfs_
;
79 mojo::Binding
<filesystem::FileSystemClient
> binding_
;
81 DISALLOW_COPY_AND_ASSIGN(VFSTest
);
84 TEST_F(VFSTest
, TestInstalled
) {
85 EXPECT_EQ("mojo", std::string(vfs()->zName
));
88 TEST_F(VFSTest
, ExclusiveOpen
) {
89 // Opening a non-existent file exclusively should work.
90 scoped_ptr
<sqlite3_file
> file(MakeFile());
92 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
93 SQLITE_OPEN_EXCLUSIVE
| SQLITE_OPEN_CREATE
,
95 EXPECT_EQ(SQLITE_OK
, rc
);
97 // Opening it a second time exclusively shouldn't.
98 scoped_ptr
<sqlite3_file
> file2(MakeFile());
99 rc
= vfs()->xOpen(vfs(), kFileName
, file2
.get(),
100 SQLITE_OPEN_EXCLUSIVE
| SQLITE_OPEN_CREATE
,
102 EXPECT_NE(SQLITE_OK
, rc
);
104 file
->pMethods
->xClose(file
.get());
107 TEST_F(VFSTest
, NonexclusiveOpen
) {
108 // Opening a non-existent file should work.
109 scoped_ptr
<sqlite3_file
> file(MakeFile());
111 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
112 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
114 EXPECT_EQ(SQLITE_OK
, rc
);
116 // Opening it a second time should work.
117 scoped_ptr
<sqlite3_file
> file2(MakeFile());
118 rc
= vfs()->xOpen(vfs(), kFileName
, file2
.get(),
119 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
121 EXPECT_EQ(SQLITE_OK
, rc
);
123 file
->pMethods
->xClose(file
.get());
124 file
->pMethods
->xClose(file2
.get());
127 TEST_F(VFSTest
, NullFilenameOpen
) {
128 // Opening a file with a null filename should return a valid file object.
129 scoped_ptr
<sqlite3_file
> file(MakeFile());
131 int rc
= vfs()->xOpen(
132 vfs(), nullptr, file
.get(),
133 SQLITE_OPEN_DELETEONCLOSE
| SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
135 EXPECT_EQ(SQLITE_OK
, rc
);
137 file
->pMethods
->xClose(file
.get());
140 TEST_F(VFSTest
, DeleteOnClose
) {
142 scoped_ptr
<sqlite3_file
> file(MakeFile());
144 int rc
= vfs()->xOpen(
145 vfs(), kFileName
, file
.get(),
146 SQLITE_OPEN_DELETEONCLOSE
| SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
148 EXPECT_EQ(SQLITE_OK
, rc
);
149 file
->pMethods
->xClose(file
.get());
152 // The file shouldn't exist now.
154 vfs()->xAccess(vfs(), kFileName
, SQLITE_ACCESS_EXISTS
, &result
);
155 EXPECT_FALSE(result
);
158 TEST_F(VFSTest
, TestNonExistence
) {
159 // We shouldn't have a file exist yet in a fresh directory.
161 vfs()->xAccess(vfs(), kFileName
, SQLITE_ACCESS_EXISTS
, &result
);
162 EXPECT_FALSE(result
);
165 TEST_F(VFSTest
, TestExistence
) {
167 scoped_ptr
<sqlite3_file
> file(MakeFile());
169 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
170 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
172 EXPECT_EQ(SQLITE_OK
, rc
);
174 file
->pMethods
->xClose(file
.get());
178 vfs()->xAccess(vfs(), kFileName
, SQLITE_ACCESS_EXISTS
, &result
);
182 TEST_F(VFSTest
, TestDelete
) {
184 scoped_ptr
<sqlite3_file
> file(MakeFile());
186 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
187 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
189 EXPECT_EQ(SQLITE_OK
, rc
);
191 file
->pMethods
->xClose(file
.get());
195 vfs()->xAccess(vfs(), kFileName
, SQLITE_ACCESS_EXISTS
, &result
);
198 vfs()->xDelete(vfs(), kFileName
, 0);
200 vfs()->xAccess(vfs(), kFileName
, SQLITE_ACCESS_EXISTS
, &result
);
201 EXPECT_FALSE(result
);
204 TEST_F(VFSTest
, TestWriteAndRead
) {
205 const char kBuffer
[] = "One Two Three Four Five Six Seven";
206 const int kBufferSize
= arraysize(kBuffer
);
209 scoped_ptr
<sqlite3_file
> file(MakeFile());
211 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
212 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
214 EXPECT_EQ(SQLITE_OK
, rc
);
216 for (int i
= 0; i
< 10; ++i
) {
217 rc
= file
->pMethods
->xWrite(file
.get(), kBuffer
, kBufferSize
,
219 EXPECT_EQ(SQLITE_OK
, rc
);
222 file
->pMethods
->xClose(file
.get());
225 // Expect that the size of the file is 10 * arraysize(kBuffer);
227 scoped_ptr
<sqlite3_file
> file(MakeFile());
229 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
230 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
232 EXPECT_EQ(SQLITE_OK
, rc
);
235 rc
= file
->pMethods
->xFileSize(file
.get(), &size
);
236 EXPECT_EQ(SQLITE_OK
, rc
);
237 EXPECT_EQ(10 * kBufferSize
, size
);
239 file
->pMethods
->xClose(file
.get());
242 // We should be able to read things back.
244 scoped_ptr
<sqlite3_file
> file(MakeFile());
246 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
247 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
249 EXPECT_EQ(SQLITE_OK
, rc
);
251 char data_buffer
[kBufferSize
];
252 memset(data_buffer
, '8', kBufferSize
);
253 for (int i
= 0; i
< 10; ++i
) {
254 rc
= file
->pMethods
->xRead(file
.get(), data_buffer
, kBufferSize
,
256 EXPECT_EQ(SQLITE_OK
, rc
);
257 EXPECT_TRUE(strncmp(kBuffer
, &data_buffer
[0], kBufferSize
) == 0);
260 file
->pMethods
->xClose(file
.get());
264 TEST_F(VFSTest
, PartialRead
) {
265 const char kBuffer
[] = "One Two Three Four Five Six Seven";
266 const int kBufferSize
= arraysize(kBuffer
);
268 // Write the data once.
270 scoped_ptr
<sqlite3_file
> file(MakeFile());
272 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
273 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
275 EXPECT_EQ(SQLITE_OK
, rc
);
277 rc
= file
->pMethods
->xWrite(file
.get(), kBuffer
, kBufferSize
, 0);
278 EXPECT_EQ(SQLITE_OK
, rc
);
280 file
->pMethods
->xClose(file
.get());
283 // Now attempt to read kBufferSize + 5 from a file sized to kBufferSize.
285 scoped_ptr
<sqlite3_file
> file(MakeFile());
287 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
288 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
290 EXPECT_EQ(SQLITE_OK
, rc
);
292 const char kBufferWithFiveNulls
[] =
293 "One Two Three Four Five Six Seven\0\0\0\0\0";
294 const int kBufferWithFiveNullsSize
= arraysize(kBufferWithFiveNulls
);
296 char data_buffer
[kBufferWithFiveNullsSize
];
297 memset(data_buffer
, '8', kBufferWithFiveNullsSize
);
298 rc
= file
->pMethods
->xRead(file
.get(), data_buffer
,
299 kBufferWithFiveNullsSize
, 0);
300 EXPECT_EQ(SQLITE_IOERR_SHORT_READ
, rc
);
302 EXPECT_TRUE(strncmp(kBufferWithFiveNulls
, &data_buffer
[0],
303 kBufferWithFiveNullsSize
) == 0);
305 file
->pMethods
->xClose(file
.get());
309 TEST_F(VFSTest
, Truncate
) {
310 const char kBuffer
[] = "One Two Three Four Five Six Seven";
311 const int kBufferSize
= arraysize(kBuffer
);
312 const int kCharsToThree
= 13;
314 scoped_ptr
<sqlite3_file
> file(MakeFile());
316 int rc
= vfs()->xOpen(vfs(), kFileName
, file
.get(),
317 SQLITE_OPEN_CREATE
| SQLITE_OPEN_READWRITE
,
319 EXPECT_EQ(SQLITE_OK
, rc
);
321 rc
= file
->pMethods
->xWrite(file
.get(), kBuffer
, kBufferSize
, 0);
322 EXPECT_EQ(SQLITE_OK
, rc
);
325 rc
= file
->pMethods
->xFileSize(file
.get(), &size
);
326 EXPECT_EQ(SQLITE_OK
, rc
);
327 EXPECT_EQ(kBufferSize
, size
);
329 rc
= file
->pMethods
->xTruncate(file
.get(), kCharsToThree
);
330 EXPECT_EQ(SQLITE_OK
, rc
);
332 rc
= file
->pMethods
->xFileSize(file
.get(), &size
);
333 EXPECT_EQ(SQLITE_OK
, rc
);
334 EXPECT_EQ(kCharsToThree
, size
);
336 file
->pMethods
->xClose(file
.get());