| // 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 and a | |
| // mock storage layer. | |
| #ifndef GOOGLE_CACHEINVALIDATION_V2_TEST_TEST_UTILS_H_ | |
| #define GOOGLE_CACHEINVALIDATION_V2_TEST_TEST_UTILS_H_ | |
| #include "google/cacheinvalidation/v2/client_protocol.pb.h" | |
| #include "google/cacheinvalidation/v2/gmock.h" | |
| #include "google/cacheinvalidation/v2/string_util.h" | |
| #include "google/cacheinvalidation/v2/types.pb.h" | |
| #include "google/cacheinvalidation/v2/basic-system-resources.h" | |
| #include "google/cacheinvalidation/v2/constants.h" | |
| #include "google/cacheinvalidation/v2/log-macro.h" | |
| #include "google/cacheinvalidation/v2/protocol-handler.h" | |
| #include "google/cacheinvalidation/v2/statistics.h" | |
| #include "google/cacheinvalidation/v2/test/deterministic-scheduler.h" | |
| #include "google/cacheinvalidation/v2/types.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 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 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. */ | |
| static const int kDefaultSmearPercent = 20; | |
| // 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 {@code 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 MessageLite& expected, const 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; | |
| }; | |
| } // namespace invalidation | |
| #endif // GOOGLE_CACHEINVALIDATION_V2_TEST_TEST_UTILS_H_ |