root/webkit/browser/quota/storage_monitor_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. LastEvent
  2. EventCount
  3. OnStorageEvent
  4. callback_status_
  5. SetCallbackParams
  6. GetUsageAndQuotaForWebApps
  7. DispatchPendingEvents
  8. GetPendingEvent
  9. GetPendingEvent
  10. GetRequiredUpdatesCount
  11. GetRequiredUpdatesCount
  12. SetLastNotificationTime
  13. SetLastNotificationTime
  14. GetObserverCount
  15. SetUp
  16. TearDown
  17. TEST_F
  18. TEST_F
  19. TEST_F
  20. TEST_F
  21. TEST_F
  22. TEST_F
  23. TEST_F
  24. TEST_F
  25. params2_
  26. SetUp
  27. GetObserverCount
  28. CheckObserverCount
  29. TEST_F
  30. TEST_F
  31. TEST_F
  32. TEST_F
  33. SetUp
  34. TearDown
  35. TEST_F

// 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

/* [<][>][^][v][top][bottom][index][help] */