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 |