Home | History | Annotate | Download | only in appcache
      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.
      4 
      5 #include <map>
      6 #include <set>
      7 
      8 #include "base/bind.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/message_loop/message_loop_proxy.h"
     11 #include "net/base/net_errors.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "webkit/browser/appcache/appcache_quota_client.h"
     14 #include "webkit/browser/appcache/mock_appcache_service.h"
     15 
     16 namespace appcache {
     17 
     18 // Declared to shorten the line lengths.
     19 static const quota::StorageType kTemp = quota::kStorageTypeTemporary;
     20 static const quota::StorageType kPerm = quota::kStorageTypePersistent;
     21 
     22 // Base class for our test fixtures.
     23 class AppCacheQuotaClientTest : public testing::Test {
     24  public:
     25   const GURL kOriginA;
     26   const GURL kOriginB;
     27   const GURL kOriginOther;
     28 
     29   AppCacheQuotaClientTest()
     30       : kOriginA("http://host"),
     31         kOriginB("http://host:8000"),
     32         kOriginOther("http://other"),
     33         usage_(0),
     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_(this) {
     39   }
     40 
     41   int64 GetOriginUsage(
     42       quota::QuotaClient* client,
     43       const GURL& origin,
     44       quota::StorageType type) {
     45     usage_ = -1;
     46     AsyncGetOriginUsage(client, origin, type);
     47     base::MessageLoop::current()->RunUntilIdle();
     48     return usage_;
     49   }
     50 
     51   const std::set<GURL>& GetOriginsForType(
     52       quota::QuotaClient* client,
     53       quota::StorageType type) {
     54     origins_.clear();
     55     AsyncGetOriginsForType(client, type);
     56     base::MessageLoop::current()->RunUntilIdle();
     57     return origins_;
     58   }
     59 
     60   const std::set<GURL>& GetOriginsForHost(
     61       quota::QuotaClient* client,
     62       quota::StorageType type,
     63       const std::string& host) {
     64     origins_.clear();
     65     AsyncGetOriginsForHost(client, type, host);
     66     base::MessageLoop::current()->RunUntilIdle();
     67     return origins_;
     68   }
     69 
     70   quota::QuotaStatusCode DeleteOriginData(
     71       quota::QuotaClient* client,
     72       quota::StorageType type,
     73       const GURL& origin) {
     74     delete_status_ = quota::kQuotaStatusUnknown;
     75     AsyncDeleteOriginData(client, type, origin);
     76     base::MessageLoop::current()->RunUntilIdle();
     77     return delete_status_;
     78   }
     79 
     80   void AsyncGetOriginUsage(
     81       quota::QuotaClient* client,
     82       const GURL& origin,
     83       quota::StorageType type) {
     84     client->GetOriginUsage(
     85         origin, type,
     86         base::Bind(&AppCacheQuotaClientTest::OnGetOriginUsageComplete,
     87                    weak_factory_.GetWeakPtr()));
     88   }
     89 
     90   void AsyncGetOriginsForType(
     91       quota::QuotaClient* client,
     92       quota::StorageType type) {
     93     client->GetOriginsForType(
     94         type,
     95         base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete,
     96                    weak_factory_.GetWeakPtr()));
     97   }
     98 
     99   void AsyncGetOriginsForHost(
    100       quota::QuotaClient* client,
    101       quota::StorageType type,
    102       const std::string& host) {
    103     client->GetOriginsForHost(
    104         type, host,
    105         base::Bind(&AppCacheQuotaClientTest::OnGetOriginsComplete,
    106                    weak_factory_.GetWeakPtr()));
    107   }
    108 
    109   void AsyncDeleteOriginData(
    110       quota::QuotaClient* client,
    111       quota::StorageType type,
    112       const GURL& origin) {
    113     client->DeleteOriginData(
    114         origin, type,
    115         base::Bind(&AppCacheQuotaClientTest::OnDeleteOriginDataComplete,
    116                    weak_factory_.GetWeakPtr()));
    117   }
    118 
    119   void SetUsageMapEntry(const GURL& origin, int64 usage) {
    120     mock_service_.storage()->usage_map_[origin] = usage;
    121   }
    122 
    123   AppCacheQuotaClient* CreateClient() {
    124     return new AppCacheQuotaClient(&mock_service_);
    125   }
    126 
    127   void Call_NotifyAppCacheReady(AppCacheQuotaClient* client) {
    128     client->NotifyAppCacheReady();
    129   }
    130 
    131   void Call_NotifyAppCacheDestroyed(AppCacheQuotaClient* client) {
    132     client->NotifyAppCacheDestroyed();
    133   }
    134 
    135   void Call_OnQuotaManagerDestroyed(AppCacheQuotaClient* client) {
    136     client->OnQuotaManagerDestroyed();
    137   }
    138 
    139  protected:
    140   void OnGetOriginUsageComplete(int64 usage) {
    141     ++num_get_origin_usage_completions_;
    142     usage_ = usage;
    143   }
    144 
    145   void OnGetOriginsComplete(const std::set<GURL>& origins) {
    146     ++num_get_origins_completions_;
    147     origins_ = origins;
    148   }
    149 
    150   void OnDeleteOriginDataComplete(quota::QuotaStatusCode status) {
    151     ++num_delete_origins_completions_;
    152     delete_status_ = status;
    153   }
    154 
    155   base::MessageLoop message_loop_;
    156   int64 usage_;
    157   std::set<GURL> origins_;
    158   quota::QuotaStatusCode delete_status_;
    159   int num_get_origin_usage_completions_;
    160   int num_get_origins_completions_;
    161   int num_delete_origins_completions_;
    162   MockAppCacheService mock_service_;
    163   base::WeakPtrFactory<AppCacheQuotaClientTest> weak_factory_;
    164 };
    165 
    166 
    167 TEST_F(AppCacheQuotaClientTest, BasicCreateDestroy) {
    168   AppCacheQuotaClient* client = CreateClient();
    169   Call_NotifyAppCacheReady(client);
    170   Call_OnQuotaManagerDestroyed(client);
    171   Call_NotifyAppCacheDestroyed(client);
    172 }
    173 
    174 TEST_F(AppCacheQuotaClientTest, EmptyService) {
    175   AppCacheQuotaClient* client = CreateClient();
    176   Call_NotifyAppCacheReady(client);
    177 
    178   EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp));
    179   EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm));
    180   EXPECT_TRUE(GetOriginsForType(client, kTemp).empty());
    181   EXPECT_TRUE(GetOriginsForType(client, kPerm).empty());
    182   EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty());
    183   EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty());
    184   EXPECT_EQ(quota::kQuotaStatusOk, DeleteOriginData(client, kTemp, kOriginA));
    185   EXPECT_EQ(quota::kQuotaStatusOk, DeleteOriginData(client, kPerm, kOriginA));
    186 
    187   Call_NotifyAppCacheDestroyed(client);
    188   Call_OnQuotaManagerDestroyed(client);
    189 }
    190 
    191 TEST_F(AppCacheQuotaClientTest, NoService) {
    192   AppCacheQuotaClient* client = CreateClient();
    193   Call_NotifyAppCacheReady(client);
    194   Call_NotifyAppCacheDestroyed(client);
    195 
    196   EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kTemp));
    197   EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm));
    198   EXPECT_TRUE(GetOriginsForType(client, kTemp).empty());
    199   EXPECT_TRUE(GetOriginsForType(client, kPerm).empty());
    200   EXPECT_TRUE(GetOriginsForHost(client, kTemp, kOriginA.host()).empty());
    201   EXPECT_TRUE(GetOriginsForHost(client, kPerm, kOriginA.host()).empty());
    202   EXPECT_EQ(quota::kQuotaErrorAbort,
    203             DeleteOriginData(client, kTemp, kOriginA));
    204   EXPECT_EQ(quota::kQuotaErrorAbort,
    205             DeleteOriginData(client, kPerm, kOriginA));
    206 
    207   Call_OnQuotaManagerDestroyed(client);
    208 }
    209 
    210 TEST_F(AppCacheQuotaClientTest, GetOriginUsage) {
    211   AppCacheQuotaClient* client = CreateClient();
    212   Call_NotifyAppCacheReady(client);
    213 
    214   SetUsageMapEntry(kOriginA, 1000);
    215   EXPECT_EQ(1000, GetOriginUsage(client, kOriginA, kTemp));
    216   EXPECT_EQ(0, GetOriginUsage(client, kOriginA, kPerm));
    217 
    218   Call_NotifyAppCacheDestroyed(client);
    219   Call_OnQuotaManagerDestroyed(client);
    220 }
    221 
    222 TEST_F(AppCacheQuotaClientTest, GetOriginsForHost) {
    223   AppCacheQuotaClient* client = CreateClient();
    224   Call_NotifyAppCacheReady(client);
    225 
    226   EXPECT_EQ(kOriginA.host(), kOriginB.host());
    227   EXPECT_NE(kOriginA.host(), kOriginOther.host());
    228 
    229   std::set<GURL> origins = GetOriginsForHost(client, kTemp, kOriginA.host());
    230   EXPECT_TRUE(origins.empty());
    231 
    232   SetUsageMapEntry(kOriginA, 1000);
    233   SetUsageMapEntry(kOriginB, 10);
    234   SetUsageMapEntry(kOriginOther, 500);
    235 
    236   origins = GetOriginsForHost(client, kTemp, kOriginA.host());
    237   EXPECT_EQ(2ul, origins.size());
    238   EXPECT_TRUE(origins.find(kOriginA) != origins.end());
    239   EXPECT_TRUE(origins.find(kOriginB) != origins.end());
    240 
    241   origins = GetOriginsForHost(client, kTemp, kOriginOther.host());
    242   EXPECT_EQ(1ul, origins.size());
    243   EXPECT_TRUE(origins.find(kOriginOther) != origins.end());
    244 
    245   origins = GetOriginsForHost(client, kPerm, kOriginA.host());
    246   EXPECT_TRUE(origins.empty());
    247 
    248   Call_NotifyAppCacheDestroyed(client);
    249   Call_OnQuotaManagerDestroyed(client);
    250 }
    251 
    252 TEST_F(AppCacheQuotaClientTest, GetOriginsForType) {
    253   AppCacheQuotaClient* client = CreateClient();
    254   Call_NotifyAppCacheReady(client);
    255 
    256   EXPECT_TRUE(GetOriginsForType(client, kTemp).empty());
    257   EXPECT_TRUE(GetOriginsForType(client, kPerm).empty());
    258 
    259   SetUsageMapEntry(kOriginA, 1000);
    260   SetUsageMapEntry(kOriginB, 10);
    261 
    262   std::set<GURL> origins = GetOriginsForType(client, kTemp);
    263   EXPECT_EQ(2ul, origins.size());
    264   EXPECT_TRUE(origins.find(kOriginA) != origins.end());
    265   EXPECT_TRUE(origins.find(kOriginB) != origins.end());
    266 
    267   EXPECT_TRUE(GetOriginsForType(client, kPerm).empty());
    268 
    269   Call_NotifyAppCacheDestroyed(client);
    270   Call_OnQuotaManagerDestroyed(client);
    271 }
    272 
    273 TEST_F(AppCacheQuotaClientTest, DeleteOriginData) {
    274   AppCacheQuotaClient* client = CreateClient();
    275   Call_NotifyAppCacheReady(client);
    276 
    277   // Perm deletions are short circuited in the Client and
    278   // should not reach the AppCacheService.
    279   EXPECT_EQ(quota::kQuotaStatusOk,
    280             DeleteOriginData(client, kPerm, kOriginA));
    281   EXPECT_EQ(0, mock_service_.delete_called_count());
    282 
    283   EXPECT_EQ(quota::kQuotaStatusOk,
    284             DeleteOriginData(client, kTemp, kOriginA));
    285   EXPECT_EQ(1, mock_service_.delete_called_count());
    286 
    287   mock_service_.set_mock_delete_appcaches_for_origin_result(
    288       net::ERR_ABORTED);
    289   EXPECT_EQ(quota::kQuotaErrorAbort,
    290             DeleteOriginData(client, kTemp, kOriginA));
    291   EXPECT_EQ(2, mock_service_.delete_called_count());
    292 
    293   Call_OnQuotaManagerDestroyed(client);
    294   Call_NotifyAppCacheDestroyed(client);
    295 }
    296 
    297 TEST_F(AppCacheQuotaClientTest, PendingRequests) {
    298   AppCacheQuotaClient* client = CreateClient();
    299 
    300   SetUsageMapEntry(kOriginA, 1000);
    301   SetUsageMapEntry(kOriginB, 10);
    302   SetUsageMapEntry(kOriginOther, 500);
    303 
    304   // Queue up some reqeusts.
    305   AsyncGetOriginUsage(client, kOriginA, kPerm);
    306   AsyncGetOriginUsage(client, kOriginB, kTemp);
    307   AsyncGetOriginsForType(client, kPerm);
    308   AsyncGetOriginsForType(client, kTemp);
    309   AsyncGetOriginsForHost(client, kTemp, kOriginA.host());
    310   AsyncGetOriginsForHost(client, kTemp, kOriginOther.host());
    311   AsyncDeleteOriginData(client, kTemp, kOriginA);
    312   AsyncDeleteOriginData(client, kPerm, kOriginA);
    313   AsyncDeleteOriginData(client, kTemp, kOriginB);
    314 
    315   EXPECT_EQ(0, num_get_origin_usage_completions_);
    316   EXPECT_EQ(0, num_get_origins_completions_);
    317   EXPECT_EQ(0, num_delete_origins_completions_);
    318   base::MessageLoop::current()->RunUntilIdle();
    319   EXPECT_EQ(0, num_get_origin_usage_completions_);
    320   EXPECT_EQ(0, num_get_origins_completions_);
    321   EXPECT_EQ(0, num_delete_origins_completions_);
    322 
    323   // Pending requests should get serviced when the appcache is ready.
    324   Call_NotifyAppCacheReady(client);
    325   EXPECT_EQ(2, num_get_origin_usage_completions_);
    326   EXPECT_EQ(4, num_get_origins_completions_);
    327   EXPECT_EQ(0, num_delete_origins_completions_);
    328   base::MessageLoop::current()->RunUntilIdle();
    329   EXPECT_EQ(3, num_delete_origins_completions_);  // deletes are really async
    330 
    331   // They should be serviced in order requested.
    332   EXPECT_EQ(10, usage_);
    333   EXPECT_EQ(1ul, origins_.size());
    334   EXPECT_TRUE(origins_.find(kOriginOther) != origins_.end());
    335 
    336   Call_NotifyAppCacheDestroyed(client);
    337   Call_OnQuotaManagerDestroyed(client);
    338 }
    339 
    340 TEST_F(AppCacheQuotaClientTest, DestroyServiceWithPending) {
    341   AppCacheQuotaClient* client = CreateClient();
    342 
    343   SetUsageMapEntry(kOriginA, 1000);
    344   SetUsageMapEntry(kOriginB, 10);
    345   SetUsageMapEntry(kOriginOther, 500);
    346 
    347   // Queue up some reqeusts prior to being ready.
    348   AsyncGetOriginUsage(client, kOriginA, kPerm);
    349   AsyncGetOriginUsage(client, kOriginB, kTemp);
    350   AsyncGetOriginsForType(client, kPerm);
    351   AsyncGetOriginsForType(client, kTemp);
    352   AsyncGetOriginsForHost(client, kTemp, kOriginA.host());
    353   AsyncGetOriginsForHost(client, kTemp, kOriginOther.host());
    354   AsyncDeleteOriginData(client, kTemp, kOriginA);
    355   AsyncDeleteOriginData(client, kPerm, kOriginA);
    356   AsyncDeleteOriginData(client, kTemp, kOriginB);
    357   base::MessageLoop::current()->RunUntilIdle();
    358   EXPECT_EQ(0, num_get_origin_usage_completions_);
    359   EXPECT_EQ(0, num_get_origins_completions_);
    360   EXPECT_EQ(0, num_delete_origins_completions_);
    361 
    362   // Kill the service.
    363   Call_NotifyAppCacheDestroyed(client);
    364 
    365   // All should have been aborted and called completion.
    366   EXPECT_EQ(2, num_get_origin_usage_completions_);
    367   EXPECT_EQ(4, num_get_origins_completions_);
    368   EXPECT_EQ(3, num_delete_origins_completions_);
    369   EXPECT_EQ(0, usage_);
    370   EXPECT_TRUE(origins_.empty());
    371   EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_);
    372 
    373   Call_OnQuotaManagerDestroyed(client);
    374 }
    375 
    376 TEST_F(AppCacheQuotaClientTest, DestroyQuotaManagerWithPending) {
    377   AppCacheQuotaClient* client = CreateClient();
    378 
    379   SetUsageMapEntry(kOriginA, 1000);
    380   SetUsageMapEntry(kOriginB, 10);
    381   SetUsageMapEntry(kOriginOther, 500);
    382 
    383   // Queue up some reqeusts prior to being ready.
    384   AsyncGetOriginUsage(client, kOriginA, kPerm);
    385   AsyncGetOriginUsage(client, kOriginB, kTemp);
    386   AsyncGetOriginsForType(client, kPerm);
    387   AsyncGetOriginsForType(client, kTemp);
    388   AsyncGetOriginsForHost(client, kTemp, kOriginA.host());
    389   AsyncGetOriginsForHost(client, kTemp, kOriginOther.host());
    390   AsyncDeleteOriginData(client, kTemp, kOriginA);
    391   AsyncDeleteOriginData(client, kPerm, kOriginA);
    392   AsyncDeleteOriginData(client, kTemp, kOriginB);
    393   base::MessageLoop::current()->RunUntilIdle();
    394   EXPECT_EQ(0, num_get_origin_usage_completions_);
    395   EXPECT_EQ(0, num_get_origins_completions_);
    396   EXPECT_EQ(0, num_delete_origins_completions_);
    397 
    398   // Kill the quota manager.
    399   Call_OnQuotaManagerDestroyed(client);
    400   Call_NotifyAppCacheReady(client);
    401 
    402   // Callbacks should be deleted and not called.
    403   base::MessageLoop::current()->RunUntilIdle();
    404   EXPECT_EQ(0, num_get_origin_usage_completions_);
    405   EXPECT_EQ(0, num_get_origins_completions_);
    406   EXPECT_EQ(0, num_delete_origins_completions_);
    407 
    408   Call_NotifyAppCacheDestroyed(client);
    409 }
    410 
    411 TEST_F(AppCacheQuotaClientTest, DestroyWithDeleteInProgress) {
    412   AppCacheQuotaClient* client = CreateClient();
    413   Call_NotifyAppCacheReady(client);
    414 
    415   // Start an async delete.
    416   AsyncDeleteOriginData(client, kTemp, kOriginB);
    417   EXPECT_EQ(0, num_delete_origins_completions_);
    418 
    419   // Kill the service.
    420   Call_NotifyAppCacheDestroyed(client);
    421 
    422   // Should have been aborted.
    423   EXPECT_EQ(1, num_delete_origins_completions_);
    424   EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_);
    425 
    426   // A real completion callback from the service should
    427   // be dropped if it comes in after NotifyAppCacheDestroyed.
    428   base::MessageLoop::current()->RunUntilIdle();
    429   EXPECT_EQ(1, num_delete_origins_completions_);
    430   EXPECT_EQ(quota::kQuotaErrorAbort, delete_status_);
    431 
    432   Call_OnQuotaManagerDestroyed(client);
    433 }
    434 
    435 }  // namespace appcache
    436