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.
9 #include "base/run_loop.h"
10 #include "content/browser/appcache/appcache_quota_client.h"
11 #include "content/browser/appcache/mock_appcache_service.h"
12 #include "net/base/net_errors.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 // Declared to shorten the line lengths.
18 static const storage::StorageType kTemp
= storage::kStorageTypeTemporary
;
19 static const storage::StorageType kPerm
= storage::kStorageTypePersistent
;
21 // Base class for our test fixtures.
22 class AppCacheQuotaClientTest
: public testing::Test
{
26 const GURL kOriginOther
;
28 AppCacheQuotaClientTest()
29 : kOriginA("http://host"),
30 kOriginB("http://host:8000"),
31 kOriginOther("http://other"),
33 delete_status_(storage::kQuotaStatusUnknown
),
34 num_get_origin_usage_completions_(0),
35 num_get_origins_completions_(0),
36 num_delete_origins_completions_(0),
37 weak_factory_(this) {}
39 int64
GetOriginUsage(storage::QuotaClient
* client
,
41 storage::StorageType type
) {
43 AsyncGetOriginUsage(client
, origin
, type
);
44 base::RunLoop().RunUntilIdle();
48 const std::set
<GURL
>& GetOriginsForType(storage::QuotaClient
* client
,
49 storage::StorageType type
) {
51 AsyncGetOriginsForType(client
, type
);
52 base::RunLoop().RunUntilIdle();
56 const std::set
<GURL
>& GetOriginsForHost(storage::QuotaClient
* client
,
57 storage::StorageType type
,
58 const std::string
& host
) {
60 AsyncGetOriginsForHost(client
, type
, host
);
61 base::RunLoop().RunUntilIdle();
65 storage::QuotaStatusCode
DeleteOriginData(storage::QuotaClient
* client
,
66 storage::StorageType type
,
68 delete_status_
= storage::kQuotaStatusUnknown
;
69 AsyncDeleteOriginData(client
, type
, origin
);
70 base::RunLoop().RunUntilIdle();
71 return delete_status_
;
74 void AsyncGetOriginUsage(storage::QuotaClient
* client
,
76 storage::StorageType type
) {
77 client
->GetOriginUsage(
79 base::Bind(&AppCacheQuotaClientTest::OnGetOriginUsageComplete
,
80 weak_factory_
.GetWeakPtr()));
83 void AsyncGetOriginsForType(storage::QuotaClient
* client
,
84 storage::StorageType type
) {
85 client
->GetOriginsForType(
87 base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete
,
88 weak_factory_
.GetWeakPtr()));
91 void AsyncGetOriginsForHost(storage::QuotaClient
* client
,
92 storage::StorageType type
,
93 const std::string
& host
) {
94 client
->GetOriginsForHost(
96 base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete
,
97 weak_factory_
.GetWeakPtr()));
100 void AsyncDeleteOriginData(storage::QuotaClient
* client
,
101 storage::StorageType type
,
102 const GURL
& origin
) {
103 client
->DeleteOriginData(
105 base::Bind(&AppCacheQuotaClientTest::OnDeleteOriginDataComplete
,
106 weak_factory_
.GetWeakPtr()));
109 void SetUsageMapEntry(const GURL
& origin
, int64 usage
) {
110 mock_service_
.storage()->usage_map_
[origin
] = usage
;
113 AppCacheQuotaClient
* CreateClient() {
114 return new AppCacheQuotaClient(&mock_service_
);
117 void Call_NotifyAppCacheReady(AppCacheQuotaClient
* client
) {
118 client
->NotifyAppCacheReady();
121 void Call_NotifyAppCacheDestroyed(AppCacheQuotaClient
* client
) {
122 client
->NotifyAppCacheDestroyed();
125 void Call_OnQuotaManagerDestroyed(AppCacheQuotaClient
* client
) {
126 client
->OnQuotaManagerDestroyed();
130 void OnGetOriginUsageComplete(int64 usage
) {
131 ++num_get_origin_usage_completions_
;
135 void OnGetOriginsComplete(const std::set
<GURL
>& origins
) {
136 ++num_get_origins_completions_
;
140 void OnDeleteOriginDataComplete(storage::QuotaStatusCode status
) {
141 ++num_delete_origins_completions_
;
142 delete_status_
= status
;
145 base::MessageLoop message_loop_
;
147 std::set
<GURL
> origins_
;
148 storage::QuotaStatusCode delete_status_
;
149 int num_get_origin_usage_completions_
;
150 int num_get_origins_completions_
;
151 int num_delete_origins_completions_
;
152 MockAppCacheService mock_service_
;
153 base::WeakPtrFactory
<AppCacheQuotaClientTest
> weak_factory_
;
157 TEST_F(AppCacheQuotaClientTest
, BasicCreateDestroy
) {
158 AppCacheQuotaClient
* client
= CreateClient();
159 Call_NotifyAppCacheReady(client
);
160 Call_OnQuotaManagerDestroyed(client
);
161 Call_NotifyAppCacheDestroyed(client
);
164 TEST_F(AppCacheQuotaClientTest
, EmptyService
) {
165 AppCacheQuotaClient
* client
= CreateClient();
166 Call_NotifyAppCacheReady(client
);
168 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kTemp
));
169 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kPerm
));
170 EXPECT_TRUE(GetOriginsForType(client
, kTemp
).empty());
171 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
172 EXPECT_TRUE(GetOriginsForHost(client
, kTemp
, kOriginA
.host()).empty());
173 EXPECT_TRUE(GetOriginsForHost(client
, kPerm
, kOriginA
.host()).empty());
174 EXPECT_EQ(storage::kQuotaStatusOk
, DeleteOriginData(client
, kTemp
, kOriginA
));
175 EXPECT_EQ(storage::kQuotaStatusOk
, DeleteOriginData(client
, kPerm
, kOriginA
));
177 Call_NotifyAppCacheDestroyed(client
);
178 Call_OnQuotaManagerDestroyed(client
);
181 TEST_F(AppCacheQuotaClientTest
, NoService
) {
182 AppCacheQuotaClient
* client
= CreateClient();
183 Call_NotifyAppCacheReady(client
);
184 Call_NotifyAppCacheDestroyed(client
);
186 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kTemp
));
187 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kPerm
));
188 EXPECT_TRUE(GetOriginsForType(client
, kTemp
).empty());
189 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
190 EXPECT_TRUE(GetOriginsForHost(client
, kTemp
, kOriginA
.host()).empty());
191 EXPECT_TRUE(GetOriginsForHost(client
, kPerm
, kOriginA
.host()).empty());
192 EXPECT_EQ(storage::kQuotaErrorAbort
,
193 DeleteOriginData(client
, kTemp
, kOriginA
));
194 EXPECT_EQ(storage::kQuotaErrorAbort
,
195 DeleteOriginData(client
, kPerm
, kOriginA
));
197 Call_OnQuotaManagerDestroyed(client
);
200 TEST_F(AppCacheQuotaClientTest
, GetOriginUsage
) {
201 AppCacheQuotaClient
* client
= CreateClient();
202 Call_NotifyAppCacheReady(client
);
204 SetUsageMapEntry(kOriginA
, 1000);
205 EXPECT_EQ(1000, GetOriginUsage(client
, kOriginA
, kTemp
));
206 EXPECT_EQ(0, GetOriginUsage(client
, kOriginA
, kPerm
));
208 Call_NotifyAppCacheDestroyed(client
);
209 Call_OnQuotaManagerDestroyed(client
);
212 TEST_F(AppCacheQuotaClientTest
, GetOriginsForHost
) {
213 AppCacheQuotaClient
* client
= CreateClient();
214 Call_NotifyAppCacheReady(client
);
216 EXPECT_EQ(kOriginA
.host(), kOriginB
.host());
217 EXPECT_NE(kOriginA
.host(), kOriginOther
.host());
219 std::set
<GURL
> origins
= GetOriginsForHost(client
, kTemp
, kOriginA
.host());
220 EXPECT_TRUE(origins
.empty());
222 SetUsageMapEntry(kOriginA
, 1000);
223 SetUsageMapEntry(kOriginB
, 10);
224 SetUsageMapEntry(kOriginOther
, 500);
226 origins
= GetOriginsForHost(client
, kTemp
, kOriginA
.host());
227 EXPECT_EQ(2ul, origins
.size());
228 EXPECT_TRUE(origins
.find(kOriginA
) != origins
.end());
229 EXPECT_TRUE(origins
.find(kOriginB
) != origins
.end());
231 origins
= GetOriginsForHost(client
, kTemp
, kOriginOther
.host());
232 EXPECT_EQ(1ul, origins
.size());
233 EXPECT_TRUE(origins
.find(kOriginOther
) != origins
.end());
235 origins
= GetOriginsForHost(client
, kPerm
, kOriginA
.host());
236 EXPECT_TRUE(origins
.empty());
238 Call_NotifyAppCacheDestroyed(client
);
239 Call_OnQuotaManagerDestroyed(client
);
242 TEST_F(AppCacheQuotaClientTest
, GetOriginsForType
) {
243 AppCacheQuotaClient
* client
= CreateClient();
244 Call_NotifyAppCacheReady(client
);
246 EXPECT_TRUE(GetOriginsForType(client
, kTemp
).empty());
247 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
249 SetUsageMapEntry(kOriginA
, 1000);
250 SetUsageMapEntry(kOriginB
, 10);
252 std::set
<GURL
> origins
= GetOriginsForType(client
, kTemp
);
253 EXPECT_EQ(2ul, origins
.size());
254 EXPECT_TRUE(origins
.find(kOriginA
) != origins
.end());
255 EXPECT_TRUE(origins
.find(kOriginB
) != origins
.end());
257 EXPECT_TRUE(GetOriginsForType(client
, kPerm
).empty());
259 Call_NotifyAppCacheDestroyed(client
);
260 Call_OnQuotaManagerDestroyed(client
);
263 TEST_F(AppCacheQuotaClientTest
, DeleteOriginData
) {
264 AppCacheQuotaClient
* client
= CreateClient();
265 Call_NotifyAppCacheReady(client
);
267 // Perm deletions are short circuited in the Client and
268 // should not reach the AppCacheServiceImpl.
269 EXPECT_EQ(storage::kQuotaStatusOk
, DeleteOriginData(client
, kPerm
, kOriginA
));
270 EXPECT_EQ(0, mock_service_
.delete_called_count());
272 EXPECT_EQ(storage::kQuotaStatusOk
, DeleteOriginData(client
, kTemp
, kOriginA
));
273 EXPECT_EQ(1, mock_service_
.delete_called_count());
275 mock_service_
.set_mock_delete_appcaches_for_origin_result(
277 EXPECT_EQ(storage::kQuotaErrorAbort
,
278 DeleteOriginData(client
, kTemp
, kOriginA
));
279 EXPECT_EQ(2, mock_service_
.delete_called_count());
281 Call_OnQuotaManagerDestroyed(client
);
282 Call_NotifyAppCacheDestroyed(client
);
285 TEST_F(AppCacheQuotaClientTest
, PendingRequests
) {
286 AppCacheQuotaClient
* client
= CreateClient();
288 SetUsageMapEntry(kOriginA
, 1000);
289 SetUsageMapEntry(kOriginB
, 10);
290 SetUsageMapEntry(kOriginOther
, 500);
292 // Queue up some reqeusts.
293 AsyncGetOriginUsage(client
, kOriginA
, kPerm
);
294 AsyncGetOriginUsage(client
, kOriginB
, kTemp
);
295 AsyncGetOriginsForType(client
, kPerm
);
296 AsyncGetOriginsForType(client
, kTemp
);
297 AsyncGetOriginsForHost(client
, kTemp
, kOriginA
.host());
298 AsyncGetOriginsForHost(client
, kTemp
, kOriginOther
.host());
299 AsyncDeleteOriginData(client
, kTemp
, kOriginA
);
300 AsyncDeleteOriginData(client
, kPerm
, kOriginA
);
301 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
303 EXPECT_EQ(0, num_get_origin_usage_completions_
);
304 EXPECT_EQ(0, num_get_origins_completions_
);
305 EXPECT_EQ(0, num_delete_origins_completions_
);
306 base::RunLoop().RunUntilIdle();
307 EXPECT_EQ(0, num_get_origin_usage_completions_
);
308 EXPECT_EQ(0, num_get_origins_completions_
);
309 EXPECT_EQ(0, num_delete_origins_completions_
);
311 // Pending requests should get serviced when the appcache is ready.
312 Call_NotifyAppCacheReady(client
);
313 EXPECT_EQ(2, num_get_origin_usage_completions_
);
314 EXPECT_EQ(4, num_get_origins_completions_
);
315 EXPECT_EQ(0, num_delete_origins_completions_
);
316 base::RunLoop().RunUntilIdle();
317 EXPECT_EQ(3, num_delete_origins_completions_
); // deletes are really async
319 // They should be serviced in order requested.
320 EXPECT_EQ(10, usage_
);
321 EXPECT_EQ(1ul, origins_
.size());
322 EXPECT_TRUE(origins_
.find(kOriginOther
) != origins_
.end());
324 Call_NotifyAppCacheDestroyed(client
);
325 Call_OnQuotaManagerDestroyed(client
);
328 TEST_F(AppCacheQuotaClientTest
, DestroyServiceWithPending
) {
329 AppCacheQuotaClient
* client
= CreateClient();
331 SetUsageMapEntry(kOriginA
, 1000);
332 SetUsageMapEntry(kOriginB
, 10);
333 SetUsageMapEntry(kOriginOther
, 500);
335 // Queue up some reqeusts prior to being ready.
336 AsyncGetOriginUsage(client
, kOriginA
, kPerm
);
337 AsyncGetOriginUsage(client
, kOriginB
, kTemp
);
338 AsyncGetOriginsForType(client
, kPerm
);
339 AsyncGetOriginsForType(client
, kTemp
);
340 AsyncGetOriginsForHost(client
, kTemp
, kOriginA
.host());
341 AsyncGetOriginsForHost(client
, kTemp
, kOriginOther
.host());
342 AsyncDeleteOriginData(client
, kTemp
, kOriginA
);
343 AsyncDeleteOriginData(client
, kPerm
, kOriginA
);
344 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
345 base::RunLoop().RunUntilIdle();
346 EXPECT_EQ(0, num_get_origin_usage_completions_
);
347 EXPECT_EQ(0, num_get_origins_completions_
);
348 EXPECT_EQ(0, num_delete_origins_completions_
);
351 Call_NotifyAppCacheDestroyed(client
);
353 // All should have been aborted and called completion.
354 EXPECT_EQ(2, num_get_origin_usage_completions_
);
355 EXPECT_EQ(4, num_get_origins_completions_
);
356 EXPECT_EQ(3, num_delete_origins_completions_
);
357 EXPECT_EQ(0, usage_
);
358 EXPECT_TRUE(origins_
.empty());
359 EXPECT_EQ(storage::kQuotaErrorAbort
, delete_status_
);
361 Call_OnQuotaManagerDestroyed(client
);
364 TEST_F(AppCacheQuotaClientTest
, DestroyQuotaManagerWithPending
) {
365 AppCacheQuotaClient
* client
= CreateClient();
367 SetUsageMapEntry(kOriginA
, 1000);
368 SetUsageMapEntry(kOriginB
, 10);
369 SetUsageMapEntry(kOriginOther
, 500);
371 // Queue up some reqeusts prior to being ready.
372 AsyncGetOriginUsage(client
, kOriginA
, kPerm
);
373 AsyncGetOriginUsage(client
, kOriginB
, kTemp
);
374 AsyncGetOriginsForType(client
, kPerm
);
375 AsyncGetOriginsForType(client
, kTemp
);
376 AsyncGetOriginsForHost(client
, kTemp
, kOriginA
.host());
377 AsyncGetOriginsForHost(client
, kTemp
, kOriginOther
.host());
378 AsyncDeleteOriginData(client
, kTemp
, kOriginA
);
379 AsyncDeleteOriginData(client
, kPerm
, kOriginA
);
380 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
381 base::RunLoop().RunUntilIdle();
382 EXPECT_EQ(0, num_get_origin_usage_completions_
);
383 EXPECT_EQ(0, num_get_origins_completions_
);
384 EXPECT_EQ(0, num_delete_origins_completions_
);
386 // Kill the quota manager.
387 Call_OnQuotaManagerDestroyed(client
);
388 Call_NotifyAppCacheReady(client
);
390 // Callbacks should be deleted and not called.
391 base::RunLoop().RunUntilIdle();
392 EXPECT_EQ(0, num_get_origin_usage_completions_
);
393 EXPECT_EQ(0, num_get_origins_completions_
);
394 EXPECT_EQ(0, num_delete_origins_completions_
);
396 Call_NotifyAppCacheDestroyed(client
);
399 TEST_F(AppCacheQuotaClientTest
, DestroyWithDeleteInProgress
) {
400 AppCacheQuotaClient
* client
= CreateClient();
401 Call_NotifyAppCacheReady(client
);
403 // Start an async delete.
404 AsyncDeleteOriginData(client
, kTemp
, kOriginB
);
405 EXPECT_EQ(0, num_delete_origins_completions_
);
408 Call_NotifyAppCacheDestroyed(client
);
410 // Should have been aborted.
411 EXPECT_EQ(1, num_delete_origins_completions_
);
412 EXPECT_EQ(storage::kQuotaErrorAbort
, delete_status_
);
414 // A real completion callback from the service should
415 // be dropped if it comes in after NotifyAppCacheDestroyed.
416 base::RunLoop().RunUntilIdle();
417 EXPECT_EQ(1, num_delete_origins_completions_
);
418 EXPECT_EQ(storage::kQuotaErrorAbort
, delete_status_
);
420 Call_OnQuotaManagerDestroyed(client
);
423 } // namespace content