TEST_F(MultiCountMetricTest, testSameScope) {
  sp_string scope1 = "testscope1";
  CountMetric* count_metric1 = multi_count_metric_->scope(scope1);
  count_metric1->incr();
  count_metric1->incr();

  // Same scope
  sp_string scope2 = "testscope1";
  CountMetric* count_metric2 = multi_count_metric_->scope(scope2);
  count_metric2->incr_by(3);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";

  // Expected count is sum of all the above increments.
  int expectedCount = 5;
  sp_string expectedPrefix = prefix + "/" + scope1;

  multi_count_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  delete message;
}
TEST_F(MultiCountMetricTest, testOneCountMetric) {
  sp_string scope1 = "testscope1";
  CountMetric* count_metric = multi_count_metric_->scope(scope1);
  count_metric->incr();

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  int expectedCount = 1;

  // Prefix should also have scope attached to it.
  sp_string expectedPrefix = prefix + "/" + scope1;

  multi_count_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(MultiMeanMetricTest, testOneMeanMetric) {
  sp_string scope1 = "testscope1";
  MeanMetric* mean_metric = multi_mean_metric_->scope(scope1);
  mean_metric->record(5);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  double expectedMean = 5.0;

  // Prefix should also have scope attached to it.
  sp_string expectedPrefix = prefix + "/" + scope1;

  multi_mean_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_DOUBLE_EQ(expectedMean, atof(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(MultiMeanMetricTest, testSameScope) {
  sp_string scope1 = "testscope1";
  MeanMetric* mean_metric1 = multi_mean_metric_->scope(scope1);
  mean_metric1->record(4);
  mean_metric1->record(5);

  // Same scope
  sp_string scope2 = "testscope1";
  MeanMetric* mean_metric2 = multi_mean_metric_->scope(scope2);
  mean_metric2->record(9);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";

  // Expected mean is sum of all the above records.
  double expectedMean = 6.0;
  sp_string expectedPrefix = prefix + "/" + scope1;

  multi_mean_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_DOUBLE_EQ(expectedMean, atof(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(MultiMeanMetricTest, testGetAndReset) {
  sp_string scope1 = "testscope1";
  MeanMetric* mean_metric1 = multi_mean_metric_->scope(scope1);
  mean_metric1->record(2);
  mean_metric1->record(4);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  double expectedMean = 3.0;
  sp_string expectedPrefix = prefix + "/" + scope1;

  multi_mean_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_DOUBLE_EQ(expectedMean, atof(datum.value().c_str()));

  // Clean up.
  delete message;

  // After last GetAndReset, the value should have been reset.
  // Create another message for next GetAndReset call.
  message = CreateEmptyPublishMessage();

  // Expected mean should be zero.
  expectedMean = 0.0;
  multi_mean_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_DOUBLE_EQ(expectedMean, atof(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(MultiCountMetricTest, testGetAndReset) {
  sp_string scope1 = "testscope1";
  CountMetric* count_metric1 = multi_count_metric_->scope(scope1);
  count_metric1->incr_by(2);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  int expectedCount = 2;
  sp_string expectedPrefix = prefix + "/" + scope1;

  multi_count_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Clean up.
  delete message;

  // After last GetAndReset, the value should have been reset.
  // Create another message for next GetAndReset call.
  message = CreateEmptyPublishMessage();

  // Expected count should be zero.
  expectedCount = 0;
  multi_count_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(CountMetricTest, testIncrBy) {
  count_metric_->incr_by(2);
  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  int expectedCount = 2;
  count_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(CountMetricTest, testMultipleDatum) {
  count_metric_->incr();
  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  int expectedCount = 1;
  count_metric_->GetAndReset(prefix, message);

  // Only one metric datum should be present.
  EXPECT_EQ(1, message->metrics_size());

  // Check that datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Next metrics
  count_metric_->incr_by(2);

  // Send the same message object.
  count_metric_->GetAndReset(prefix, message);

  // Two metric datum should be present.
  EXPECT_EQ(2, message->metrics_size());

  // Check the first datum.
  datum = message->metrics(0);
  EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Check the second datum.
  expectedCount = 2;
  datum = message->metrics(1);
  EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount, atoi(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(MultiMeanMetricTest, testMultipleMeanMetrics) {
  sp_string scope1 = "testscope1";
  MeanMetric* mean_metric1 = multi_mean_metric_->scope(scope1);
  mean_metric1->record(5);
  mean_metric1->record(2);

  sp_string scope2 = "testscope2";
  MeanMetric* mean_metric2 = multi_mean_metric_->scope(scope2);
  mean_metric2->record(5);
  mean_metric2->record(8);
  mean_metric2->record(2);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  double expectedMean1 = 3.5;
  double expectedMean2 = 5.0;
  sp_string expectedPrefix1 = prefix + "/" + scope1;
  sp_string expectedPrefix2 = prefix + "/" + scope2;

  multi_mean_metric_->GetAndReset(prefix, message);

  // Two metric datum should be present.
  EXPECT_EQ(2, message->metrics_size());

  // Check first datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix1.c_str(), datum.name().c_str());
  EXPECT_DOUBLE_EQ(expectedMean1, atof(datum.value().c_str()));

  // Check second datum.
  datum = message->metrics(1);
  EXPECT_STREQ(expectedPrefix2.c_str(), datum.name().c_str());
  EXPECT_DOUBLE_EQ(expectedMean2, atof(datum.value().c_str()));

  // Clean up.
  delete message;
}
TEST_F(MultiCountMetricTest, testMultipleCountMetrics) {
  sp_string scope1 = "testscope1";
  CountMetric* count_metric1 = multi_count_metric_->scope(scope1);
  count_metric1->incr();
  count_metric1->incr();

  sp_string scope2 = "testscope2";
  CountMetric* count_metric2 = multi_count_metric_->scope(scope2);
  count_metric2->incr_by(3);

  heron::proto::system::MetricPublisherPublishMessage* message = CreateEmptyPublishMessage();

  sp_string prefix = "TestPrefix";
  int expectedCount1 = 2;
  int expectedCount2 = 3;
  sp_string expectedPrefix1 = prefix + "/" + scope1;
  sp_string expectedPrefix2 = prefix + "/" + scope2;

  multi_count_metric_->GetAndReset(prefix, message);

  // Two metric datum should be present.
  EXPECT_EQ(2, message->metrics_size());

  // Check first datum.
  heron::proto::system::MetricDatum datum = message->metrics(0);
  EXPECT_STREQ(expectedPrefix1.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount1, atoi(datum.value().c_str()));

  // Check second datum.
  datum = message->metrics(1);
  EXPECT_STREQ(expectedPrefix2.c_str(), datum.name().c_str());
  EXPECT_EQ(expectedCount2, atoi(datum.value().c_str()));

  // Clean up.
  delete message;
}