Fix the EULA sentinel file path determination.
[chromium-blink-merge.git] / ppapi / proxy / file_system_resource_unittest.cc
blobf93695439cbac7deffefbcd63c73716f0c1d38a0
1 // Copyright 2014 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 "base/message_loop/message_loop.h"
6 #include "ppapi/c/pp_errors.h"
7 #include "ppapi/c/ppb_file_io.h"
8 #include "ppapi/c/ppb_file_ref.h"
9 #include "ppapi/c/ppb_file_system.h"
10 #include "ppapi/proxy/file_system_resource.h"
11 #include "ppapi/proxy/locking_resource_releaser.h"
12 #include "ppapi/proxy/plugin_message_filter.h"
13 #include "ppapi/proxy/ppapi_message_utils.h"
14 #include "ppapi/proxy/ppapi_messages.h"
15 #include "ppapi/proxy/ppapi_proxy_test.h"
16 #include "ppapi/shared_impl/proxy_lock.h"
17 #include "ppapi/shared_impl/scoped_pp_var.h"
18 #include "ppapi/shared_impl/var.h"
19 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_file_system_api.h"
21 #include "ppapi/thunk/thunk.h"
23 using ppapi::proxy::ResourceMessageTestSink;
24 using ppapi::thunk::EnterResource;
25 using ppapi::thunk::PPB_FileSystem_API;
27 namespace ppapi {
28 namespace proxy {
30 namespace {
32 const int64_t kExpectedFileSystemSize = 100;
33 const int64_t kQuotaRequestAmount1 = 10;
34 const int64_t kQuotaRequestAmount2 = 20;
36 class MockCompletionCallback {
37 public:
38 MockCompletionCallback() : called_(false) {}
40 bool called() { return called_; }
41 int32_t result() { return result_; }
43 static void Callback(void* user_data, int32_t result) {
44 MockCompletionCallback* that =
45 reinterpret_cast<MockCompletionCallback*>(user_data);
46 that->called_ = true;
47 that->result_ = result;
50 private:
51 bool called_;
52 int32_t result_;
55 class MockRequestQuotaCallback {
56 public:
57 MockRequestQuotaCallback() : called_(false) {}
59 bool called() { return called_; }
60 int64_t result() { return result_; }
62 void Reset() { called_ = false; }
64 void Callback(int64_t result) {
65 ASSERT_FALSE(called_);
66 called_ = true;
67 result_ = result;
70 private:
71 bool called_;
72 int64_t result_;
75 class FileSystemResourceTest : public PluginProxyTest {
76 public:
77 FileSystemResourceTest() {}
79 void SendReply(const ResourceMessageCallParams& params,
80 int32_t result,
81 const IPC::Message& nested_message) {
82 ResourceMessageReplyParams reply_params(params.pp_resource(),
83 params.sequence());
84 reply_params.set_result(result);
85 PluginMessageFilter::DispatchResourceReplyForTest(
86 reply_params, nested_message);
89 void SendOpenReply(const ResourceMessageCallParams& params, int32_t result) {
90 SendReply(params, result, PpapiPluginMsg_FileSystem_OpenReply());
93 // Opens the given file system.
94 void OpenFileSystem(PP_Resource file_system) {
95 MockCompletionCallback cb;
96 int32_t result = thunk::GetPPB_FileSystem_1_0_Thunk()->Open(
97 file_system,
98 kExpectedFileSystemSize,
99 PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb));
100 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
102 // Should have sent two new "open" messages to the browser and renderer.
103 ResourceMessageTestSink::ResourceCallVector open_messages =
104 sink().GetAllResourceCallsMatching(PpapiHostMsg_FileSystem_Open::ID);
105 ASSERT_EQ(2U, open_messages.size());
106 sink().ClearMessages();
108 // The resource is expecting two replies.
109 SendOpenReply(open_messages[0].first, PP_OK);
110 SendOpenReply(open_messages[1].first, PP_OK);
112 ASSERT_TRUE(cb.called());
113 ASSERT_EQ(PP_OK, cb.result());
116 // Opens the given file in the given file system. Since there is no host,
117 // the file handle will be invalid.
118 void OpenFile(PP_Resource file_io,
119 PP_Resource file_ref,
120 PP_Resource file_system) {
121 MockCompletionCallback cb;
122 int32_t result = thunk::GetPPB_FileIO_1_1_Thunk()->Open(
123 file_io,
124 file_ref,
125 PP_FILEOPENFLAG_WRITE,
126 PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb));
127 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
129 // Should have sent an "open" message.
130 ResourceMessageCallParams params;
131 IPC::Message msg;
132 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
133 PpapiHostMsg_FileIO_Open::ID, &params, &msg));
134 sink().ClearMessages();
136 // Send a success reply.
137 ResourceMessageReplyParams reply_params(params.pp_resource(),
138 params.sequence());
139 reply_params.set_result(PP_OK);
140 PluginMessageFilter::DispatchResourceReplyForTest(
141 reply_params,
142 PpapiPluginMsg_FileIO_OpenReply(file_system,
143 0 /* max_written_offset */));
147 } // namespace
149 // Test that Open fails if either host returns failure. The other tests exercise
150 // the case where both hosts return PP_OK.
151 TEST_F(FileSystemResourceTest, OpenFailure) {
152 const PPB_FileSystem_1_0* fs_iface = thunk::GetPPB_FileSystem_1_0_Thunk();
153 // Fail if the first reply doesn't return PP_OK.
155 LockingResourceReleaser file_system(
156 fs_iface->Create(pp_instance(), PP_FILESYSTEMTYPE_LOCALTEMPORARY));
158 MockCompletionCallback cb;
159 int32_t result = thunk::GetPPB_FileSystem_1_0_Thunk()->Open(
160 file_system.get(),
161 kExpectedFileSystemSize,
162 PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb));
163 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
165 ResourceMessageTestSink::ResourceCallVector open_messages =
166 sink().GetAllResourceCallsMatching(PpapiHostMsg_FileSystem_Open::ID);
167 ASSERT_EQ(2U, open_messages.size());
168 sink().ClearMessages();
170 SendOpenReply(open_messages[0].first, PP_ERROR_FAILED);
171 SendOpenReply(open_messages[1].first, PP_OK);
173 ASSERT_TRUE(cb.called());
174 ASSERT_EQ(PP_ERROR_FAILED, cb.result());
176 // Fail if the second reply doesn't return PP_OK.
178 LockingResourceReleaser file_system(
179 fs_iface->Create(pp_instance(), PP_FILESYSTEMTYPE_LOCALTEMPORARY));
181 MockCompletionCallback cb;
182 int32_t result = thunk::GetPPB_FileSystem_1_0_Thunk()->Open(
183 file_system.get(),
184 kExpectedFileSystemSize,
185 PP_MakeCompletionCallback(&MockCompletionCallback::Callback, &cb));
186 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
188 ResourceMessageTestSink::ResourceCallVector open_messages =
189 sink().GetAllResourceCallsMatching(PpapiHostMsg_FileSystem_Open::ID);
190 ASSERT_EQ(2U, open_messages.size());
191 sink().ClearMessages();
193 SendOpenReply(open_messages[0].first, PP_OK);
194 SendOpenReply(open_messages[1].first, PP_ERROR_FAILED);
196 ASSERT_TRUE(cb.called());
197 ASSERT_EQ(PP_ERROR_FAILED, cb.result());
201 TEST_F(FileSystemResourceTest, RequestQuota) {
202 const PPB_FileSystem_1_0* fs_iface = thunk::GetPPB_FileSystem_1_0_Thunk();
203 const PPB_FileRef_1_1* fref_iface = thunk::GetPPB_FileRef_1_1_Thunk();
204 const PPB_FileIO_1_1* fio_iface = thunk::GetPPB_FileIO_1_1_Thunk();
206 LockingResourceReleaser file_system(
207 fs_iface->Create(pp_instance(), PP_FILESYSTEMTYPE_LOCALTEMPORARY));
209 OpenFileSystem(file_system.get());
211 // Create and open two files in the file system. FileIOResource calls
212 // FileSystemResource::OpenQuotaFile on success.
213 LockingResourceReleaser file_ref1(
214 fref_iface->Create(file_system.get(), "/file1"));
215 LockingResourceReleaser file_io1(fio_iface->Create(pp_instance()));
216 OpenFile(file_io1.get(), file_ref1.get(), file_system.get());
217 LockingResourceReleaser file_ref2(
218 fref_iface->Create(file_system.get(), "/file2"));
219 LockingResourceReleaser file_io2(fio_iface->Create(pp_instance()));
220 OpenFile(file_io2.get(), file_ref2.get(), file_system.get());
222 EnterResource<PPB_FileSystem_API> enter(file_system.get(), true);
223 ASSERT_FALSE(enter.failed());
224 PPB_FileSystem_API* file_system_api = enter.object();
226 MockRequestQuotaCallback cb1;
227 int64_t result = file_system_api->RequestQuota(
228 kQuotaRequestAmount1,
229 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1)));
230 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
232 // Should have sent a "reserve quota" message, with the amount of the request
233 // and a map of all currently open files to their max written offsets.
234 ResourceMessageCallParams params;
235 IPC::Message msg;
236 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
237 PpapiHostMsg_FileSystem_ReserveQuota::ID, &params, &msg));
238 sink().ClearMessages();
240 int64_t amount = 0;
241 FileGrowthMap file_growths;
242 ASSERT_TRUE(UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>(
243 msg, &amount, &file_growths));
244 ASSERT_EQ(kQuotaRequestAmount1, amount);
245 ASSERT_EQ(2U, file_growths.size());
246 ASSERT_EQ(0, file_growths[file_io1.get()].max_written_offset);
247 ASSERT_EQ(0, file_growths[file_io2.get()].max_written_offset);
249 // Make another request while the "reserve quota" message is pending.
250 MockRequestQuotaCallback cb2;
251 result = file_system_api->RequestQuota(
252 kQuotaRequestAmount2,
253 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb2)));
254 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
255 // No new "reserve quota" message should be sent while one is pending.
256 ASSERT_FALSE(sink().GetFirstResourceCallMatching(
257 PpapiHostMsg_FileSystem_ReserveQuota::ID, &params, &msg));
259 ProxyAutoUnlock unlock_to_prevent_deadlock;
260 // Reply with quota reservation amount sufficient to cover both requests.
261 // Both callbacks should be called with the requests granted.
262 SendReply(params,
263 PP_OK,
264 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
265 kQuotaRequestAmount1 + kQuotaRequestAmount2,
266 FileGrowthMapToFileSizeMapForTesting(file_growths)));
268 ASSERT_TRUE(cb1.called());
269 ASSERT_EQ(kQuotaRequestAmount1, cb1.result());
270 ASSERT_TRUE(cb2.called());
271 ASSERT_EQ(kQuotaRequestAmount2, cb2.result());
272 cb1.Reset();
273 cb2.Reset();
275 // All requests should fail when insufficient quota is returned to satisfy
276 // the first request.
277 result = file_system_api->RequestQuota(
278 kQuotaRequestAmount1,
279 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1)));
280 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
281 result = file_system_api->RequestQuota(
282 kQuotaRequestAmount2,
283 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb2)));
284 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
286 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
287 PpapiHostMsg_FileSystem_ReserveQuota::ID, &params, &msg));
288 sink().ClearMessages();
290 ProxyAutoUnlock unlock_to_prevent_deadlock;
291 // Reply with quota reservation amount insufficient to cover the first
292 // request.
293 SendReply(params,
294 PP_OK,
295 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
296 kQuotaRequestAmount1 - 1,
297 FileGrowthMapToFileSizeMapForTesting(file_growths)));
299 ASSERT_TRUE(cb1.called());
300 ASSERT_EQ(0, cb1.result());
301 ASSERT_TRUE(cb2.called());
302 ASSERT_EQ(0, cb2.result());
303 cb1.Reset();
304 cb2.Reset();
306 // A new request should be made if the quota reservation is enough to satisfy
307 // at least one request.
308 result = file_system_api->RequestQuota(
309 kQuotaRequestAmount1,
310 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1)));
311 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
312 result = file_system_api->RequestQuota(
313 kQuotaRequestAmount2,
314 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb2)));
315 ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
317 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
318 PpapiHostMsg_FileSystem_ReserveQuota::ID, &params, &msg));
319 sink().ClearMessages();
321 ProxyAutoUnlock unlock_to_prevent_deadlock;
322 // Reply with quota reservation amount sufficient only to cover the first
323 // request.
324 SendReply(params,
325 PP_OK,
326 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
327 kQuotaRequestAmount1,
328 FileGrowthMapToFileSizeMapForTesting(file_growths)));
330 ASSERT_TRUE(cb1.called());
331 ASSERT_EQ(kQuotaRequestAmount1, cb1.result());
332 ASSERT_FALSE(cb2.called());
334 // Another request message should have been sent.
335 ASSERT_TRUE(sink().GetFirstResourceCallMatching(
336 PpapiHostMsg_FileSystem_ReserveQuota::ID, &params, &msg));
337 sink().ClearMessages();
339 ProxyAutoUnlock unlock_to_prevent_deadlock;
340 // Reply with quota reservation amount sufficient to cover the second
341 // request and some extra.
342 SendReply(params,
343 PP_OK,
344 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
345 kQuotaRequestAmount1 + kQuotaRequestAmount2,
346 FileGrowthMapToFileSizeMapForTesting(file_growths)));
349 ASSERT_TRUE(cb2.called());
350 ASSERT_EQ(kQuotaRequestAmount2, cb2.result());
351 cb1.Reset();
352 cb2.Reset();
354 // There is kQuotaRequestAmount1 of quota left, and a request for it should
355 // succeed immediately.
356 result = file_system_api->RequestQuota(
357 kQuotaRequestAmount1,
358 base::Bind(&MockRequestQuotaCallback::Callback, base::Unretained(&cb1)));
359 ASSERT_EQ(kQuotaRequestAmount1, result);
362 } // namespace proxy
363 } // namespace ppapi