// Copyright 2015 Open Source Robotics Foundation, 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. #include #include #include #include "rclcpp/rate.hpp" #include "../utils/rclcpp_gtest_macros.hpp" class TestRate : public ::testing::Test { public: void SetUp() { rclcpp::init(0, nullptr); } void TearDown() { rclcpp::shutdown(); } }; /* Basic tests for the Rate and WallRate classes. */ TEST_F(TestRate, rate_basics) { auto period = std::chrono::milliseconds(1000); auto offset = std::chrono::milliseconds(500); auto epsilon = std::chrono::milliseconds(100); double overrun_ratio = 1.5; auto start = std::chrono::system_clock::now(); rclcpp::Rate r(period); EXPECT_EQ(rclcpp::Duration(period), r.period()); ASSERT_EQ(RCL_SYSTEM_TIME, r.get_type()); ASSERT_TRUE(r.sleep()); auto one = std::chrono::system_clock::now(); auto delta = one - start; EXPECT_LT(period, delta + epsilon); EXPECT_GT(period * overrun_ratio, delta); rclcpp::sleep_for(offset); ASSERT_TRUE(r.sleep()); auto two = std::chrono::system_clock::now(); delta = two - start; EXPECT_LT(2 * period, delta); EXPECT_GT(2 * period * overrun_ratio, delta); rclcpp::sleep_for(offset); auto two_offset = std::chrono::system_clock::now(); r.reset(); ASSERT_TRUE(r.sleep()); auto three = std::chrono::system_clock::now(); delta = three - two_offset; EXPECT_LT(period, delta + epsilon); EXPECT_GT(period * overrun_ratio, delta); rclcpp::sleep_for(offset + period); auto four = std::chrono::system_clock::now(); ASSERT_FALSE(r.sleep()); auto five = std::chrono::system_clock::now(); delta = five - four; ASSERT_TRUE(epsilon > delta); } TEST_F(TestRate, wall_rate_basics) { auto period = std::chrono::milliseconds(100); auto offset = std::chrono::milliseconds(50); auto epsilon = std::chrono::milliseconds(1); double overrun_ratio = 1.5; auto start = std::chrono::steady_clock::now(); rclcpp::WallRate r(period); EXPECT_EQ(rclcpp::Duration(period), r.period()); ASSERT_EQ(RCL_STEADY_TIME, r.get_type()); ASSERT_TRUE(r.sleep()); auto one = std::chrono::steady_clock::now(); auto delta = one - start; EXPECT_LT(period, delta); EXPECT_GT(period * overrun_ratio, delta); rclcpp::sleep_for(offset); ASSERT_TRUE(r.sleep()); auto two = std::chrono::steady_clock::now(); delta = two - start; EXPECT_LT(2 * period, delta + epsilon); EXPECT_GT(2 * period * overrun_ratio, delta); rclcpp::sleep_for(offset); auto two_offset = std::chrono::steady_clock::now(); r.reset(); ASSERT_TRUE(r.sleep()); auto three = std::chrono::steady_clock::now(); delta = three - two_offset; EXPECT_LT(period, delta); EXPECT_GT(period * overrun_ratio, delta); rclcpp::sleep_for(offset + period); auto four = std::chrono::steady_clock::now(); ASSERT_FALSE(r.sleep()); auto five = std::chrono::steady_clock::now(); delta = five - four; EXPECT_GT(epsilon, delta); } TEST_F(TestRate, from_double) { { rclcpp::Rate rate(1.0); EXPECT_EQ(rclcpp::Duration(std::chrono::seconds(1)), rate.period()); } { rclcpp::Rate rate(2.0); EXPECT_EQ(rclcpp::Duration(std::chrono::milliseconds(500)), rate.period()); } { rclcpp::WallRate rate(0.5); EXPECT_EQ(rclcpp::Duration(std::chrono::seconds(2)), rate.period()); } { rclcpp::WallRate rate(4.0); EXPECT_EQ(rclcpp::Duration(std::chrono::milliseconds(250)), rate.period()); } } TEST_F(TestRate, clock_types) { { rclcpp::Rate rate(1.0, std::make_shared(RCL_SYSTEM_TIME)); EXPECT_EQ(RCL_SYSTEM_TIME, rate.get_type()); } { rclcpp::Rate rate(1.0, std::make_shared(RCL_STEADY_TIME)); EXPECT_EQ(RCL_STEADY_TIME, rate.get_type()); } { rclcpp::Rate rate(1.0, std::make_shared(RCL_ROS_TIME)); EXPECT_EQ(RCL_ROS_TIME, rate.get_type()); } } TEST_F(TestRate, incorrect_constuctor) { // Constructor with 0-frequency RCLCPP_EXPECT_THROW_EQ( rclcpp::Rate rate(0.0), std::invalid_argument("rate must be greater than 0")); // Constructor with negative frequency RCLCPP_EXPECT_THROW_EQ( rclcpp::Rate rate(-1.0), std::invalid_argument("rate must be greater than 0")); // Constructor with 0-duration RCLCPP_EXPECT_THROW_EQ( rclcpp::Rate rate(rclcpp::Duration(0, 0)), std::invalid_argument("period must be greater than 0")); // Constructor with negative duration RCLCPP_EXPECT_THROW_EQ( rclcpp::Rate rate(rclcpp::Duration(-1, 0)), std::invalid_argument("period must be greater than 0")); } TEST(TestRateBasic, invalid_context) { rclcpp::init(0, nullptr); rclcpp::Rate rate(1.0); ASSERT_TRUE(rate.sleep()); rclcpp::shutdown(); EXPECT_NO_THROW(rate.sleep()); ASSERT_FALSE(rate.sleep()); }