// Copyright (c) 2012 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 "sync/notifier/registration_manager.h"

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <deque>
#include <vector>

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "google/cacheinvalidation/include/invalidation-client.h"
#include "sync/notifier/invalidation_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace syncer {
namespace {

// Fake registration manager that lets you override jitter.
class FakeRegistrationManager : public RegistrationManager {
 public:
  explicit FakeRegistrationManager(
      invalidation::InvalidationClient* invalidation_client)
      : RegistrationManager(invalidation_client),
        jitter_(0.0) {}

  virtual ~FakeRegistrationManager() {}

  void SetJitter(double jitter) {
    jitter_ = jitter;
  }

 protected:
  virtual double GetJitter() {
    return jitter_;
  }

 private:
  double jitter_;

  DISALLOW_COPY_AND_ASSIGN(FakeRegistrationManager);
};

// Fake invalidation client that just stores the currently-registered
// object IDs.
class FakeInvalidationClient : public invalidation::InvalidationClient {
 public:
  FakeInvalidationClient() {}

  virtual ~FakeInvalidationClient() {}

  void LoseRegistration(const invalidation::ObjectId& oid) {
    EXPECT_TRUE(ContainsKey(registered_ids_, oid));
    registered_ids_.erase(oid);
  }

  void LoseAllRegistrations() {
    registered_ids_.clear();
  }

  // invalidation::InvalidationClient implementation.

  virtual void Start() {}
  virtual void Stop() {}
  virtual void Acknowledge(const invalidation::AckHandle& handle) {}

  virtual void Register(const invalidation::ObjectId& oid) {
    EXPECT_FALSE(ContainsKey(registered_ids_, oid));
    registered_ids_.insert(oid);
  }

  virtual void Register(const std::vector<invalidation::ObjectId>& oids) {
    // Unused for now.
  }

  virtual void Unregister(const invalidation::ObjectId& oid) {
    EXPECT_TRUE(ContainsKey(registered_ids_, oid));
    registered_ids_.erase(oid);
  }

  virtual void Unregister(const std::vector<invalidation::ObjectId>& oids) {
    // Unused for now.
  }

  const ObjectIdSet& GetRegisteredIdsForTest() const {
    return registered_ids_;
  }

 private:
  ObjectIdSet registered_ids_;

  DISALLOW_COPY_AND_ASSIGN(FakeInvalidationClient);
};

size_t kObjectIdsCount = 5;

invalidation::ObjectId GetIdForIndex(size_t index) {
  char name[2] = "a";
  name[0] += static_cast<char>(index);
  return invalidation::ObjectId(1 + index, name);
}

ObjectIdSet GetSequenceOfIdsStartingAt(size_t start, size_t count) {
  ObjectIdSet ids;
  for (size_t i = start; i < start + count; ++i)
    ids.insert(GetIdForIndex(i));
  return ids;
}

ObjectIdSet GetSequenceOfIds(size_t count) {
  return GetSequenceOfIdsStartingAt(0, count);
}

void ExpectPendingRegistrations(
    const ObjectIdSet& expected_pending_ids,
    double expected_delay_seconds,
    const RegistrationManager::PendingRegistrationMap& pending_registrations) {
  ObjectIdSet pending_ids;
  for (RegistrationManager::PendingRegistrationMap::const_iterator it =
           pending_registrations.begin(); it != pending_registrations.end();
       ++it) {
    SCOPED_TRACE(ObjectIdToString(it->first));
    pending_ids.insert(it->first);
    base::TimeDelta offset =
        it->second.last_registration_request -
        it->second.registration_attempt;
    base::TimeDelta expected_delay =
        base::TimeDelta::FromSeconds(
            static_cast<int64>(expected_delay_seconds)) + offset;
    // TODO(akalin): Add base::PrintTo() for base::Time and
    // base::TimeDeltas.
    EXPECT_EQ(expected_delay, it->second.delay)
        << expected_delay.InMicroseconds()
        << ", " << it->second.delay.InMicroseconds();
    if (it->second.delay <= base::TimeDelta()) {
      EXPECT_EQ(base::TimeDelta(), it->second.actual_delay);
    } else {
      EXPECT_EQ(it->second.actual_delay, it->second.delay);
    }
  }
  EXPECT_EQ(expected_pending_ids, pending_ids);
}

class RegistrationManagerTest : public testing::Test {
 protected:
  RegistrationManagerTest()
      : fake_registration_manager_(&fake_invalidation_client_) {}

  virtual ~RegistrationManagerTest() {}

  void LoseRegistrations(const ObjectIdSet& oids) {
    for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end();
         ++it) {
      fake_invalidation_client_.LoseRegistration(*it);
      fake_registration_manager_.MarkRegistrationLost(*it);
    }
  }

  void DisableIds(const ObjectIdSet& oids) {
    for (ObjectIdSet::const_iterator it = oids.begin(); it != oids.end();
         ++it) {
      fake_invalidation_client_.LoseRegistration(*it);
      fake_registration_manager_.DisableId(*it);
    }
  }

  // Used by MarkRegistrationLostBackoff* tests.
  void RunBackoffTest(double jitter) {
    fake_registration_manager_.SetJitter(jitter);
    ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);
    fake_registration_manager_.SetRegisteredIds(ids);

    // Lose some ids.
    ObjectIdSet lost_ids = GetSequenceOfIds(2);
    LoseRegistrations(lost_ids);
    ExpectPendingRegistrations(
        lost_ids, 0.0,
        fake_registration_manager_.GetPendingRegistrationsForTest());

    // Trigger another failure to start delaying.
    fake_registration_manager_.FirePendingRegistrationsForTest();
    LoseRegistrations(lost_ids);

    double scaled_jitter =
        jitter * RegistrationManager::kRegistrationDelayMaxJitter;

    double expected_delay =
        RegistrationManager::kInitialRegistrationDelaySeconds *
        (1.0 + scaled_jitter);
    expected_delay = std::floor(expected_delay);
    ExpectPendingRegistrations(
        lost_ids, expected_delay,
        fake_registration_manager_.GetPendingRegistrationsForTest());

    // Trigger another failure.
    fake_registration_manager_.FirePendingRegistrationsForTest();
    LoseRegistrations(lost_ids);
    expected_delay *=
        RegistrationManager::kRegistrationDelayExponent + scaled_jitter;
    expected_delay = std::floor(expected_delay);
    ExpectPendingRegistrations(
        lost_ids, expected_delay,
        fake_registration_manager_.GetPendingRegistrationsForTest());

    // Trigger enough failures to hit the ceiling.
    while (expected_delay < RegistrationManager::kMaxRegistrationDelaySeconds) {
      fake_registration_manager_.FirePendingRegistrationsForTest();
      LoseRegistrations(lost_ids);
      expected_delay *=
          RegistrationManager::kRegistrationDelayExponent + scaled_jitter;
      expected_delay = std::floor(expected_delay);
    }
    ExpectPendingRegistrations(
        lost_ids,
        RegistrationManager::kMaxRegistrationDelaySeconds,
        fake_registration_manager_.GetPendingRegistrationsForTest());
  }

  FakeInvalidationClient fake_invalidation_client_;
  FakeRegistrationManager fake_registration_manager_;

 private:
  // Needed by timers in RegistrationManager.
  MessageLoop message_loop_;

  DISALLOW_COPY_AND_ASSIGN(RegistrationManagerTest);
};

// Basic test of SetRegisteredIds to make sure we properly register new IDs and
// unregister any IDs no longer in the set.
TEST_F(RegistrationManagerTest, SetRegisteredIds) {
  ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount - 1);

  EXPECT_TRUE(fake_registration_manager_.GetRegisteredIdsForTest().empty());
  EXPECT_TRUE(fake_invalidation_client_.GetRegisteredIdsForTest().empty());

  fake_registration_manager_.SetRegisteredIds(ids);
  EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
  EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());

  ids.insert(GetIdForIndex(kObjectIdsCount - 1));
  ids.erase(GetIdForIndex(kObjectIdsCount - 2));
  fake_registration_manager_.SetRegisteredIds(ids);
  EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
  EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
}

int GetRoundedBackoff(double retry_interval, double jitter) {
  const double kInitialRetryInterval = 3.0;
  const double kMinRetryInterval = 2.0;
  const double kMaxRetryInterval = 20.0;
  const double kBackoffExponent = 2.0;
  const double kMaxJitter = 0.5;

  return static_cast<int>(
      RegistrationManager::CalculateBackoff(retry_interval,
                                            kInitialRetryInterval,
                                            kMinRetryInterval,
                                            kMaxRetryInterval,
                                            kBackoffExponent,
                                            jitter,
                                            kMaxJitter));
}

TEST_F(RegistrationManagerTest, CalculateBackoff) {
  // Test initial.
  EXPECT_EQ(2, GetRoundedBackoff(0.0, -1.0));
  EXPECT_EQ(3, GetRoundedBackoff(0.0,  0.0));
  EXPECT_EQ(4, GetRoundedBackoff(0.0, +1.0));

  // Test non-initial.
  EXPECT_EQ(4, GetRoundedBackoff(3.0, -1.0));
  EXPECT_EQ(6, GetRoundedBackoff(3.0,  0.0));
  EXPECT_EQ(7, GetRoundedBackoff(3.0, +1.0));

  EXPECT_EQ(7, GetRoundedBackoff(5.0, -1.0));
  EXPECT_EQ(10, GetRoundedBackoff(5.0,  0.0));
  EXPECT_EQ(12, GetRoundedBackoff(5.0, +1.0));

  // Test ceiling.
  EXPECT_EQ(19, GetRoundedBackoff(13.0, -1.0));
  EXPECT_EQ(20, GetRoundedBackoff(13.0,  0.0));
  EXPECT_EQ(20, GetRoundedBackoff(13.0, +1.0));
}

// Losing a registration should queue automatic re-registration.
TEST_F(RegistrationManagerTest, MarkRegistrationLost) {
  ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);

  fake_registration_manager_.SetRegisteredIds(ids);
  EXPECT_TRUE(
      fake_registration_manager_.GetPendingRegistrationsForTest().empty());

  // Lose some ids.
  ObjectIdSet lost_ids = GetSequenceOfIds(3);
  ObjectIdSet non_lost_ids = GetSequenceOfIdsStartingAt(3, kObjectIdsCount - 3);
  LoseRegistrations(lost_ids);
  ExpectPendingRegistrations(
      lost_ids, 0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());
  EXPECT_EQ(non_lost_ids, fake_registration_manager_.GetRegisteredIdsForTest());
  EXPECT_EQ(non_lost_ids, fake_invalidation_client_.GetRegisteredIdsForTest());

  // Pretend we waited long enough to re-register.
  fake_registration_manager_.FirePendingRegistrationsForTest();
  EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
  EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
}

TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffLow) {
  RunBackoffTest(-1.0);
}

TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffMid) {
  RunBackoffTest(0.0);
}

TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffHigh) {
  RunBackoffTest(+1.0);
}

// Exponential backoff on lost registrations should be reset to zero if
// SetRegisteredIds is called.
TEST_F(RegistrationManagerTest, MarkRegistrationLostBackoffReset) {
  ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);

  fake_registration_manager_.SetRegisteredIds(ids);

  // Lose some ids.
  ObjectIdSet lost_ids = GetSequenceOfIds(2);
  LoseRegistrations(lost_ids);
  ExpectPendingRegistrations(
      lost_ids, 0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());

  // Trigger another failure to start delaying.
  fake_registration_manager_.FirePendingRegistrationsForTest();
  LoseRegistrations(lost_ids);
  double expected_delay =
      RegistrationManager::kInitialRegistrationDelaySeconds;
  ExpectPendingRegistrations(
      lost_ids, expected_delay,
      fake_registration_manager_.GetPendingRegistrationsForTest());

  // Set ids again.
  fake_registration_manager_.SetRegisteredIds(ids);
  ExpectPendingRegistrations(
      ObjectIdSet(),
      0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());
}

TEST_F(RegistrationManagerTest, MarkAllRegistrationsLost) {
  ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);

  fake_registration_manager_.SetRegisteredIds(ids);

  fake_invalidation_client_.LoseAllRegistrations();
  fake_registration_manager_.MarkAllRegistrationsLost();

  EXPECT_TRUE(fake_registration_manager_.GetRegisteredIdsForTest().empty());
  EXPECT_TRUE(fake_invalidation_client_.GetRegisteredIdsForTest().empty());

  ExpectPendingRegistrations(
      ids, 0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());

  // Trigger another failure to start delaying.
  fake_registration_manager_.FirePendingRegistrationsForTest();
  fake_invalidation_client_.LoseAllRegistrations();
  fake_registration_manager_.MarkAllRegistrationsLost();
  double expected_delay =
      RegistrationManager::kInitialRegistrationDelaySeconds;
  ExpectPendingRegistrations(
      ids, expected_delay,
      fake_registration_manager_.GetPendingRegistrationsForTest());

  // Pretend we waited long enough to re-register.
  fake_registration_manager_.FirePendingRegistrationsForTest();
  EXPECT_EQ(ids, fake_registration_manager_.GetRegisteredIdsForTest());
  EXPECT_EQ(ids, fake_invalidation_client_.GetRegisteredIdsForTest());
}

// IDs that are disabled should not be re-registered by SetRegisteredIds or
// automatic re-registration if that registration is lost.
TEST_F(RegistrationManagerTest, DisableId) {
  ObjectIdSet ids = GetSequenceOfIds(kObjectIdsCount);

  fake_registration_manager_.SetRegisteredIds(ids);
  EXPECT_TRUE(
      fake_registration_manager_.GetPendingRegistrationsForTest().empty());

  // Disable some ids.
  ObjectIdSet disabled_ids = GetSequenceOfIds(3);
  ObjectIdSet enabled_ids = GetSequenceOfIdsStartingAt(3, kObjectIdsCount - 3);
  DisableIds(disabled_ids);
  ExpectPendingRegistrations(
      ObjectIdSet(),
      0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());
  EXPECT_EQ(enabled_ids, fake_registration_manager_.GetRegisteredIdsForTest());
  EXPECT_EQ(enabled_ids, fake_invalidation_client_.GetRegisteredIdsForTest());

  fake_registration_manager_.SetRegisteredIds(ids);
  EXPECT_EQ(enabled_ids, fake_registration_manager_.GetRegisteredIdsForTest());

  fake_registration_manager_.MarkRegistrationLost(
      *disabled_ids.begin());
  ExpectPendingRegistrations(
      ObjectIdSet(),
      0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());

  fake_registration_manager_.MarkAllRegistrationsLost();
  ExpectPendingRegistrations(
      enabled_ids, 0.0,
      fake_registration_manager_.GetPendingRegistrationsForTest());
}

}  // namespace
}  // namespace syncer
