// Test simple data tuples drain
TEST(TupleCache, test_simple_data_drain) {
  sp_int32 data_tuples_count = 23354;
  EventLoopImpl ss;
  sp_uint32 drain_threshold = 1024 * 1024;
  heron::stmgr::TupleCache* g = new heron::stmgr::TupleCache(&ss, drain_threshold);
  std::map<sp_int32, sp_int32> data_tuples;
  data_tuples[1] = data_tuples_count;
  std::map<sp_int32, sp_int32> ack_tuples;
  std::map<sp_int32, sp_int32> fail_tuples;
  Drainer* drainer = new Drainer(data_tuples, ack_tuples, fail_tuples);
  g->RegisterDrainer(&Drainer::Drain, drainer);

  heron::proto::api::StreamId dummy;
  dummy.set_id("stream");
  dummy.set_component_name("comp");
  for (sp_int32 i = 0; i < data_tuples_count; ++i) {
    heron::proto::system::HeronDataTuple tuple;
    tuple.set_key(RandUtils::lrand());
    g->add_data_tuple(1, dummy, tuple);
  }

  // 300 milliseconds second
  auto cb = [&ss](EventLoopImpl::Status status) { DoneHandler(&ss, status); };
  ss.registerTimer(std::move(cb), false, 300000);

  ss.loop();

  EXPECT_EQ(drainer->Verify(), true);
  delete drainer;
  delete g;
}
// Test different stream mix
TEST(TupleCache, test_different_stream_mix) {
  sp_int32 data_tuples_count = 23354;  // make sure this is even
  sp_int32 ack_tuples_count = 3544;    // make sure this is even
  sp_int32 fail_tuples_count = 6564;   // make sure this is even
  EventLoopImpl ss;
  sp_uint32 drain_threshold = 1024 * 1024;
  heron::stmgr::TupleCache* g = new heron::stmgr::TupleCache(&ss, drain_threshold);
  std::map<sp_int32, sp_int32> data_tuples;
  data_tuples[1] = data_tuples_count / 2;
  data_tuples[2] = data_tuples_count / 2;
  std::map<sp_int32, sp_int32> ack_tuples;
  ack_tuples[1] = ack_tuples_count / 2;
  ack_tuples[2] = ack_tuples_count / 2;
  std::map<sp_int32, sp_int32> fail_tuples;
  fail_tuples[1] = fail_tuples_count / 2;
  fail_tuples[2] = fail_tuples_count / 2;
  Drainer* drainer = new Drainer(data_tuples, ack_tuples, fail_tuples);
  g->RegisterDrainer(&Drainer::Drain, drainer);

  heron::proto::api::StreamId stream1;
  stream1.set_id("stream1");
  stream1.set_component_name("comp1");
  heron::proto::api::StreamId stream2;
  stream2.set_id("stream2");
  stream2.set_component_name("comp2");
  sp_int32 max_count = std::max(std::max(data_tuples_count, ack_tuples_count), fail_tuples_count);
  for (sp_int32 i = 0; i < max_count; ++i) {
    if (i < data_tuples_count) {
      heron::proto::system::HeronDataTuple tuple;
      tuple.set_key(RandUtils::lrand());
      if (i % 2 == 0) {
        g->add_data_tuple(1, stream1, tuple);
      } else {
        g->add_data_tuple(2, stream2, tuple);
      }
    }
    if (i < ack_tuples_count) {
      heron::proto::system::AckTuple tuple;
      tuple.set_ackedtuple(RandUtils::lrand());
      if (i % 2 == 0) {
        g->add_ack_tuple(1, tuple);
      } else {
        g->add_ack_tuple(2, tuple);
      }
    }
    if (i < fail_tuples_count) {
      heron::proto::system::AckTuple tuple;
      tuple.set_ackedtuple(RandUtils::lrand());
      if (i % 2 == 0) {
        g->add_fail_tuple(1, tuple);
      } else {
        g->add_fail_tuple(2, tuple);
      }
    }
  }

  // 400 milliseconds second
  auto cb = [&ss](EventLoopImpl::Status status) { DoneHandler(&ss, status); };
  ss.registerTimer(std::move(cb), false, 300000);

  ss.loop();

  EXPECT_EQ(drainer->Verify(), true);
  delete drainer;
  delete g;
}