// Copyright 2012 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//
// Helper classes for tests including a mock Scheduler, a mock network, a
// mock storage layer, and a mock listener.

#ifndef GOOGLE_CACHEINVALIDATION_TEST_TEST_UTILS_H_
#define GOOGLE_CACHEINVALIDATION_TEST_TEST_UTILS_H_

#include "google/cacheinvalidation/client_protocol.pb.h"
#include "google/cacheinvalidation/include/invalidation-listener.h"
#include "google/cacheinvalidation/include/types.h"
#include "google/cacheinvalidation/types.pb.h"
#include "google/cacheinvalidation/deps/gmock.h"
#include "google/cacheinvalidation/deps/string_util.h"
#include "google/cacheinvalidation/impl/basic-system-resources.h"
#include "google/cacheinvalidation/impl/constants.h"
#include "google/cacheinvalidation/impl/log-macro.h"
#include "google/cacheinvalidation/impl/protocol-handler.h"
#include "google/cacheinvalidation/impl/statistics.h"
#include "google/cacheinvalidation/test/deterministic-scheduler.h"

namespace invalidation {

using ::ipc::invalidation::ObjectSource_Type_TEST;
using ::ipc::invalidation::ClientHeader;
using ::ipc::invalidation::ClientVersion;
using ::ipc::invalidation::InvalidationP;
using ::ipc::invalidation::ObjectIdP;
using ::ipc::invalidation::ProtocolVersion;
using ::ipc::invalidation::RegistrationP_OpType_REGISTER;
using ::ipc::invalidation::RegistrationP_OpType_UNREGISTER;
using ::ipc::invalidation::RegistrationStatus;
using ::ipc::invalidation::RegistrationSummary;
using ::ipc::invalidation::ServerHeader;
using ::ipc::invalidation::ServerToClientMessage;
using ::ipc::invalidation::StatusP_Code_SUCCESS;
using ::ipc::invalidation::Version;
using ::google::protobuf::MessageLite;
using ::testing::_;
using ::testing::EqualsProto;
using ::testing::Matcher;
using ::testing::Property;
using ::testing::SaveArg;
using ::testing::StrictMock;

/* A random class whose RandDouble method always returns a given constant. */
class FakeRandom : public Random {
 public:
  // Constructs a fake random generator that always returns |return_value|,
  // which must be in the range [0, 1).
  explicit FakeRandom(double return_value)
      : Random(0), return_value_(return_value) {
    CHECK_GE(return_value_, 0.0);
    CHECK_LT(return_value_, 1.0);
  }

  virtual ~FakeRandom() {}

  virtual double RandDouble() {
    return return_value_;
  }

 private:
  double return_value_;
};

// A mock of the Scheduler interface.
class MockScheduler : public Scheduler {
 public:
  MOCK_METHOD2(Schedule, void(TimeDelta, Closure*));  // NOLINT
  MOCK_CONST_METHOD0(IsRunningOnThread, bool());
  MOCK_CONST_METHOD0(GetCurrentTime, Time());
  MOCK_METHOD1(SetSystemResources, void(SystemResources*));  // NOLINT
};

// A mock of the Network interface.
class MockNetwork : public NetworkChannel {
 public:
  MOCK_METHOD1(SendMessage, void(const string&));  // NOLINT
  MOCK_METHOD1(SetMessageReceiver, void(MessageCallback*));  // NOLINT
  MOCK_METHOD1(AddNetworkStatusReceiver, void(NetworkStatusCallback*));  // NOLINT
  MOCK_METHOD1(SetSystemResources, void(SystemResources*));  // NOLINT
};

// A mock of the Storage interface.
class MockStorage : public Storage {
 public:
  MOCK_METHOD3(WriteKey, void(const string&, const string&, WriteKeyCallback*));  // NOLINT
  MOCK_METHOD2(ReadKey, void(const string&, ReadKeyCallback*));  // NOLINT
  MOCK_METHOD2(DeleteKey, void(const string&, DeleteKeyCallback*));  // NOLINT
  MOCK_METHOD1(ReadAllKeys, void(ReadAllKeysCallback*));  // NOLINT
  MOCK_METHOD1(SetSystemResources, void(SystemResources*));  // NOLINT
};

// A mock of the InvalidationListener interface.
class MockInvalidationListener : public InvalidationListener {
 public:
  MOCK_METHOD1(Ready, void(InvalidationClient*));  // NOLINT

  MOCK_METHOD3(Invalidate,
      void(InvalidationClient *, const Invalidation&,  // NOLINT
           const AckHandle&));  // NOLINT

  MOCK_METHOD3(InvalidateUnknownVersion,
               void(InvalidationClient *, const ObjectId&,
                    const AckHandle&));  // NOLINT

  MOCK_METHOD2(InvalidateAll,
      void(InvalidationClient *, const AckHandle&));  // NOLINT

  MOCK_METHOD3(InformRegistrationStatus,
      void(InvalidationClient*, const ObjectId&, RegistrationState));  // NOLINT

  MOCK_METHOD4(InformRegistrationFailure,
      void(InvalidationClient*, const ObjectId&, bool, const string&));

  MOCK_METHOD3(ReissueRegistrations,
      void(InvalidationClient*, const string&, int));

  MOCK_METHOD2(InformError,
      void(InvalidationClient*, const ErrorInfo&));
};

// A base class for unit tests to share common methods and helper routines.
class UnitTestBase : public testing::Test {
 public:
  // Default smearing to be done to randomize delays. Zero to get
  // precise delays.
  static const int kDefaultSmearPercent = 0;

  // The token or nonce used by default for a client in client to server or
  // server to client messages.
  static const char *kClientToken;

  // When "waiting" at the end of a test to make sure nothing happens, how long
  // to wait.
  static TimeDelta EndOfTestWaitTime();

  // When "waiting" at the end of a test to make sure nothing happens, how long
  // to wait. This delay will not only allow to run the processing on the
  // workqueue but will also give some 'extra' time to the code to do other
  // (incorrect) activities if there is a bug, e.g., make an uneccessary
  // listener call, etc.
  static TimeDelta MessageHandlingDelay();

  // Populates |object_ids| with |count| object ids in the TEST id space, each
  // named oid<n>.
  static void InitTestObjectIds(int count, vector<ObjectIdP>* object_ids);

  // Converts object id protos in |oid_protos| to ObjecIds in |oids|.
  static void ConvertFromObjectIdProtos(const vector<ObjectIdP>& oid_protos,
      vector<ObjectId> *oids);

  // Converts invalidation protos in |inv_protos| to Invalidations in |invs|.
  static void ConvertFromInvalidationProtos(
      const vector<InvalidationP>& inv_protos, vector<Invalidation> *invs);

  // For each object id in |object_ids|, adds an invalidation to |invalidations|
  // for that object at an arbitrary version.
  static void MakeInvalidationsFromObjectIds(
      const vector<ObjectIdP>& object_ids,
      vector<InvalidationP>* invalidations);

  // For each object in |object_ids|, makes a SUCCESSful registration status for
  // that object, alternating between REGISTER and UNREGISTER.  The precise
  // contents of these messages are unimportant to the protocol handler; we just
  // need them to pass the message validator.
  static void MakeRegistrationStatusesFromObjectIds(
      const vector<ObjectIdP>& object_ids, bool is_reg, bool is_success,
      vector<RegistrationStatus>* registration_statuses);

  // Returns the maximum smeared delay possible for |delay_ms| given the
  // |Smearer|'s default smearing.
  static TimeDelta GetMaxDelay(int delay_ms);

  // Returns the maximum batching delay that a message will incur in the
  // protocol handler.
  static TimeDelta GetMaxBatchingDelay(const ProtocolHandlerConfigP& config);

  // Initializes |summary| with a registration summary for 0 objects.
  static void InitZeroRegistrationSummary(RegistrationSummary* summary);

  // Creates a matcher for the parts of the header that the test can predict.
  static Matcher<ClientHeader> ClientHeaderMatches(const ClientHeader* header);

  // Initialize |reg_message| to contain registrations for all objects in |oids|
  // with |is_reg| indicating whether the operation is register or unregister.
  static void InitRegistrationMessage(const vector<ObjectIdP>& oids,
      bool is_reg, RegistrationMessage *reg_message);

  // Initializes |inv_message| to contain the invalidations |invs|.
  static void InitInvalidationMessage(const vector<InvalidationP>& invs,
      InvalidationMessage *inv_message);

  // Initializes |error_message| to contain given the |error_code| and error
  // |description|.
  static void InitErrorMessage(ErrorMessage::Code error_code,
      const string& description, ErrorMessage* error_message);

  // Performs setup for protocol handler unit tests, e.g. creating resource
  // components and setting up common expectations for certain mock objects.
  virtual void SetUp();

  // Tears down the test, e.g., drains any schedulers if needed.
  virtual void TearDown();

  // Initializes the basic system resources, using mocks for various components.
  void InitSystemResources();

  // Sets up some common expectations for the system resources.
  void InitCommonExpectations();

  // Initializes a server header with the given token (registration summary is
  // picked up the internal state |reg_summary|).
  void InitServerHeader(const string& token, ServerHeader* header);

  // Gives a ServerToClientMessage |message| to the protocol handler and
  // passes time in the internal scheduler by |delay| waiting for processing to
  // be done.
  void ProcessIncomingMessage(const ServerToClientMessage& message,
      TimeDelta delay);

  // Returns true iff the messages are equal (with lists interpreted as sets).
  bool CompareMessages(
      const ::google::protobuf::MessageLite& expected,
      const ::google::protobuf::MessageLite& actual);

  // Checks that |vec1| and |vec2| contain the same number of elements
  // and each element in |vec1| is present in |vec2| and vice-versa (Uses the
  // == operator for comparing). Returns true iff it is the case. Note that this
  // method will return true for (aab, abb)
  template <class T>
  static bool CompareVectorsAsSets(const vector<T>& vec1,
      const vector<T>& vec2) {
    if (vec1.size() != vec2.size()) {
      return false;
    }
    for (size_t i = 0; i < vec1.size(); i++) {
      bool found = false;
      for (size_t j = 0; (j < vec2.size()) && !found; j++) {
        found = found || (vec1[i] == vec2[j]);
      }
      if (!found) {
        return false;
      }
    }
    return true;
  }

  //
  // Internal state
  //

  // The time at which the test started.  Initialized to an arbitrary value to
  // ensure that we don't depend on it starting at 0.
  Time start_time;

  // Components of BasicSystemResources.  It takes ownership of all of these,
  // and its destructor deletes them, so we need to create fresh ones for each
  // test.

  // Use a deterministic scheduler for the protocol handler's internals, since
  // we want precise control over when batching intervals expire.
  DeterministicScheduler* internal_scheduler;

  // DeterministicScheduler or MockScheduler depending on the test.
  MockScheduler* listener_scheduler;

  // Use a mock network to let us trap the protocol handler's message receiver
  // and its attempts to send messages.
  MockNetwork* network;

  // A logger.
  Logger* logger;

  // Storage shouldn't be used by the protocol handler, so use a strict mock to
  // catch any accidental calls.
  MockStorage* storage;

  // System resources (owned by the test).
  scoped_ptr<BasicSystemResources> resources;

  // Statistics object for counting occurrences of different types of events.
  scoped_ptr<Statistics> statistics;

  // Message callback installed by the protocol handler.  Captured by the mock
  // network.
  MessageCallback* message_callback;

  // Registration summary to be placed in messages from the client to the server
  // and vice-versa.
  scoped_ptr<RegistrationSummary> reg_summary;
};

// Creates an action InvokeAndDeleteClosure<k> that invokes the kth closure and
// deletes it after the Run method has been called.
ACTION_TEMPLATE(
    InvokeAndDeleteClosure,
    HAS_1_TEMPLATE_PARAMS(int, k),
    AND_0_VALUE_PARAMS()) {
  std::tr1::get<k>(args)->Run();
  delete std::tr1::get<k>(args);
}

}  // namespace invalidation

#endif  // GOOGLE_CACHEINVALIDATION_TEST_TEST_UTILS_H_
