cloudwatch_metrics_collector_test.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  * http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 #include <aws/core/Aws.h>
16 #include <aws/core/utils/logging/LogMacros.h>
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <ros/console.h>
20 #include <ros/ros.h>
21 
27 #include <ros_monitoring_msgs/MetricData.h>
28 
30 #include <utility>
31 
32 using namespace Aws::CloudWatchMetrics;
33 using namespace Aws::CloudWatchMetrics::Utils;
34 using namespace Aws::FileManagement;
35 using ::testing::_;
36 using ::testing::Return;
37 using ::testing::StrEq;
38 
40 char** test_argv;
41 
43 {
44 public:
45  MOCK_METHOD4(createMetricService,
46  std::shared_ptr<MetricService>(
47  const std::string & metrics_namespace,
48  const Aws::Client::ClientConfiguration & client_config,
49  const Aws::SDKOptions & sdk_options,
50  const CloudWatchOptions & cloudwatch_option)
51  );
52 };
53 
55 {
56 public:
57 
58  MOCK_METHOD0(publishBatchedData, bool());
59 };
60 
62 {
63 public:
64  MetricPublisherMock(const std::string & metrics_namespace,
65  const Aws::Client::ClientConfiguration & client_config)
66  : MetricPublisher(metrics_namespace, client_config) {}
67 };
68 
70 {
71 public:
73  std::shared_ptr<DataBatcher<MetricDatum>> batcher,
74  std::shared_ptr<FileUploadStreamer<MetricDatumCollection>> file_upload_streamer = nullptr)
75  : MetricService(std::move(publisher), std::move(batcher), std::move(file_upload_streamer)) {}
76 
77  MOCK_METHOD1(batchData, bool(const MetricObject & data_to_batch));
78  MOCK_METHOD0(start, bool());
79  MOCK_METHOD0(shutdown, bool());
80  MOCK_METHOD0(publishBatchedData, bool());
81 };
82 
83 
84 class MetricsCollectorFixture : public ::testing::Test
85 {
86 protected:
87  const std::string kMetricsTopic = "metrics";
88  const std::string kMetricName1 = "CWMetricsNodeTestMetric";
89  const std::string kMetricUnit1 = "sec";
90  const std::string metric_namespace = "test_namespace";
91 
92  Aws::Client::ClientConfiguration config;
93  Aws::SDKOptions sdk_options;
95 
96  std::shared_ptr<MetricServiceMock> metric_service;
97  std::shared_ptr<MetricPublisherMock> metric_publisher;
98  std::shared_ptr<MetricBatcherMock> metric_batcher;
99  std::shared_ptr<MetricsCollector> metrics_collector;
100 
101  std::shared_ptr<ros::NodeHandle> node_handle;
102  std::shared_ptr<ros::Publisher> metrics_pub;
103 
104  void SetUp() override
105  {
106  metric_batcher = std::make_shared<MetricBatcherMock>();
107  metric_publisher = std::make_shared<MetricPublisherMock>(metric_namespace, config);
108  metric_service = std::make_shared<MetricServiceMock>(metric_publisher, metric_batcher);
109  }
110 
111  void Initialize(std::map<std::string, std::string> metric_dimensions) {
112 
113  ros::init(test_argc, test_argv, "CWMetricsNodeTest");
114  metrics_collector = std::make_shared<MetricsCollector>();
115 
116  node_handle = std::make_shared<ros::NodeHandle>();
117  metrics_pub = std::make_shared<ros::Publisher>(
118  node_handle->advertise<ros_monitoring_msgs::MetricList>(kMetricsTopic.c_str(), 1));
119 
120  EXPECT_CALL(*metric_service, start()).Times(1);
121 
122  std::shared_ptr<MetricServiceFactoryMock> metric_factory_mock = std::make_shared<MetricServiceFactoryMock>();
123 
124  EXPECT_CALL(*metric_factory_mock,
125  createMetricService(StrEq(metric_namespace), _, _, _))
126  .WillOnce(Return(metric_service));
127 
128  node_handle = std::make_shared<ros::NodeHandle>();
129 
130  metrics_collector->Initialize(metric_namespace,
131  metric_dimensions,
132  60,
133  *node_handle,
134  config,
135  sdk_options,
136  cloudwatch_options,
137  metric_factory_mock);
138 
139  metrics_collector->start();
140  }
141 
142  void TearDown() override {
143  if(metrics_collector) {
144  EXPECT_CALL(*metric_service, shutdown()).Times(1);
145  metrics_collector->shutdown();
146  }
148  }
149 
150  void SendMetricMessages(int num_msgs, ros_monitoring_msgs::MetricData & metric_data_proto)
151  {
152  ros_monitoring_msgs::MetricList metric_list_msg = ros_monitoring_msgs::MetricList();
153  for (int i = 0; i < num_msgs; i++) {
154  metric_data_proto.value = i;
155  metric_data_proto.time_stamp = ros::Time::now();
156  metric_list_msg.metrics.clear();
157  metric_list_msg.metrics.push_back(metric_data_proto);
158  AWS_LOGSTREAM_DEBUG(__func__, "Publishing " << metric_list_msg.metrics.size()
159  << " metrics to topic " << kMetricsTopic.c_str());
160  metrics_pub->publish(metric_list_msg);
161  ros::spinOnce();
162  std::this_thread::sleep_for(std::chrono::seconds(1));
163  }
164  }
165 
166  ros_monitoring_msgs::MetricData BasicMetricData()
167  {
168  ros_monitoring_msgs::MetricData metric_data = ros_monitoring_msgs::MetricData();
169  metric_data.metric_name = kMetricName1;
170  metric_data.unit = kMetricUnit1;
171  return metric_data;
172  }
173 };
174 
175 // Test fixture Setup and TearDown
177  ASSERT_TRUE(true);
178 }
179 
180 // Test fixture init
181 TEST_F(MetricsCollectorFixture, TestInitialize) {
182  std::map<std::string, std::string> metric_dimensions;
183  Initialize(metric_dimensions);
184 }
185 
189 };
190 
191 class GetMetricDataEpochMillisFixture : public ::testing::TestWithParam<GetMetricDataEpochMillisTestDatum> {};
192 
193 TEST_P(GetMetricDataEpochMillisFixture, getMetricDataEpochMillisTestOk)
194 {
195  ros_monitoring_msgs::MetricData metric_msg;
196  metric_msg.time_stamp = GetParam().input_time;
197  EXPECT_EQ(GetParam().expected_timestamp, MetricsCollector::GetMetricDataEpochMillis(metric_msg));
198 }
199 
208 };
209 
210 INSTANTIATE_TEST_CASE_P(getMetricDataEpochMillisTest, GetMetricDataEpochMillisFixture,
211  ::testing::ValuesIn(getMetricDataEpochMillisTestData));
212 
213 TEST_F(MetricsCollectorFixture, timerCallsMetricManagerService)
214 {
215  std::map<std::string, std::string> metric_dimensions;
216  Initialize(metric_dimensions);
217 
218  int num_msgs = 3;
219 
220  EXPECT_CALL(*metric_service, publishBatchedData())
221  .Times(::testing::AnyNumber())
222  .WillRepeatedly(::testing::Return(true));
223 
224  EXPECT_CALL(*metric_service,
225  batchData(::testing::_))
226  .Times(::testing::AtLeast(num_msgs))
227  .WillRepeatedly(::testing::Return(true));
228 
229  ros_monitoring_msgs::MetricData metric_data = BasicMetricData();
230  SendMetricMessages(num_msgs, metric_data);
231  for (int i = 0; i < num_msgs; i++) {
232  ros::spinOnce();
233  std::this_thread::sleep_for(std::chrono::seconds(1));
234  }
235 }
236 
241 MATCHER_P(metricsAreEqual, toTest, "") {
242  return arg.metric_name == toTest.metric_name
243  && arg.value == toTest.value
244  && arg.unit == toTest.unit
245  && arg.dimensions == toTest.dimensions
246  && arg.storage_resolution == toTest.storage_resolution;
247  // timestamp is ignored
248 }
249 
250 TEST_F(MetricsCollectorFixture, metricsRecordedNoDimension)
251 {
252  std::map<std::string, std::string> metric_dimensions;
253  Initialize(metric_dimensions);
254 
255  int num_msgs = 3;
256 
257  MetricObject m01 = MetricObject {kMetricName1, 0.0, kMetricUnit1, 1234, std::map<std::string, std::string>(), 60};
258  MetricObject m02 = MetricObject {kMetricName1, 1.0, kMetricUnit1, 1234, std::map<std::string, std::string>(), 60};
259  MetricObject m03 = MetricObject {kMetricName1, 2.0, kMetricUnit1, 1234, std::map<std::string, std::string>(), 60};
260 
261  EXPECT_CALL(*metric_service, publishBatchedData())
262  .Times(::testing::AnyNumber())
263  .WillRepeatedly(::testing::Return(true));
264  {
265  ::testing::Sequence rm_seq;
266  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m01)))
267  .WillOnce(::testing::Return(true));
268  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m02)))
269  .WillOnce(::testing::Return(true));
270  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m03)))
271  .WillOnce(::testing::Return(true));
272  }
273 
274  ros_monitoring_msgs::MetricData metric_data = BasicMetricData();
275  SendMetricMessages(num_msgs, metric_data);
276  ros::spinOnce();
277 }
278 
279 TEST_F(MetricsCollectorFixture, metricRecordedWithDimension)
280 {
281 
282  int num_msgs = 3;
283  const std::string metric_dimension_name = "CWMetricsNodeTestDim1";
284  const std::string metric_dimension_value = "CWMetricsNodeTestDim1Value";
285 
286  std::map<std::string, std::string> expected_dim;
287  expected_dim[metric_dimension_name] = metric_dimension_value;
288 
289  MetricObject m01 = MetricObject {kMetricName1, 0.0, kMetricUnit1, 1234, expected_dim, 60};
290  MetricObject m02 = MetricObject {kMetricName1, 1.0, kMetricUnit1, 1234, expected_dim, 60};
291  MetricObject m03 = MetricObject {kMetricName1, 2.0, kMetricUnit1, 1234, expected_dim, 60};
292 
293  EXPECT_CALL(*metric_service, publishBatchedData())
294  .Times(::testing::AnyNumber())
295  .WillRepeatedly(::testing::Return(true));
296 
297  {
298  ::testing::Sequence rm_seq;
299  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m01)))
300  .WillOnce(::testing::Return(true));
301  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m02)))
302  .WillOnce(::testing::Return(true));
303  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m03)))
304  .WillOnce(::testing::Return(true));
305  }
306 
307  Initialize(expected_dim);
308 
309  ros_monitoring_msgs::MetricData metric_data = BasicMetricData();
310  ros_monitoring_msgs::MetricDimension metric_dimension = ros_monitoring_msgs::MetricDimension();
311  metric_dimension.name = metric_dimension_name;
312  metric_dimension.value = metric_dimension_value;
313  metric_data.dimensions.push_back(metric_dimension);
314 
315  SendMetricMessages(num_msgs, metric_data);
316  ros::spinOnce();
317 }
318 
319 TEST_F(MetricsCollectorFixture, metricRecordedWithDefaultDimensions)
320 {
321 
322  int num_msgs = 3;
323  const std::string metric_dimension_name = "CWMetricsNodeTestDim1";
324  const std::string metric_dimension_value = "CWMetricsNodeTestDim1Value";
325 
326  std::map<std::string, std::string> expected_dim;
327  expected_dim[metric_dimension_name] = metric_dimension_value;
328 
329  MetricObject m01 = MetricObject {kMetricName1, 0.0, kMetricUnit1, 1234, expected_dim, 60};
330  MetricObject m02 = MetricObject {kMetricName1, 1.0, kMetricUnit1, 1234, expected_dim, 60};
331  MetricObject m03 = MetricObject {kMetricName1, 2.0, kMetricUnit1, 1234, expected_dim, 60};
332 
333  EXPECT_CALL(*metric_service, publishBatchedData())
334  .Times(::testing::AnyNumber())
335  .WillRepeatedly(::testing::Return(true));
336 
337  {
338  ::testing::Sequence rm_seq;
339  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m01)))
340  .WillOnce(::testing::Return(true));
341  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m02)))
342  .WillOnce(::testing::Return(true));
343  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m03)))
344  .WillOnce(::testing::Return(true));
345  }
346 
347  std::map<std::string, std::string> default_metric_dims;
348  default_metric_dims.emplace(metric_dimension_name, metric_dimension_value);
349  Initialize(default_metric_dims);
350 
351  ros_monitoring_msgs::MetricData metric_data = BasicMetricData();
352 
353  SendMetricMessages(num_msgs, metric_data);
354  ros::spinOnce();
355 }
356 
357 TEST_F(MetricsCollectorFixture, customTopicsListened)
358 {
359  std::vector<std::string> topics;
360  topics.emplace_back("metrics_topic0");
361  topics.emplace_back("metrics_topic1");
363 
364  std::map<std::string, std::string> default_metric_dims;
365 
366  MetricObject m01 = MetricObject {kMetricName1, 0.0, kMetricUnit1, 1234, default_metric_dims, 60};
367  MetricObject m02 = MetricObject {kMetricName1, 1.0, kMetricUnit1, 1234, default_metric_dims, 60};
368 
369  EXPECT_CALL(*metric_service, publishBatchedData())
370  .Times(::testing::AnyNumber())
371  .WillRepeatedly(::testing::Return(true));
372  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m01)))
373  .Times(1)
374  .WillOnce(::testing::Return(true));
375  EXPECT_CALL(*metric_service, batchData(metricsAreEqual(m02)))
376  .Times(1)
377  .WillOnce(::testing::Return(true));
378 
379  Initialize(default_metric_dims);
380 
381  ros_monitoring_msgs::MetricList metric_list_msg = ros_monitoring_msgs::MetricList();
382  ros_monitoring_msgs::MetricData metric_data = BasicMetricData();
383  ros::Publisher metrics_pub0 =
384  node_handle->advertise<ros_monitoring_msgs::MetricList>(topics[0].c_str(), 1);
385  metric_data.value = 0;
386  metric_data.time_stamp = ros::Time::now();
387  metric_list_msg.metrics.clear();
388  metric_list_msg.metrics.push_back(metric_data);
389  metrics_pub0.publish(metric_list_msg);
390  ros::spinOnce();
391  ros::Publisher metrics_pub1 =
392  node_handle->advertise<ros_monitoring_msgs::MetricList>(topics[1].c_str(), 1);
393  metric_data.value = 1;
394  metric_data.time_stamp = ros::Time::now();
395  metric_list_msg.metrics.clear();
396  metric_list_msg.metrics.push_back(metric_data);
397  metrics_pub1.publish(metric_list_msg);
398  ros::spinOnce();
399  std::this_thread::sleep_for(std::chrono::seconds(1));
400  ros::spinOnce();
401 }
402 
403 int main(int argc, char ** argv)
404 {
405  testing::InitGoogleTest(&argc, argv);
406  test_argc = argc;
407  test_argv = argv;
408  return RUN_ALL_TESTS();
409 }
MATCHER_P(metricsAreEqual, toTest,"")
ros_monitoring_msgs::MetricData BasicMetricData()
ROSCPP_DECL void start()
void publish(const boost::shared_ptr< M > &message) const
std::shared_ptr< ros::NodeHandle > node_handle
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
const GetMetricDataEpochMillisTestDatum getMetricDataEpochMillisTestData[]
Aws::Client::ClientConfiguration config
std::shared_ptr< ros::Publisher > metrics_pub
std::shared_ptr< MetricBatcherMock > metric_batcher
MetricPublisherMock(const std::string &metrics_namespace, const Aws::Client::ClientConfiguration &client_config)
std::shared_ptr< MetricsCollector > metrics_collector
ROSCPP_DECL void set(const std::string &key, const XmlRpc::XmlRpcValue &v)
const std::string kNodeParamMonitorTopicsListKey("aws_monitored_metric_topics")
std::shared_ptr< MetricServiceMock > metric_service
void Initialize(std::map< std::string, std::string > metric_dimensions)
std::shared_ptr< MetricPublisherMock > metric_publisher
INSTANTIATE_TEST_CASE_P(getMetricDataEpochMillisTest, GetMetricDataEpochMillisFixture,::testing::ValuesIn(getMetricDataEpochMillisTestData))
int main(int argc, char **argv)
ROSCPP_DECL bool del(const std::string &key)
ROSCONSOLE_DECL void shutdown()
void SendMetricMessages(int num_msgs, ros_monitoring_msgs::MetricData &metric_data_proto)
Aws::CloudWatchMetrics::CloudWatchOptions cloudwatch_options
static int64_t GetMetricDataEpochMillis(const ros_monitoring_msgs::MetricData &metric_msg)
static Time now()
MetricServiceMock(std::shared_ptr< Publisher< MetricDatumCollection >> publisher, std::shared_ptr< DataBatcher< MetricDatum >> batcher, std::shared_ptr< FileUploadStreamer< MetricDatumCollection >> file_upload_streamer=nullptr)
ROSCPP_DECL void spinOnce()
TEST_F(MetricsCollectorFixture, Sanity)
TEST_P(GetMetricDataEpochMillisFixture, getMetricDataEpochMillisTestOk)


cloudwatch_metrics_collector
Author(s): AWS RoboMaker
autogenerated on Fri Mar 5 2021 03:38:40