/*
 * Copyright 2016 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.
 */

// Author: yeputons@google.com (Egor Suvorov)

// Unit-test the redis interface.

#include "pagespeed/system/redis_cache.h"

#include <cstdlib>

#include "apr_network_io.h"  // NOLINT
#include "base/logging.h"
#include "pagespeed/kernel/base/google_message_handler.h"
#include "pagespeed/kernel/base/gmock.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/null_mutex.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/posix_timer.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/cache/cache_test_base.h"
#include "pagespeed/kernel/thread/worker_test_base.h"
#include "pagespeed/kernel/util/platform.h"
#include "pagespeed/kernel/util/simple_stats.h"
#include "pagespeed/system/tcp_connection_for_testing.h"
#include "pagespeed/system/tcp_server_thread_for_testing.h"

namespace net_instaweb {

namespace {
  static const int kReconnectionDelayMs = 10;
  static const int kTimeoutUs = 100 * Timer::kMsUs;
  static const int kDatabaseIndex[] = {0, 1};
  static const char kSomeKey[] = "SomeKey";
  static const char kSomeValue[] = "SomeValue";
}

using testing::HasSubstr;

// TODO(yeputons): refactor this class with AprMemCacheTest, see details in
// apr_mem_cache_test.cc
class RedisCacheTest : public CacheTestBase {
 protected:
  RedisCacheTest()
      : thread_system_(Platform::CreateThreadSystem()),
        statistics_(thread_system_.get()),
        timer_(new NullMutex, 0),
        redis_port_env_(0) {
    RedisCache::InitStats(&statistics_);
  }

  bool PrepareRedisOrSkip() {
    const char* portString = getenv("REDIS_PORT");
    int port;
    if (portString == nullptr || !StringToInt(portString, &port)) {
      LOG(ERROR) << "RedisCache tests are skipped because env var "
                 << "$REDIS_PORT is not set to an integer. Set that "
                 << "to the port number where redis is running to "
                 << "enable the tests. See install/run_program_with_redis.sh";
      return false;
    }

    redis_port_env_ = port;

    {
      TcpConnectionForTesting conn;
      CHECK(conn.Connect("localhost", port))
          << "Cannot connect to Redis server";
      conn.Send("FLUSHALL\r\n");
      CHECK_EQ("+OK\r\n", conn.ReadLineCrLf());
    }
    return true;
  }

  void InitRedisWithCustomDatabaseIndex(const int database_index) {
    cache_.emplace_back(new RedisCache("localhost", redis_port_env_,
                            thread_system_.get(), &handler_, &timer_,
                            kReconnectionDelayMs, kTimeoutUs, &statistics_,
                            database_index));
    cache_.back()->StartUp();
  }

  void InitRedisWithCustomServer() {
    cache_.emplace_back(new RedisCache("localhost", custom_server_port_,
                                thread_system_.get(), &handler_, &timer_,
                                kReconnectionDelayMs, kTimeoutUs,
                                &statistics_, kDatabaseIndex[0]));
  }

  void InitRedisWithUnreachableServer() {
    // Try to connect to some definitely unreachable host.
    // 192.0.2.0/24 is reserved for documentation purposes in RFC5737 and no
    // machine should ever be routable in that subnet.
    cache_.emplace_back(new RedisCache("192.0.2.1", 12345, thread_system_.get(),
                                &handler_, &timer_, kReconnectionDelayMs,
                                kTimeoutUs, &statistics_, kDatabaseIndex[0]));
  }

  static void SetUpTestCase() {
    apr_initialize();
    TcpServerThreadForTesting::PickListenPortOnce(&custom_server_port_);
    CHECK_NE(custom_server_port_, 0);
  }

  template<class ServerThread>
  bool StartCustomServer() {
    WaitForCustomServerShutdown();
    custom_server_.reset(
        new ServerThread(custom_server_port_, thread_system_.get()));
    if (!custom_server_->Start()) {
      return false;
    }
    // Wait while server starts and check its port
    return custom_server_->GetListeningPort() == custom_server_port_;
  }

  void WaitForCustomServerShutdown() {
    custom_server_.reset();
  }

  static void TearDownTestCase() {
    apr_terminate();
  }

  CacheInterface* Cache() override { return cache_[0].get(); }

  ThreadSynchronizer* GetThreadSynchronizer() {
    return cache_[0]->GetThreadSynchronizerForTesting();
  }

  std::vector<std::unique_ptr<RedisCache>> cache_;
  scoped_ptr<ThreadSystem> thread_system_;
  SimpleStats statistics_;
  MockTimer timer_;
  GoogleMessageHandler handler_;

  scoped_ptr<TcpServerThreadForTesting> custom_server_;
  static apr_port_t custom_server_port_;
  int redis_port_env_;
};

apr_port_t RedisCacheTest::custom_server_port_ = 0;

// Simple flow of putting in an item, getting it, deleting it.
TEST_F(RedisCacheTest, PutGetDelete) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  CheckPut("Name", "Value");
  CheckGet("Name", "Value");
  CheckNotFound("Another Name");

  CheckPut("Name", "NewValue");
  CheckGet("Name", "NewValue");

  CheckDelete("Name");
  CheckNotFound("Name");

  // We're not running against redis cluster, so we don't expect to ever be
  // redirected, and we should never ask for cluster slots.
  EXPECT_EQ(0, cache_[0]->Redirections());
  EXPECT_EQ(0, cache_[0]->ClusterSlotsFetches());
}

// Make sure curly braces in keys aren't treated specially.
TEST_F(RedisCacheTest, CurlyBraces) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  CheckPut("{1}NameA", "Value1A");
  CheckPut("{2}NameB", "Value2B");
  CheckPut("{2}NameC", "Value2C");

  CheckGet("{1}NameA", "Value1A");
  CheckGet("{2}NameB", "Value2B");
  CheckGet("{2}NameC", "Value2C");
}

// And spaces
TEST_F(RedisCacheTest, Spaces) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  CheckPut("1 NameA", "Value1A");
  CheckPut("2 NameB", "Value2B");
  CheckPut("2 NameC", "Value2C");

  CheckGet("1 NameA", "Value1A");
  CheckGet("2 NameB", "Value2B");
  CheckGet("2 NameC", "Value2C");
}

TEST_F(RedisCacheTest, MultiGet) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);
  TestMultiGet();  // Test from CacheTestBase is just fine.
}

TEST_F(RedisCacheTest, BasicInvalid) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  // Check that we honor callback veto on validity.
  CheckPut("nameA", "valueA");
  CheckPut("nameB", "valueB");
  CheckGet("nameA", "valueA");
  CheckGet("nameB", "valueB");
  set_invalid_value("valueA");
  CheckNotFound("nameA");
  CheckGet("nameB", "valueB");
}

TEST_F(RedisCacheTest, GetStatus) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  GoogleString status;
  cache_[0]->GetStatus(&status);

  // Check that some reasonable info is present.
  EXPECT_THAT(status, HasSubstr(cache_[0]->ServerDescription()));
  EXPECT_THAT(status, HasSubstr("redis_version:"));
  EXPECT_THAT(status, HasSubstr("connected_clients:"));
  EXPECT_THAT(status, HasSubstr("tcp_port:"));
  EXPECT_THAT(status, HasSubstr("used_memory:"));
}

// Two following tests are identical and ensure that no keys are leaked between
// tests through shared running Redis server.
TEST_F(RedisCacheTest, TestsAreIsolated1) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  CheckNotFound(kSomeKey);
  CheckPut(kSomeKey, kSomeValue);
}

TEST_F(RedisCacheTest, TestsAreIsolated2) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  CheckNotFound(kSomeKey);
  CheckPut(kSomeKey, kSomeValue);
}

// Test to check multiple redis database(with different index)
TEST_F(RedisCacheTest, TestMultipleDatabases) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(kDatabaseIndex[0]);
  InitRedisWithCustomDatabaseIndex(kDatabaseIndex[1]);

  CheckPut("key1", "value1");
  // adding same key to second database
  CheckPut(cache_[1].get(), "key1", "value2");

  // checking key entries from databases
  CheckGet("key1", "value1");
  CheckGet(cache_[1].get(), "key1", "value2");

  CheckDelete("key1");

  // checking key deleted from first database
  CheckNotFound("key1");

  // check same key present in second database
  CheckGet(cache_[1].get(), "key1", "value2");
}

class RedisGetRespondingServerThread : public TcpServerThreadForTesting {
 public:
  RedisGetRespondingServerThread(apr_port_t listen_port,
                                 ThreadSystem* thread_system)
      : TcpServerThreadForTesting(listen_port, "redis_get_answering_server",
                                  thread_system) {}

  virtual ~RedisGetRespondingServerThread() { ShutDown(); }

 private:
  void HandleClientConnection(apr_socket_t* sock) override {
    // See http://redis.io/topics/protocol for details. Request is an array of
    // two bulk strings, answer for GET is a single bulk string.

    // during redis cache startup, Select database command is fired
    // being the first command, it is captured by the mock redis server
    static const char kSelectRequest[] =
        "*2\r\n"
        "$6\r\nSELECT\r\n"
        "$1\r\n0\r\n";
    static const char kSelectAnswer[] = "+OK\r\n";
    apr_size_t answer_size_select  = STATIC_STRLEN(kSelectAnswer);

    char requestBuf[STATIC_STRLEN(kSelectRequest) + 1];
    apr_size_t recvSize = sizeof(requestBuf) - 1;

    apr_socket_recv(sock, requestBuf, &recvSize);
    EXPECT_EQ(STATIC_STRLEN(kSelectRequest), recvSize);
    requestBuf[recvSize] = 0;
    EXPECT_STREQ(kSelectRequest, requestBuf);

    apr_socket_send(sock, kSelectAnswer, &answer_size_select);

    static const char kRequest[] =
        "*2\r\n"
        "$3\r\nGET\r\n"
        "$7\r\nSomeKey\r\n";
    static const char kAnswer[] = "$9\r\nSomeValue\r\n";
    apr_size_t answer_size  = STATIC_STRLEN(kAnswer);

    char buf[STATIC_STRLEN(kRequest) + 1];
    apr_size_t size = sizeof(buf) - 1;

    apr_socket_recv(sock, buf, &size);
    EXPECT_EQ(STATIC_STRLEN(kRequest), size);
    buf[size] = 0;
    EXPECT_STREQ(kRequest, buf);

    apr_socket_send(sock, kAnswer, &answer_size);
    apr_socket_close(sock);
  }
};

TEST_F(RedisCacheTest, ReconnectsInstantly) {
  InitRedisWithCustomServer();
  ASSERT_TRUE(StartCustomServer<RedisGetRespondingServerThread>());
  cache_[0]->StartUp();

  CheckGet(kSomeKey, kSomeValue);
  // Server closes connection after processing one request, but cache does not
  // know about that yet.
  WaitForCustomServerShutdown();
  EXPECT_TRUE(Cache()->IsHealthy());

  // Client should not reconnect as it learns about disconnection only when it
  // tries to run the command.
  ASSERT_TRUE(StartCustomServer<RedisGetRespondingServerThread>());
  CheckNotFound(kSomeKey);

  // First reconnection attempt should happen right away.
  EXPECT_TRUE(Cache()->IsHealthy());  // Allow reconnection.
  CheckGet(kSomeKey, kSomeValue);
}

TEST_F(RedisCacheTest, ReconnectsUntilSuccessWithTimeout) {
  InitRedisWithCustomServer();
  ASSERT_TRUE(StartCustomServer<RedisGetRespondingServerThread>());
  cache_[0]->StartUp();

  CheckGet(kSomeKey, kSomeValue);
  // Server closes connection after processing one request, but cache does not
  // know about that yet.
  WaitForCustomServerShutdown();
  EXPECT_TRUE(Cache()->IsHealthy());

  // Let client know that we're disconnected by trying to read.
  CheckNotFound(kSomeKey);

  // Try to reconnect right away after failure.
  EXPECT_TRUE(Cache()->IsHealthy());  // Reconnection is allowed...
  CheckNotFound(kSomeKey);  // ...but it fails.

  // Second attempt, should not reconnect before timeout.
  ASSERT_TRUE(StartCustomServer<RedisGetRespondingServerThread>());
  timer_.AdvanceMs(kReconnectionDelayMs - 1);
  EXPECT_FALSE(Cache()->IsHealthy());  // Reconnection is not allowed.
  CheckNotFound(kSomeKey);

  // Should reconnect after timeout passes.
  timer_.AdvanceMs(1);
  EXPECT_TRUE(Cache()->IsHealthy());  // Reconnection is allowed.
  CheckGet(kSomeKey, kSomeValue);
}

TEST_F(RedisCacheTest, ReconnectsIfStartUpFailed) {
  InitRedisWithCustomServer();
  cache_[0]->StartUp();

  // Client already knows that connection failed.
  EXPECT_FALSE(Cache()->IsHealthy());
  CheckNotFound(kSomeKey);

  // Should not reconnect before timeout.
  ASSERT_TRUE(StartCustomServer<RedisGetRespondingServerThread>());
  timer_.AdvanceMs(kReconnectionDelayMs - 1);
  EXPECT_FALSE(Cache()->IsHealthy());  // Reconnection is not allowed.
  CheckNotFound(kSomeKey);

  // Should reconnect after timeout passes.
  timer_.AdvanceMs(1);
  EXPECT_TRUE(Cache()->IsHealthy());  // Reconnection is allowed.
  CheckGet(kSomeKey, kSomeValue);
}

TEST_F(RedisCacheTest, DoesNotReconnectAfterShutdown) {
  if (!PrepareRedisOrSkip()) {
    return;
  }
  InitRedisWithCustomDatabaseIndex(0);

  CheckPut(kSomeKey, kSomeValue);
  CheckGet(kSomeKey, kSomeValue);
  EXPECT_TRUE(Cache()->IsHealthy());

  Cache()->ShutDown();
  timer_.AdvanceMs(kReconnectionDelayMs);

  EXPECT_FALSE(Cache()->IsHealthy());  // Reconnection is not allowed.
  CheckNotFound(kSomeKey);
}

// This server always waits until connection is received to avoid race
// condition between server destruction and accepting connection (like in
// ShutDownDuringConnection). Other servers do not do that because tests
// actually rely on their answers to client.
class RedisNotRespondingServerThread : public TcpServerThreadForTesting {
 public:
  RedisNotRespondingServerThread(apr_port_t listen_port,
                                 ThreadSystem* thread_system)
      : TcpServerThreadForTesting(listen_port, "redis_not_responding_server",
                                  thread_system),
        connection_received_(thread_system) {}

  ~RedisNotRespondingServerThread() {
    connection_received_.Wait();
    ShutDown();
  }

 protected:
  void HandleClientConnection(apr_socket_t* sock) override {
    // Do nothing, socket will be closed in destructor
    connection_received_.Notify();
  }

 private:
  WorkerTestBase::SyncPoint connection_received_;
};

// This server always waits until connection is received to avoid race
// condition between server destruction and accepting connection (like in
// ShutDownDuringConnection). Other servers do not do that because tests
// actually rely on their answers to client.
class RedisNotRespondingOperationTimeoutServerThread :
    public TcpServerThreadForTesting {
 public:
  RedisNotRespondingOperationTimeoutServerThread(apr_port_t listen_port,
                                 ThreadSystem* thread_system)
      : TcpServerThreadForTesting(listen_port, "redis_not_responding_server",
                                  thread_system),
        connection_received_(thread_system) {}

  ~RedisNotRespondingOperationTimeoutServerThread() {
    connection_received_.Wait();
    ShutDown();
  }

 protected:
  void HandleClientConnection(apr_socket_t* sock) override {
    // Do nothing, socket will be closed in destructor

    // during redis cache startup, Select database command is fired
    // being the first command, it is captured by the mock redis server
    static const char kSelectRequest[] =
        "*2\r\n"
        "$6\r\nSELECT\r\n"
        "$1\r\n0\r\n";
    static const char kSelectAnswer[] = "+OK\r\n";
    apr_size_t answer_size_select  = STATIC_STRLEN(kSelectAnswer);

    char requestBuf[STATIC_STRLEN(kSelectRequest) + 1];
    apr_size_t recvSize = sizeof(requestBuf) - 1;

    apr_socket_recv(sock, requestBuf, &recvSize);
    EXPECT_EQ(STATIC_STRLEN(kSelectRequest), recvSize);
    requestBuf[recvSize] = 0;
    EXPECT_STREQ(kSelectRequest, requestBuf);

    apr_socket_send(sock, kSelectAnswer, &answer_size_select);
    connection_received_.Notify();
  }

 private:
  WorkerTestBase::SyncPoint connection_received_;
};

// These constants are for timeout tests.
namespace {
// Experiments showed that I/O functions on Linux may sometimes time out
// slightly earlier than configured. It does not look like precision or
// rounding error; waking up recv() 2ms earlier has probability around 0.7%.
// That is partially leveraged by the fact that we have a bunch of code around
// I/O in RedisCache, but probability is still non-zero (0.05%). Probability
// of 1ms gap in RedisCacheOperationTimeouTest was around 5% at the time it was
// written. So we put here 5ms to be safe.
const int kTimedOutOperationMinTimeUs = kTimeoutUs - 5 * Timer::kMsUs;

// Upper gap is bigger because taking more time than time out is expected.
// Unfortunately, it still gives 0.05%-0.1% of spurious failures and 'real'
// overhead in these outliers can be bigger than 100ms.
const int kTimedOutOperationMaxTimeUs = kTimeoutUs + 50 * Timer::kMsUs;

// We want timeout to be significantly greater than measuring gap.
static_assert(kTimeoutUs >= 60 * Timer::kMsUs,
              "kTimeoutUs is smaller than measuring gap");
}  // namespace

TEST_F(RedisCacheTest, ConnectionTimeout) {
  InitRedisWithUnreachableServer();
  PosixTimer timer;
  int64 started_at_us = timer.NowUs();
  cache_[0]->StartUp();  // Should try to connect as well.
  int64 waited_for_us = timer.NowUs() - started_at_us;
  EXPECT_FALSE(cache_[0]->IsHealthy());
  EXPECT_GE(waited_for_us, kTimedOutOperationMinTimeUs);
  EXPECT_LE(waited_for_us, kTimedOutOperationMaxTimeUs);
}

class GetRequestThread : public ThreadSystem::Thread {
 public:
  GetRequestThread(CacheInterface* cache, ThreadSystem* system)
      : ThreadSystem::Thread(system, "get_request_thread",
                             ThreadSystem::kJoinable),
        cache_(cache),
        check_called_(false) {}

  void Run() override {
    cache_->Get(kSomeKey, &callback_);
  }

  void CheckLookupResult(CacheInterface::KeyState expected_state) {
    check_called_ = true;
    Join();
    EXPECT_TRUE(callback_.called());
    EXPECT_EQ(callback_.state(), expected_state);
    if (expected_state == CacheInterface::kAvailable) {
      EXPECT_STREQ(callback_.value().Value(), kSomeValue);
    }
  }

  ~GetRequestThread() override {
    EXPECT_TRUE(check_called_)
        << "CheckLookupResult() was not called on GetRequestThread";
  }

 private:
  CacheInterface* cache_;
  CacheInterface::SynchronousCallback callback_;
  bool check_called_;
};

TEST_F(RedisCacheTest, IsHealthyDoesNotBlock) {
  InitRedisWithCustomServer();
  StartCustomServer<RedisGetRespondingServerThread>();
  cache_[0]->StartUp();

  // enabling thread synchronizer after cache start up because
  // cache startup fires redis command to select redis database
  // and this execution interferes with the test thread synchronization
  GetThreadSynchronizer()->EnableForPrefix("RedisCommand.After");

  GetRequestThread thread(Cache(), thread_system_.get());
  ASSERT_TRUE(thread.Start());
  GetThreadSynchronizer()->Wait("RedisCommand.After.Signal");

  // Check that IsHealthy() returns even when operation is in progress.
  Cache()->IsHealthy();

  GetThreadSynchronizer()->Signal("RedisCommand.After.Wait");
  thread.CheckLookupResult(CacheInterface::kAvailable);
}

TEST_F(RedisCacheTest, ConnectionFastFail) {
  InitRedisWithCustomServer();
  StartCustomServer<RedisGetRespondingServerThread>();
  GetThreadSynchronizer()->EnableForPrefix("RedisConnect.After");
  cache_[0]->StartUp(/* connect_now */ false);

  EXPECT_TRUE(Cache()->IsHealthy());
  GetRequestThread thread(Cache(), thread_system_.get());
  ASSERT_TRUE(thread.Start());
  GetThreadSynchronizer()->Wait("RedisConnect.After.Signal");

  EXPECT_FALSE(Cache()->IsHealthy());  // Connection is in progress.

  // Check that Get() returns immediately. Two times becase first call may
  // theoretically override cache's state (real bug).
  for (int iter = 1; iter <= 2; iter++) {
    CheckNotFound(kSomeKey);
  }

  GetThreadSynchronizer()->Signal("RedisConnect.After.Wait");
  thread.CheckLookupResult(CacheInterface::kAvailable);

  // Now that thread is terminated, connection is established, cache should be
  // healthy again.
  EXPECT_TRUE(Cache()->IsHealthy());
}

TEST_F(RedisCacheTest, ShutDownDuringConnection) {
  InitRedisWithCustomServer();
  StartCustomServer<RedisNotRespondingServerThread>();
  GetThreadSynchronizer()->EnableForPrefix("RedisConnect.After");
  cache_[0]->StartUp(/* connect_now */ false);

  EXPECT_TRUE(Cache()->IsHealthy());
  GetRequestThread thread(Cache(), thread_system_.get());
  ASSERT_TRUE(thread.Start());
  GetThreadSynchronizer()->Wait("RedisConnect.After.Signal");

  Cache()->ShutDown();

  GetThreadSynchronizer()->Signal("RedisConnect.After.Wait");
  thread.CheckLookupResult(CacheInterface::kNotFound);

  // Cache potentially may want to reconnect, so we advance timer to ensure that
  // it does not want to.
  timer_.AdvanceMs(kReconnectionDelayMs);
  EXPECT_FALSE(Cache()->IsHealthy());
}

// All RedisCacheOperationTimeoutTests start with a cache connected to a server
// which accepts single connection and does not answer until test is finished.
// The test calls a single command. If the timeout handling is correct, it times
// out and the test terminates correctly. If the timeout handling is not
// correct, the test hangs.
class RedisCacheOperationTimeoutTest : public RedisCacheTest {
 protected:
  void SetUp() {
    InitRedisWithCustomServer();
    CHECK(StartCustomServer<RedisNotRespondingOperationTimeoutServerThread>());
    cache_[0]->StartUp();
    started_at_us_ = timer_.NowUs();
  }

  void TearDown() {
    int64 waited_for_us = timer_.NowUs() - started_at_us_;
    EXPECT_GE(waited_for_us, kTimedOutOperationMinTimeUs);
    EXPECT_LE(waited_for_us, kTimedOutOperationMaxTimeUs);
  }

 private:
  PosixTimer timer_;
  int64 started_at_us_;
};

TEST_F(RedisCacheOperationTimeoutTest, Get) {
  CheckNotFound("Key");
}

// TODO(yeputons): test MultiGet when it's a single command, not sequenced GET()

TEST_F(RedisCacheOperationTimeoutTest, Put) {
  CheckPut("Key", "Value");
}

TEST_F(RedisCacheOperationTimeoutTest, Delete) {
  CheckDelete("Key");
}

}  // namespace net_instaweb
