Index: webkit/browser/quota/storage_monitor_unittest.cc |
diff --git a/webkit/browser/quota/storage_monitor_unittest.cc b/webkit/browser/quota/storage_monitor_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..da1d695d2d3b3773ed7f3351bdabbaf5ae712186 |
--- /dev/null |
+++ b/webkit/browser/quota/storage_monitor_unittest.cc |
@@ -0,0 +1,640 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <vector> |
+ |
+#include "base/files/scoped_temp_dir.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/message_loop/message_loop_proxy.h" |
+#include "base/run_loop.h" |
+#include "net/base/net_util.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webkit/browser/quota/mock_special_storage_policy.h" |
+#include "webkit/browser/quota/mock_storage_client.h" |
+#include "webkit/browser/quota/quota_manager.h" |
+#include "webkit/browser/quota/quota_manager_proxy.h" |
+#include "webkit/browser/quota/storage_monitor.h" |
+#include "webkit/browser/quota/storage_observer.h" |
+ |
+namespace quota { |
+ |
+namespace { |
+ |
+const char kDefaultOrigin[] = "http://www.foo.com/"; |
+const char kAlternativeOrigin[] = "http://www.bar.com/"; |
+ |
+class MockObserver : public StorageObserver { |
+ public: |
+ const StorageObserver::Event& LastEvent() const { |
+ CHECK(!events_.empty()); |
+ return events_.back(); |
+ } |
+ |
+ int EventCount() const { |
+ return events_.size(); |
+ } |
+ |
+ // StorageObserver implementation: |
+ virtual void OnStorageEvent(const StorageObserver::Event& event) OVERRIDE { |
+ events_.push_back(event); |
+ } |
+ |
+ private: |
+ std::vector<StorageObserver::Event> events_; |
+}; |
+ |
+// A mock quota manager for overriding GetUsageAndQuotaForWebApps(). |
+class UsageMockQuotaManager : public QuotaManager { |
+ public: |
+ UsageMockQuotaManager(SpecialStoragePolicy* special_storage_policy) |
+ : QuotaManager( |
+ false, |
+ base::FilePath(), |
+ base::MessageLoopProxy::current().get(), |
+ base::MessageLoopProxy::current().get(), |
+ special_storage_policy), |
+ callback_usage_(0), |
+ callback_quota_(0), |
+ callback_status_(kQuotaStatusOk) { |
+ } |
+ |
+ void SetCallbackParams(int64 usage, int64 quota, QuotaStatusCode status) { |
+ callback_quota_ = quota; |
+ callback_usage_ = usage; |
+ callback_status_ = status; |
+ } |
+ |
+ virtual void GetUsageAndQuotaForWebApps( |
+ const GURL& origin, |
+ StorageType type, |
+ const GetUsageAndQuotaCallback& callback) OVERRIDE { |
+ callback.Run(callback_status_, callback_usage_, callback_quota_); |
+ } |
+ |
+ protected: |
+ virtual ~UsageMockQuotaManager() {} |
+ |
+ private: |
+ int64 callback_usage_; |
+ int64 callback_quota_; |
+ QuotaStatusCode callback_status_; |
+}; |
+ |
+} // namespace |
+ |
+class StorageMonitorTestBase : public testing::Test { |
+ protected: |
+ void DispatchPendingEvents(StorageObserverList& observer_list) { |
+ observer_list.DispatchPendingEvent(); |
+ } |
+ |
+ const StorageObserver::Event* GetPendingEvent( |
+ const StorageObserverList& observer_list) { |
+ return observer_list.notification_timer_.IsRunning() |
+ ? &observer_list.pending_event_ : NULL; |
+ } |
+ |
+ const StorageObserver::Event* GetPendingEvent( |
+ const HostStorageObservers& host_observers) { |
+ return GetPendingEvent(host_observers.observers_); |
+ } |
+ |
+ int GetRequiredUpdatesCount(const StorageObserverList& observer_list) { |
+ int count = 0; |
+ for (StorageObserverList::StorageObserverStateMap::const_iterator it = |
+ observer_list.observers_.begin(); |
+ it != observer_list.observers_.end(); ++it) { |
+ if (it->second.requires_update) |
+ ++count; |
+ } |
+ |
+ return count; |
+ } |
+ |
+ int GetRequiredUpdatesCount(const HostStorageObservers& host_observers) { |
+ return GetRequiredUpdatesCount(host_observers.observers_); |
+ } |
+ |
+ void SetLastNotificationTime(StorageObserverList& observer_list, |
+ StorageObserver* observer) { |
+ ASSERT_TRUE(observer_list.observers_.find(observer) != |
+ observer_list.observers_.end()); |
+ |
+ StorageObserverList::ObserverState& state = |
+ observer_list.observers_[observer]; |
+ state.last_notification_time = base::TimeTicks::Now() - state.rate; |
+ } |
+ |
+ void SetLastNotificationTime(HostStorageObservers& host_observers, |
+ StorageObserver* observer) { |
+ SetLastNotificationTime(host_observers.observers_, observer); |
+ } |
+ |
+ int GetObserverCount(const HostStorageObservers& host_observers) { |
+ return host_observers.observers_.ObserverCount(); |
+ } |
+}; |
+ |
+class StorageTestWithManagerBase : public StorageMonitorTestBase { |
+ public: |
+ virtual void SetUp() OVERRIDE { |
+ storage_policy_ = new MockSpecialStoragePolicy(); |
+ quota_manager_ = new UsageMockQuotaManager(storage_policy_.get()); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { |
+ // This ensures the quota manager is destroyed correctly. |
+ quota_manager_ = NULL; |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ protected: |
+ base::MessageLoop message_loop_; |
+ scoped_refptr<MockSpecialStoragePolicy> storage_policy_; |
+ scoped_refptr<UsageMockQuotaManager> quota_manager_; |
+}; |
+ |
+// Tests for StorageObserverList: |
+ |
+typedef StorageMonitorTestBase StorageObserverListTest; |
+ |
+// Test dispatching events to one observer. |
+TEST_F(StorageObserverListTest, DispatchEventToSingleObserver) { |
+ // A message loop is required as StorageObserverList may schedule jobs. |
+ base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); |
+ |
+ StorageObserver::MonitorParams params(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ MockObserver mock_observer; |
+ StorageObserverList observer_list; |
+ observer_list.AddObserver(&mock_observer, params); |
+ |
+ StorageObserver::Event event; |
+ event.filter = params.filter; |
+ |
+ // Verify that the first event is dispatched immediately. |
+ event.quota = 1; |
+ event.usage = 1; |
+ observer_list.OnStorageChange(event); |
+ EXPECT_EQ(1, mock_observer.EventCount()); |
+ EXPECT_EQ(event, mock_observer.LastEvent()); |
+ EXPECT_EQ(NULL, GetPendingEvent(observer_list)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); |
+ |
+ // Verify that the next event is pending. |
+ event.quota = 2; |
+ event.usage = 2; |
+ observer_list.OnStorageChange(event); |
+ EXPECT_EQ(1, mock_observer.EventCount()); |
+ ASSERT_TRUE(GetPendingEvent(observer_list)); |
+ EXPECT_EQ(event, *GetPendingEvent(observer_list)); |
+ EXPECT_EQ(1, GetRequiredUpdatesCount(observer_list)); |
+ |
+ // Fake the last notification time so that an event will be dispatched. |
+ SetLastNotificationTime(observer_list, &mock_observer); |
+ event.quota = 3; |
+ event.usage = 3; |
+ observer_list.OnStorageChange(event); |
+ EXPECT_EQ(2, mock_observer.EventCount()); |
+ EXPECT_EQ(event, mock_observer.LastEvent()); |
+ EXPECT_EQ(NULL, GetPendingEvent(observer_list)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); |
+ |
+ // Remove the observer. |
+ event.quota = 4; |
+ event.usage = 4; |
+ observer_list.RemoveObserver(&mock_observer); |
+ observer_list.OnStorageChange(event); |
+ EXPECT_EQ(2, mock_observer.EventCount()); |
+ EXPECT_EQ(NULL, GetPendingEvent(observer_list)); |
+} |
+ |
+// Test dispatching events to multiple observers. |
+TEST_F(StorageObserverListTest, DispatchEventToMultipleObservers) { |
+ // A message loop is required as StorageObserverList may schedule jobs. |
+ base::MessageLoop loop(base::MessageLoop::TYPE_DEFAULT); |
+ |
+ MockObserver mock_observer1; |
+ MockObserver mock_observer2; |
+ StorageObserverList observer_list; |
+ StorageObserver::Filter filter(kStorageTypePersistent, |
+ GURL(kDefaultOrigin)); |
+ observer_list.AddObserver( |
+ &mock_observer1, |
+ StorageObserver::MonitorParams( |
+ filter, base::TimeDelta::FromHours(1), false)); |
+ observer_list.AddObserver( |
+ &mock_observer2, |
+ StorageObserver::MonitorParams( |
+ filter, base::TimeDelta::FromHours(2), false)); |
+ |
+ StorageObserver::Event event; |
+ event.filter = filter; |
+ |
+ // Verify that the first event is dispatched immediately. |
+ event.quota = 1; |
+ event.usage = 1; |
+ observer_list.OnStorageChange(event); |
+ EXPECT_EQ(1, mock_observer1.EventCount()); |
+ EXPECT_EQ(1, mock_observer2.EventCount()); |
+ EXPECT_EQ(event, mock_observer1.LastEvent()); |
+ EXPECT_EQ(event, mock_observer2.LastEvent()); |
+ EXPECT_EQ(NULL, GetPendingEvent(observer_list)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); |
+ |
+ // Fake the last notification time so that observer1 will receive the next |
+ // event, but it will be pending for observer2. |
+ SetLastNotificationTime(observer_list, &mock_observer1); |
+ event.quota = 2; |
+ event.usage = 2; |
+ observer_list.OnStorageChange(event); |
+ EXPECT_EQ(2, mock_observer1.EventCount()); |
+ EXPECT_EQ(1, mock_observer2.EventCount()); |
+ EXPECT_EQ(event, mock_observer1.LastEvent()); |
+ ASSERT_TRUE(GetPendingEvent(observer_list)); |
+ EXPECT_EQ(event, *GetPendingEvent(observer_list)); |
+ EXPECT_EQ(1, GetRequiredUpdatesCount(observer_list)); |
+ |
+ // Now dispatch the pending event to observer2. |
+ SetLastNotificationTime(observer_list, &mock_observer2); |
+ DispatchPendingEvents(observer_list); |
+ EXPECT_EQ(2, mock_observer1.EventCount()); |
+ EXPECT_EQ(2, mock_observer2.EventCount()); |
+ EXPECT_EQ(event, mock_observer1.LastEvent()); |
+ EXPECT_EQ(event, mock_observer2.LastEvent()); |
+ EXPECT_EQ(NULL, GetPendingEvent(observer_list)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(observer_list)); |
+} |
+ |
+// Ensure that the |origin| field in events match the origin specified by the |
+// observer on registration. |
+TEST_F(StorageObserverListTest, ReplaceEventOrigin) { |
+ StorageObserver::MonitorParams params(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ MockObserver mock_observer; |
+ StorageObserverList observer_list; |
+ observer_list.AddObserver(&mock_observer, params); |
+ |
+ StorageObserver::Event dispatched_event; |
+ dispatched_event.filter = params.filter; |
+ dispatched_event.filter.origin = GURL("https://www.foo.com/bar"); |
+ observer_list.OnStorageChange(dispatched_event); |
+ |
+ EXPECT_EQ(params.filter.origin, mock_observer.LastEvent().filter.origin); |
+} |
+ |
+// Tests for HostStorageObservers: |
+ |
+typedef StorageTestWithManagerBase HostStorageObserversTest; |
+ |
+// Verify that HostStorageObservers is initialized after the first usage change. |
+TEST_F(HostStorageObserversTest, InitializeOnUsageChange) { |
+ StorageObserver::MonitorParams params(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ const int64 kUsage = 324554; |
+ const int64 kQuota = 234354354; |
+ quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk); |
+ |
+ MockObserver mock_observer; |
+ HostStorageObservers host_observers(quota_manager_.get()); |
+ host_observers.AddObserver(&mock_observer, params); |
+ |
+ // Verify that HostStorageObservers dispatches the first event correctly. |
+ StorageObserver::Event expected_event(params.filter, kUsage, kQuota); |
+ host_observers.NotifyUsageChange(params.filter, 87324); |
+ EXPECT_EQ(1, mock_observer.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer.LastEvent()); |
+ EXPECT_TRUE(host_observers.is_initialized()); |
+ |
+ // Verify that HostStorageObservers handles subsequent usage changes |
+ // correctly. |
+ const int64 kDelta = 2345; |
+ expected_event.usage += kDelta; |
+ SetLastNotificationTime(host_observers, &mock_observer); |
+ host_observers.NotifyUsageChange(params.filter, kDelta); |
+ EXPECT_EQ(2, mock_observer.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer.LastEvent()); |
+} |
+ |
+// Verify that HostStorageObservers is initialized after the adding the first |
+// observer that elected to receive the initial state. |
+TEST_F(HostStorageObserversTest, InitializeOnObserver) { |
+ const int64 kUsage = 74387; |
+ const int64 kQuota = 92834743; |
+ quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk); |
+ HostStorageObservers host_observers(quota_manager_.get()); |
+ |
+ // |host_observers| should not be initialized after the first observer is |
+ // added because it did not elect to receive the initial state. |
+ StorageObserver::MonitorParams params(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ MockObserver mock_observer1; |
+ host_observers.AddObserver(&mock_observer1, params); |
+ EXPECT_FALSE(host_observers.is_initialized()); |
+ EXPECT_EQ(0, mock_observer1.EventCount()); |
+ |
+ // |host_observers| should be initialized after the second observer is |
+ // added. |
+ MockObserver mock_observer2; |
+ params.dispatch_initial_state = true; |
+ host_observers.AddObserver(&mock_observer2, params); |
+ StorageObserver::Event expected_event(params.filter, kUsage, kQuota); |
+ EXPECT_EQ(0, mock_observer1.EventCount()); |
+ EXPECT_EQ(1, mock_observer2.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer2.LastEvent()); |
+ EXPECT_TRUE(host_observers.is_initialized()); |
+ EXPECT_EQ(NULL, GetPendingEvent(host_observers)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); |
+ |
+ // Verify that both observers will receive events after a usage change. |
+ const int64 kDelta = 2345; |
+ expected_event.usage += kDelta; |
+ SetLastNotificationTime(host_observers, &mock_observer2); |
+ host_observers.NotifyUsageChange(params.filter, kDelta); |
+ EXPECT_EQ(1, mock_observer1.EventCount()); |
+ EXPECT_EQ(2, mock_observer2.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer1.LastEvent()); |
+ EXPECT_EQ(expected_event, mock_observer2.LastEvent()); |
+ EXPECT_EQ(NULL, GetPendingEvent(host_observers)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); |
+ |
+ // Verify that the addition of a third observer only causes an event to be |
+ // dispatched to the new observer. |
+ MockObserver mock_observer3; |
+ params.dispatch_initial_state = true; |
+ host_observers.AddObserver(&mock_observer3, params); |
+ EXPECT_EQ(1, mock_observer1.EventCount()); |
+ EXPECT_EQ(2, mock_observer2.EventCount()); |
+ EXPECT_EQ(1, mock_observer3.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer3.LastEvent()); |
+} |
+ |
+// Verify that negative usage and quota is changed to zero. |
+TEST_F(HostStorageObserversTest, NegativeUsageAndQuota) { |
+ StorageObserver::MonitorParams params(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ const int64 kUsage = -324554; |
+ const int64 kQuota = -234354354; |
+ quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk); |
+ |
+ MockObserver mock_observer; |
+ HostStorageObservers host_observers(quota_manager_.get()); |
+ host_observers.AddObserver(&mock_observer, params); |
+ |
+ StorageObserver::Event expected_event(params.filter, 0, 0); |
+ host_observers.NotifyUsageChange(params.filter, -87324); |
+ EXPECT_EQ(expected_event, mock_observer.LastEvent()); |
+} |
+ |
+// Verify that HostStorageObservers can recover from a bad initialization. |
+TEST_F(HostStorageObserversTest, RecoverFromBadUsageInit) { |
+ StorageObserver::MonitorParams params(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ MockObserver mock_observer; |
+ HostStorageObservers host_observers(quota_manager_.get()); |
+ host_observers.AddObserver(&mock_observer, params); |
+ |
+ // Set up the quota manager to return an error status. |
+ const int64 kUsage = 6656; |
+ const int64 kQuota = 99585556; |
+ quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaErrorNotSupported); |
+ |
+ // Verify that |host_observers| is not initialized and an event has not been |
+ // dispatched. |
+ host_observers.NotifyUsageChange(params.filter, 9438); |
+ EXPECT_EQ(0, mock_observer.EventCount()); |
+ EXPECT_FALSE(host_observers.is_initialized()); |
+ EXPECT_EQ(NULL, GetPendingEvent(host_observers)); |
+ EXPECT_EQ(0, GetRequiredUpdatesCount(host_observers)); |
+ |
+ // Now ensure that quota manager returns a good status. |
+ quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk); |
+ host_observers.NotifyUsageChange(params.filter, 9048543); |
+ StorageObserver::Event expected_event(params.filter, kUsage, kQuota); |
+ EXPECT_EQ(1, mock_observer.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer.LastEvent()); |
+ EXPECT_TRUE(host_observers.is_initialized()); |
+} |
+ |
+// Tests for StorageTypeObservers: |
+ |
+typedef StorageTestWithManagerBase StorageTypeObserversTest; |
+ |
+// Test adding and removing observers. |
+TEST_F(StorageTypeObserversTest, AddRemoveObservers) { |
+ StorageTypeObservers type_observers(quota_manager_.get()); |
+ |
+ StorageObserver::MonitorParams params1(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ StorageObserver::MonitorParams params2(kStorageTypePersistent, |
+ GURL(kAlternativeOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ std::string host1 = net::GetHostOrSpecFromURL(params1.filter.origin); |
+ std::string host2 = net::GetHostOrSpecFromURL(params2.filter.origin); |
+ |
+ MockObserver mock_observer1; |
+ MockObserver mock_observer2; |
+ MockObserver mock_observer3; |
+ type_observers.AddObserver(&mock_observer1, params1); |
+ type_observers.AddObserver(&mock_observer2, params1); |
+ |
+ type_observers.AddObserver(&mock_observer1, params2); |
+ type_observers.AddObserver(&mock_observer2, params2); |
+ type_observers.AddObserver(&mock_observer3, params2); |
+ |
+ // Verify that the observers have been removed correctly. |
+ ASSERT_TRUE(type_observers.GetHostObservers(host1)); |
+ ASSERT_TRUE(type_observers.GetHostObservers(host2)); |
+ EXPECT_EQ(2, GetObserverCount(*type_observers.GetHostObservers(host1))); |
+ EXPECT_EQ(3, GetObserverCount(*type_observers.GetHostObservers(host2))); |
+ |
+ // Remove an observer for a specific filter. |
+ type_observers.RemoveObserverForFilter(&mock_observer1, params1.filter); |
+ ASSERT_TRUE(type_observers.GetHostObservers(host1)); |
+ ASSERT_TRUE(type_observers.GetHostObservers(host2)); |
+ EXPECT_EQ(1, GetObserverCount(*type_observers.GetHostObservers(host1))); |
+ EXPECT_EQ(3, GetObserverCount(*type_observers.GetHostObservers(host2))); |
+ |
+ // Remove all instances of an observer. |
+ type_observers.RemoveObserver(&mock_observer2); |
+ ASSERT_TRUE(type_observers.GetHostObservers(host2)); |
+ EXPECT_EQ(2, GetObserverCount(*type_observers.GetHostObservers(host2))); |
+ // Observers of host1 has been deleted as it is empty. |
+ EXPECT_FALSE(type_observers.GetHostObservers(host1)); |
+} |
+ |
+// Tests for StorageMonitor: |
+ |
+class StorageMonitorTest : public StorageTestWithManagerBase { |
+ public: |
+ StorageMonitorTest() |
+ : storage_monitor_(NULL), |
+ params1_(kStorageTypeTemporary, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false), |
+ params2_(kStorageTypePersistent, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false) { |
+ } |
+ |
+ protected: |
+ virtual void SetUp() OVERRIDE { |
+ StorageTestWithManagerBase::SetUp(); |
+ |
+ storage_monitor_ = quota_manager_->storage_monitor_.get(); |
+ host_ = net::GetHostOrSpecFromURL(params1_.filter.origin); |
+ |
+ storage_monitor_->AddObserver(&mock_observer1_, params1_); |
+ storage_monitor_->AddObserver(&mock_observer2_, params1_); |
+ |
+ storage_monitor_->AddObserver(&mock_observer1_, params2_); |
+ storage_monitor_->AddObserver(&mock_observer2_, params2_); |
+ storage_monitor_->AddObserver(&mock_observer3_, params2_); |
+ } |
+ |
+ int GetObserverCount(StorageType storage_type) { |
+ const StorageTypeObservers* type_observers = |
+ storage_monitor_->GetStorageTypeObservers(storage_type); |
+ return StorageMonitorTestBase::GetObserverCount( |
+ *type_observers->GetHostObservers(host_)); |
+ } |
+ |
+ void CheckObserverCount(int expected_temporary, int expected_persistent) { |
+ ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers( |
+ kStorageTypeTemporary)); |
+ ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers( |
+ kStorageTypeTemporary)->GetHostObservers(host_)); |
+ EXPECT_EQ(expected_temporary, GetObserverCount(kStorageTypeTemporary)); |
+ |
+ ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers( |
+ kStorageTypePersistent)); |
+ ASSERT_TRUE(storage_monitor_->GetStorageTypeObservers( |
+ kStorageTypePersistent)->GetHostObservers(host_)); |
+ EXPECT_EQ(expected_persistent, GetObserverCount(kStorageTypePersistent)); |
+ } |
+ |
+ StorageMonitor* storage_monitor_; |
+ StorageObserver::MonitorParams params1_; |
+ StorageObserver::MonitorParams params2_; |
+ MockObserver mock_observer1_; |
+ MockObserver mock_observer2_; |
+ MockObserver mock_observer3_; |
+ std::string host_; |
+}; |
+ |
+// Test adding storage observers. |
+TEST_F(StorageMonitorTest, AddObservers) { |
+ // Verify that the observers are added correctly. |
+ CheckObserverCount(2, 3); |
+} |
+ |
+// Test dispatching events to storage observers. |
+TEST_F(StorageMonitorTest, EventDispatch) { |
+ // Verify dispatch of events. |
+ const int64 kUsage = 5325; |
+ const int64 kQuota = 903845; |
+ quota_manager_->SetCallbackParams(kUsage, kQuota, kQuotaStatusOk); |
+ storage_monitor_->NotifyUsageChange(params1_.filter, 9048543); |
+ |
+ StorageObserver::Event expected_event(params1_.filter, kUsage, kQuota); |
+ EXPECT_EQ(1, mock_observer1_.EventCount()); |
+ EXPECT_EQ(1, mock_observer2_.EventCount()); |
+ EXPECT_EQ(0, mock_observer3_.EventCount()); |
+ EXPECT_EQ(expected_event, mock_observer1_.LastEvent()); |
+ EXPECT_EQ(expected_event, mock_observer2_.LastEvent()); |
+} |
+ |
+// Test removing all instances of an observer. |
+TEST_F(StorageMonitorTest, RemoveObserver) { |
+ storage_monitor_->RemoveObserver(&mock_observer1_); |
+ CheckObserverCount(1, 2); |
+} |
+ |
+// Test removing an observer for a specific filter. |
+TEST_F(StorageMonitorTest, RemoveObserverForFilter) { |
+ storage_monitor_->RemoveObserverForFilter(&mock_observer1_, params2_.filter); |
+ CheckObserverCount(2, 2); |
+} |
+ |
+// Integration test for QuotaManager and StorageMonitor: |
+ |
+class StorageMonitorIntegrationTest : public testing::Test { |
+ public: |
+ virtual void SetUp() OVERRIDE { |
+ ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); |
+ storage_policy_ = new MockSpecialStoragePolicy(); |
+ quota_manager_ = new QuotaManager( |
+ false, |
+ data_dir_.path(), |
+ base::MessageLoopProxy::current().get(), |
+ base::MessageLoopProxy::current().get(), |
+ storage_policy_.get()); |
+ |
+ client_ = new MockStorageClient(quota_manager_->proxy(), |
+ NULL, |
+ QuotaClient::kFileSystem, |
+ 0); |
+ |
+ quota_manager_->proxy()->RegisterClient(client_); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { |
+ // This ensures the quota manager is destroyed correctly. |
+ quota_manager_ = NULL; |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ protected: |
+ base::MessageLoop message_loop_; |
+ base::ScopedTempDir data_dir_; |
+ scoped_refptr<MockSpecialStoragePolicy> storage_policy_; |
+ scoped_refptr<QuotaManager> quota_manager_; |
+ MockStorageClient* client_; |
+}; |
+ |
+// This test simulates a usage change in a quota client and verifies that a |
+// storage observer will receive a storage event. |
+TEST_F(StorageMonitorIntegrationTest, NotifyUsageEvent) { |
+ const StorageType kTestStorageType = kStorageTypePersistent; |
+ const int64 kTestUsage = 234743; |
+ |
+ // Register the observer. |
+ StorageObserver::MonitorParams params(kTestStorageType, |
+ GURL(kDefaultOrigin), |
+ base::TimeDelta::FromHours(1), |
+ false); |
+ MockObserver mock_observer; |
+ quota_manager_->AddStorageObserver(&mock_observer, params); |
+ |
+ // Fire a usage change. |
+ client_->AddOriginAndNotify(GURL(kDefaultOrigin), |
+ kTestStorageType, |
+ kTestUsage); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ // Verify that the observer receives it. |
+ ASSERT_EQ(1, mock_observer.EventCount()); |
+ const StorageObserver::Event& event = mock_observer.LastEvent(); |
+ EXPECT_EQ(params.filter, event.filter); |
+ EXPECT_EQ(kTestUsage, event.usage); |
+} |
+ |
+} // namespace quota |