blob: 294a35a9aef353fdb114cf2cae4c4e84aea2b558 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "gtest/gtest.h"
#include "proto/messages.h"
#include "basics/basics.h"
#include "errors/errors.h"
#include "threads/threads.h"
#include "network/network.h"
#include "basics/modinit.h"
#include "errors/modinit.h"
#include "threads/modinit.h"
#include "network/modinit.h"
#include "metrics/metrics.h"
namespace heron {
namespace common {
using proto::system::MetricPublisherPublishMessage;
using proto::system::MetricDatum;
using std::chrono::high_resolution_clock;
using std::chrono::duration;
using std::chrono::milliseconds;
class TimeSpentMetricTest : public ::testing::Test {
public:
TimeSpentMetricTest() {}
~TimeSpentMetricTest() {}
void SetUp() { time_spent_metric_ = new TimeSpentMetric(); }
void TearDown() { delete time_spent_metric_; }
// It is hard to test the time in milliseconds.
// So we use EXPECT_NEAR, which take the error margin
// as a parameter.
// This function returns the absolute error expected
// for the given expected time.
sp_lint32 ExpectedError(sp_lint32 expectedTime) {
// We expect only 5% of the expected value as error.
sp_lint32 error = (sp_lint32)(5.0 / 100.0 * expectedTime);
return error;
}
protected:
TimeSpentMetric* time_spent_metric_;
};
TEST_F(TimeSpentMetricTest, testStart) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
// Sleep for some time
::usleep(sleepTime);
auto end = std::chrono::high_resolution_clock::now();
time_spent_metric_->GetAndReset(prefix, message);
sp_lint32 expectedTime =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testStartWithoutStop) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
// Sleep for some time
::usleep(sleepTime);
// Starting again should not make any difference.
time_spent_metric_->Start();
// It will just add up in the current recorded time.
::usleep(sleepTime);
auto end = std::chrono::high_resolution_clock::now();
time_spent_metric_->GetAndReset(prefix, message);
sp_lint32 expectedTime =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testStopWithouStart) {
sp_lint32 sleepTime = 100000; // microseconds
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
// Sleep for some time just to check.
::usleep(sleepTime);
// This should do nothing.
time_spent_metric_->Stop();
time_spent_metric_->GetAndReset(prefix, message);
sp_lint32 expectedTime = 0l;
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testStopAfterStop) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
// Sleep for some time
::usleep(sleepTime);
auto end = high_resolution_clock::now();
time_spent_metric_->Stop();
// It will should not affect the end time...
::usleep(sleepTime);
// if we Stop after a Stop.
time_spent_metric_->Stop();
time_spent_metric_->GetAndReset(prefix, message);
sp_lint32 expectedTime =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testStartStopStart) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = high_resolution_clock::now();
time_spent_metric_->Start();
// Sleep for some time
::usleep(sleepTime);
auto end = std::chrono::high_resolution_clock::now();
time_spent_metric_->Stop();
sp_lint32 expectedTime =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Start again
start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
// Sleep for some time
::usleep(sleepTime);
end = std::chrono::high_resolution_clock::now();
time_spent_metric_->GetAndReset(prefix, message);
expectedTime += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testMultipleStartStops) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
// Sleep for some time
::usleep(sleepTime);
auto end = std::chrono::high_resolution_clock::now();
time_spent_metric_->Stop();
sp_lint32 expectedTime =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Do it again.
start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
// Sleep for some time
::usleep(sleepTime);
end = std::chrono::high_resolution_clock::now();
time_spent_metric_->Stop();
expectedTime += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
time_spent_metric_->GetAndReset(prefix, message);
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testGetAndReset) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
// Sleep for some time
::usleep(sleepTime);
auto end = std::chrono::high_resolution_clock::now();
time_spent_metric_->Stop();
sp_lint32 expectedTime =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
time_spent_metric_->GetAndReset(prefix, message);
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime = atol(datum.value().c_str());
sp_lint32 expectedError = ExpectedError(expectedTime);
EXPECT_NEAR(expectedTime, actualTime, expectedError);
// Clean up.
delete message;
// After last GetAndReset, the value should have been reset.
// Create another message for next GetAndReset call.
message = new MetricPublisherPublishMessage();
// Expected count should be zero.
expectedTime = 0l;
time_spent_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(prefix.c_str(), datum.name().c_str());
// It should be absolutely zero.
EXPECT_EQ(expectedTime, atol(datum.value().c_str()));
// Clean up.
delete message;
}
TEST_F(TimeSpentMetricTest, testMultipleDatum) {
sp_lint32 sleepTime = 100000; // microseconds
auto start = high_resolution_clock::now();
time_spent_metric_->Start();
// Sleep for some time
::usleep(sleepTime);
auto end = std::chrono::high_resolution_clock::now();
time_spent_metric_->Stop();
sp_lint32 expectedTime1 =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
MetricPublisherPublishMessage* message = new MetricPublisherPublishMessage();
sp_string prefix = "TestPrefix";
time_spent_metric_->GetAndReset(prefix, message);
// Only one metric datum should be present.
EXPECT_EQ(1, message->metrics_size());
// Check that datum.
MetricDatum datum = message->metrics(0);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime1 = atol(datum.value().c_str());
sp_lint32 expectedError1 = ExpectedError(expectedTime1);
EXPECT_NEAR(expectedTime1, actualTime1, expectedError1);
// Next metrics
// Do it again.
start = std::chrono::high_resolution_clock::now();
time_spent_metric_->Start();
// Sleep for some time
::usleep(sleepTime);
end = std::chrono::high_resolution_clock::now();
time_spent_metric_->Stop();
sp_lint32 expectedTime2 =
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// Send the same message object.
time_spent_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());
actualTime1 = atol(datum.value().c_str());
expectedError1 = ExpectedError(expectedTime1);
EXPECT_NEAR(expectedTime1, actualTime1, expectedError1);
// Check the second datum.
datum = message->metrics(1);
EXPECT_STREQ(prefix.c_str(), datum.name().c_str());
sp_lint32 actualTime2 = atol(datum.value().c_str());
sp_lint32 expectedError2 = ExpectedError(expectedTime2);
EXPECT_NEAR(expectedTime2, actualTime2, expectedError2);
// Clean up.
delete message;
}
} // namespace common
} // namespace heron
sp_int32 main(sp_int32 argc, char** argv) {
heron::common::Initialize(argv[0]);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}