1 // Copyright (c) 2012 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.
9 #include "base/message_loop.h"
10 #include "base/message_loop_proxy.h"
11 #include "net/base/net_errors.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "webkit/appcache/appcache_quota_client.h"
14 #include "webkit/appcache/mock_appcache_service.h"
18 // Declared to shorten the line lengths.
19 static const quota::StorageType kTemp
= quota::kStorageTypeTemporary
;
20 static const quota::StorageType kPerm
= quota::kStorageTypePersistent
;
22 // Base class for our test fixtures.
23 class AppCacheQuotaClientTest
: public testing::Test
{
27 const GURL kOriginOther
;
29 AppCacheQuotaClientTest()
30 : kOriginA("http://host"),
31 kOriginB("http://host:8000"),
32 kOriginOther("http://other"),
34 delete_status_(quota::kQuotaStatusUnknown
),
35 num_get_origin_usage_completions_(0),
36 num_get_origins_completions_(0),
37 num_delete_origins_completions_(0),
38 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
42 quota::QuotaClient
* client
,
44 quota::StorageType type
) {
46 AsyncGetOriginUsage(client
, origin
, type
);
47 MessageLoop::current()->RunUntilIdle();
51 const std::set
<GURL
>& GetOriginsForType(
52 quota::QuotaClient
* client
,
53 quota::StorageType type
) {
55 AsyncGetOriginsForType(client
, type
);
56 MessageLoop::current()->RunUntilIdle();
60 const std::set
<GURL
>& GetOriginsForHost(
61 quota::QuotaClient
* client
,
62 quota::StorageType type
,
63 const std::string
& host
) {
65 AsyncGetOriginsForHost(client
, type
, host
);
66 MessageLoop::current()->RunUntilIdle();
70 quota::QuotaStatusCode
DeleteOriginData(
71 quota::QuotaClient
* client
,
72 quota::StorageType type
,
74 delete_status_
= quota::kQuotaStatusUnknown
;
75 AsyncDeleteOriginData(client
, type
, origin
);
76 MessageLoop::current()->RunUntilIdle();
77 return delete_status_
;
80 void AsyncGetOriginUsage(
81 quota::QuotaClient
* client
,
83 quota::StorageType type
) {
84 client
->GetOriginUsage(
86 base::Bind(&AppCacheQuotaClientTest::OnGetOriginUsageComplete
,
87 weak_factory_
.GetWeakPtr()));
90 void AsyncGetOriginsForType(
91 quota::QuotaClient
* client
,
92 quota::StorageType type
) {
93 client
->GetOriginsForType(
95 base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete
,
96 weak_factory_
.GetWeakPtr()));
99 void AsyncGetOriginsForHost(
100 quota::QuotaClient
* client
,
101 quota::StorageType type
,
102 const std::string
& host
) {
103 client
->GetOriginsForHost(
105 base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete
,
106 weak_factory_
.GetWeakPtr()));
109 void AsyncDeleteOriginData(
110 quota::QuotaClient
* client
,
111 quota::StorageType type
,
112 const GURL
& origin
) {
113 client
->DeleteOriginData(
115 base::Bind(&AppCacheQuotaClientTest::OnDeleteOriginDataComplete
,
116 weak_factory_
.GetWeakPtr()));
119 void SetUsageMapEntry(const GURL
& origin
, int64 usage
) {
120 mock_service_
.storage()->usage_map_
[origin
] = usage
;
123 AppCacheQuotaClient
* CreateClient() {
124 return new AppCacheQuotaClient(&mock_service_
);
127 void Call_NotifyAppCacheReady(AppCacheQuotaClient
* client
) {
128 client
->NotifyAppCacheReady();
131 void Call_NotifyAppCacheDestroyed(AppCacheQuotaClient
* client
) {
132 client
->NotifyAppCacheDestroyed();
135 void Call_OnQuotaManagerDestroyed(AppCacheQuotaClient
* client
) {
136 client
->OnQuotaManagerDestroyed();
140 void OnGetOriginUsageComplete(int64 usage
) {
141 ++num_get_origin_usage_completions_
;
145 void OnGetOriginsComplete(const std::set
<GURL
>& origins
,
146 quota::StorageType type
) {
147 ++num_get_origins_completions_
;
152 void OnDeleteOriginDataComplete(quota::QuotaStatusCode status
) {
153 ++num_delete_origins_completions_
;
154 delete_status_
= status
;
157 MessageLoop message_loop_
;
159 std::set
<GURL
> origins_
;
160 quota::StorageType type_
;
161 quota::QuotaStatusCode delete_status_
;
162 int num_get_origin_usage_completions_
;
163 int num_get_origins_completions_
;
164 int num_delete_origins_completions_
;
165 MockAppCacheService mock_service_
;
166 base::WeakPtrFactory
<AppCacheQuotaClientTest
> weak_factory_
;
170 TEST_F(AppCacheQuotaClientTest
, BasicCreateDestroy
) {
171 AppCacheQuotaClient
* client
= CreateClient();
172 Call_NotifyAppCacheReady(client
);
173 Call_OnQuotaManagerDestroyed(client
);
174 Call_NotifyAppCacheDestroyed(client
);
177 TEST_F(AppCacheQuotaClientTest
, EmptyService
) {
178 AppCacheQuotaClient
* client
= CreateClient();
179 Call_NotifyAppCacheReady(client
);
181 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kTemp
));
182 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kPerm
));
183 EXPECT_TRUE(GetOriginsForType(client
, kTemp
).empty());
184 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
185 EXPECT_TRUE(GetOriginsForHost(client
, kTemp
, kOriginA
.host()).empty());
186 EXPECT_TRUE(GetOriginsForHost(client
, kPerm
, kOriginA
.host()).empty());
187 EXPECT_EQ(quota::kQuotaStatusOk
, DeleteOriginData(client
, kTemp
, kOriginA
));
188 EXPECT_EQ(quota::kQuotaStatusOk
, DeleteOriginData(client
, kPerm
, kOriginA
));
190 Call_NotifyAppCacheDestroyed(client
);
191 Call_OnQuotaManagerDestroyed(client
);
194 TEST_F(AppCacheQuotaClientTest
, NoService
) {
195 AppCacheQuotaClient
* client
= CreateClient();
196 Call_NotifyAppCacheReady(client
);
197 Call_NotifyAppCacheDestroyed(client
);
199 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kTemp
));
200 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kPerm
));
201 EXPECT_TRUE(GetOriginsForType(client
, kTemp
).empty());
202 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
203 EXPECT_TRUE(GetOriginsForHost(client
, kTemp
, kOriginA
.host()).empty());
204 EXPECT_TRUE(GetOriginsForHost(client
, kPerm
, kOriginA
.host()).empty());
205 EXPECT_EQ(quota::kQuotaErrorAbort
,
206 DeleteOriginData(client
, kTemp
, kOriginA
));
207 EXPECT_EQ(quota::kQuotaErrorAbort
,
208 DeleteOriginData(client
, kPerm
, kOriginA
));
210 Call_OnQuotaManagerDestroyed(client
);
213 TEST_F(AppCacheQuotaClientTest
, GetOriginUsage
) {
214 AppCacheQuotaClient
* client
= CreateClient();
215 Call_NotifyAppCacheReady(client
);
217 SetUsageMapEntry(kOriginA
, 1000);
218 EXPECT_EQ(1000, GetOriginUsage(client
, kOriginA
, kTemp
));
219 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kPerm
));
221 Call_NotifyAppCacheDestroyed(client
);
222 Call_OnQuotaManagerDestroyed(client
);
225 TEST_F(AppCacheQuotaClientTest
, GetOriginsForHost
) {
226 AppCacheQuotaClient
* client
= CreateClient();
227 Call_NotifyAppCacheReady(client
);
229 EXPECT_EQ(kOriginA
.host(), kOriginB
.host());
230 EXPECT_NE(kOriginA
.host(), kOriginOther
.host());
232 std::set
<GURL
> origins
= GetOriginsForHost(client
, kTemp
, kOriginA
.host());
233 EXPECT_TRUE(origins
.empty());
235 SetUsageMapEntry(kOriginA
, 1000);
236 SetUsageMapEntry(kOriginB
, 10);
237 SetUsageMapEntry(kOriginOther
, 500);
239 origins
= GetOriginsForHost(client
, kTemp
, kOriginA
.host());
240 EXPECT_EQ(2ul, origins
.size());
241 EXPECT_TRUE(origins
.find(kOriginA
) != origins
.end());
242 EXPECT_TRUE(origins
.find(kOriginB
) != origins
.end());
244 origins
= GetOriginsForHost(client
, kTemp
, kOriginOther
.host());
245 EXPECT_EQ(1ul, origins
.size());
246 EXPECT_TRUE(origins
.find(kOriginOther
) != origins
.end());
248 origins
= GetOriginsForHost(client
, kPerm
, kOriginA
.host());
249 EXPECT_TRUE(origins
.empty());
251 Call_NotifyAppCacheDestroyed(client
);
252 Call_OnQuotaManagerDestroyed(client
);
255 TEST_F(AppCacheQuotaClientTest
, GetOriginsForType
) {
256 AppCacheQuotaClient
* client
= CreateClient();
257 Call_NotifyAppCacheReady(client
);
259 EXPECT_TRUE(GetOriginsForType(client
, kTemp
).empty());
260 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
262 SetUsageMapEntry(kOriginA
, 1000);
263 SetUsageMapEntry(kOriginB
, 10);
265 std::set
<GURL
> origins
= GetOriginsForType(client
, kTemp
);
266 EXPECT_EQ(2ul, origins
.size());
267 EXPECT_TRUE(origins
.find(kOriginA
) != origins
.end());
268 EXPECT_TRUE(origins
.find(kOriginB
) != origins
.end());
270 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
272 Call_NotifyAppCacheDestroyed(client
);
273 Call_OnQuotaManagerDestroyed(client
);
276 TEST_F(AppCacheQuotaClientTest
, DeleteOriginData
) {
277 AppCacheQuotaClient
* client
= CreateClient();
278 Call_NotifyAppCacheReady(client
);
280 // Perm deletions are short circuited in the Client and
281 // should not reach the AppCacheService.
282 EXPECT_EQ(quota::kQuotaStatusOk
,
283 DeleteOriginData(client
, kPerm
, kOriginA
));
284 EXPECT_EQ(0, mock_service_
.delete_called_count());
286 EXPECT_EQ(quota::kQuotaStatusOk
,
287 DeleteOriginData(client
, kTemp
, kOriginA
));
288 EXPECT_EQ(1, mock_service_
.delete_called_count());
290 mock_service_
.set_mock_delete_appcaches_for_origin_result(
292 EXPECT_EQ(quota::kQuotaErrorAbort
,
293 DeleteOriginData(client
, kTemp
, kOriginA
));
294 EXPECT_EQ(2, mock_service_
.delete_called_count());
296 Call_OnQuotaManagerDestroyed(client
);
297 Call_NotifyAppCacheDestroyed(client
);
300 TEST_F(AppCacheQuotaClientTest
, PendingRequests
) {
301 AppCacheQuotaClient
* client
= CreateClient();
303 SetUsageMapEntry(kOriginA
, 1000);
304 SetUsageMapEntry(kOriginB
, 10);
305 SetUsageMapEntry(kOriginOther
, 500);
307 // Queue up some reqeusts.
308 AsyncGetOriginUsage(client
, kOriginA
, kPerm
);
309 AsyncGetOriginUsage(client
, kOriginB
, kTemp
);
310 AsyncGetOriginsForType(client
, kPerm
);
311 AsyncGetOriginsForType(client
, kTemp
);
312 AsyncGetOriginsForHost(client
, kTemp
, kOriginA
.host());
313 AsyncGetOriginsForHost(client
, kTemp
, kOriginOther
.host());
314 AsyncDeleteOriginData(client
, kTemp
, kOriginA
);
315 AsyncDeleteOriginData(client
, kPerm
, kOriginA
);
316 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
318 EXPECT_EQ(0, num_get_origin_usage_completions_
);
319 EXPECT_EQ(0, num_get_origins_completions_
);
320 EXPECT_EQ(0, num_delete_origins_completions_
);
321 MessageLoop::current()->RunUntilIdle();
322 EXPECT_EQ(0, num_get_origin_usage_completions_
);
323 EXPECT_EQ(0, num_get_origins_completions_
);
324 EXPECT_EQ(0, num_delete_origins_completions_
);
326 // Pending requests should get serviced when the appcache is ready.
327 Call_NotifyAppCacheReady(client
);
328 EXPECT_EQ(2, num_get_origin_usage_completions_
);
329 EXPECT_EQ(4, num_get_origins_completions_
);
330 EXPECT_EQ(0, num_delete_origins_completions_
);
331 MessageLoop::current()->RunUntilIdle();
332 EXPECT_EQ(3, num_delete_origins_completions_
); // deletes are really async
334 // They should be serviced in order requested.
335 EXPECT_EQ(10, usage_
);
336 EXPECT_EQ(1ul, origins_
.size());
337 EXPECT_TRUE(origins_
.find(kOriginOther
) != origins_
.end());
339 Call_NotifyAppCacheDestroyed(client
);
340 Call_OnQuotaManagerDestroyed(client
);
343 TEST_F(AppCacheQuotaClientTest
, DestroyServiceWithPending
) {
344 AppCacheQuotaClient
* client
= CreateClient();
346 SetUsageMapEntry(kOriginA
, 1000);
347 SetUsageMapEntry(kOriginB
, 10);
348 SetUsageMapEntry(kOriginOther
, 500);
350 // Queue up some reqeusts prior to being ready.
351 AsyncGetOriginUsage(client
, kOriginA
, kPerm
);
352 AsyncGetOriginUsage(client
, kOriginB
, kTemp
);
353 AsyncGetOriginsForType(client
, kPerm
);
354 AsyncGetOriginsForType(client
, kTemp
);
355 AsyncGetOriginsForHost(client
, kTemp
, kOriginA
.host());
356 AsyncGetOriginsForHost(client
, kTemp
, kOriginOther
.host());
357 AsyncDeleteOriginData(client
, kTemp
, kOriginA
);
358 AsyncDeleteOriginData(client
, kPerm
, kOriginA
);
359 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
360 MessageLoop::current()->RunUntilIdle();
361 EXPECT_EQ(0, num_get_origin_usage_completions_
);
362 EXPECT_EQ(0, num_get_origins_completions_
);
363 EXPECT_EQ(0, num_delete_origins_completions_
);
366 Call_NotifyAppCacheDestroyed(client
);
368 // All should have been aborted and called completion.
369 EXPECT_EQ(2, num_get_origin_usage_completions_
);
370 EXPECT_EQ(4, num_get_origins_completions_
);
371 EXPECT_EQ(3, num_delete_origins_completions_
);
372 EXPECT_EQ(0, usage_
);
373 EXPECT_TRUE(origins_
.empty());
374 EXPECT_EQ(quota::kQuotaErrorAbort
, delete_status_
);
376 Call_OnQuotaManagerDestroyed(client
);
379 TEST_F(AppCacheQuotaClientTest
, DestroyQuotaManagerWithPending
) {
380 AppCacheQuotaClient
* client
= CreateClient();
382 SetUsageMapEntry(kOriginA
, 1000);
383 SetUsageMapEntry(kOriginB
, 10);
384 SetUsageMapEntry(kOriginOther
, 500);
386 // Queue up some reqeusts prior to being ready.
387 AsyncGetOriginUsage(client
, kOriginA
, kPerm
);
388 AsyncGetOriginUsage(client
, kOriginB
, kTemp
);
389 AsyncGetOriginsForType(client
, kPerm
);
390 AsyncGetOriginsForType(client
, kTemp
);
391 AsyncGetOriginsForHost(client
, kTemp
, kOriginA
.host());
392 AsyncGetOriginsForHost(client
, kTemp
, kOriginOther
.host());
393 AsyncDeleteOriginData(client
, kTemp
, kOriginA
);
394 AsyncDeleteOriginData(client
, kPerm
, kOriginA
);
395 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
396 MessageLoop::current()->RunUntilIdle();
397 EXPECT_EQ(0, num_get_origin_usage_completions_
);
398 EXPECT_EQ(0, num_get_origins_completions_
);
399 EXPECT_EQ(0, num_delete_origins_completions_
);
401 // Kill the quota manager.
402 Call_OnQuotaManagerDestroyed(client
);
403 Call_NotifyAppCacheReady(client
);
405 // Callbacks should be deleted and not called.
406 MessageLoop::current()->RunUntilIdle();
407 EXPECT_EQ(0, num_get_origin_usage_completions_
);
408 EXPECT_EQ(0, num_get_origins_completions_
);
409 EXPECT_EQ(0, num_delete_origins_completions_
);
411 Call_NotifyAppCacheDestroyed(client
);
414 TEST_F(AppCacheQuotaClientTest
, DestroyWithDeleteInProgress
) {
415 AppCacheQuotaClient
* client
= CreateClient();
416 Call_NotifyAppCacheReady(client
);
418 // Start an async delete.
419 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
420 EXPECT_EQ(0, num_delete_origins_completions_
);
423 Call_NotifyAppCacheDestroyed(client
);
425 // Should have been aborted.
426 EXPECT_EQ(1, num_delete_origins_completions_
);
427 EXPECT_EQ(quota::kQuotaErrorAbort
, delete_status_
);
429 // A real completion callback from the service should
430 // be dropped if it comes in after NotifyAppCacheDestroyed.
431 MessageLoop::current()->RunUntilIdle();
432 EXPECT_EQ(1, num_delete_origins_completions_
);
433 EXPECT_EQ(quota::kQuotaErrorAbort
, delete_status_
);
435 Call_OnQuotaManagerDestroyed(client
);
438 } // namespace appcache