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