/* Tests the rcl_system_time_point_now() function. */ TEST_F(TestTimeFixture, test_rcl_system_time_point_now) { assert_no_realloc_begin(); rcl_ret_t ret; // Check for invalid argument error condition (allowed to alloc). ret = rcl_system_time_point_now(nullptr); EXPECT_EQ(ret, RCL_RET_INVALID_ARGUMENT) << rcl_get_error_string_safe(); rcl_reset_error(); assert_no_malloc_begin(); assert_no_free_begin(); // Check for normal operation (not allowed to alloc). rcl_system_time_point_t now = {0}; ret = rcl_system_time_point_now(&now); assert_no_malloc_end(); assert_no_realloc_end(); assert_no_free_end(); stop_memory_checking(); EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe(); EXPECT_NE(now.nanoseconds, 0u); // Compare to std::chrono::system_clock time (within a second). now = {0}; ret = rcl_system_time_point_now(&now); { std::chrono::system_clock::time_point now_sc = std::chrono::system_clock::now(); auto now_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now_sc.time_since_epoch()); int64_t now_ns_int = now_ns.count(); int64_t now_diff = now.nanoseconds - now_ns_int; const int k_tolerance_ms = 1000; EXPECT_LE(llabs(now_diff), RCL_MS_TO_NS(k_tolerance_ms)) << "system_clock differs"; } }
void throw_from_rcl_error(rcl_ret_t ret, const std::string & prefix, bool reset_error) { if (RCL_RET_OK == ret) { throw std::invalid_argument("ret is RCL_RET_OK"); } const rcl_error_state_t * error_state = rcl_get_error_state(); if (!error_state) { throw std::runtime_error("rcl error state is not set"); } std::string formated_prefix = prefix; if (!prefix.empty()) { formated_prefix += ": "; } RCLErrorBase base_exc(ret, error_state); if (reset_error) { rcl_reset_error(); } switch (ret) { case RCL_RET_BAD_ALLOC: throw RCLBadAlloc(base_exc); case RCL_RET_INVALID_ARGUMENT: throw RCLInvalidArgument(base_exc, formated_prefix); default: throw RCLError(base_exc, formated_prefix); } }
/* Tests the rcl_steady_time_point_now() function. */ TEST_F(TestTimeFixture, test_rcl_steady_time_point_now) { assert_no_realloc_begin(); rcl_ret_t ret; // Check for invalid argument error condition (allowed to alloc). ret = rcl_steady_time_point_now(nullptr); EXPECT_EQ(ret, RCL_RET_INVALID_ARGUMENT) << rcl_get_error_string_safe(); rcl_reset_error(); assert_no_malloc_begin(); assert_no_free_begin(); // Check for normal operation (not allowed to alloc). rcl_steady_time_point_t now = {0}; ret = rcl_steady_time_point_now(&now); assert_no_malloc_end(); assert_no_realloc_end(); assert_no_free_end(); stop_memory_checking(); EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe(); EXPECT_NE(now.nanoseconds, 0u); // Compare to std::chrono::steady_clock difference of two times (within a second). now = {0}; ret = rcl_steady_time_point_now(&now); std::chrono::steady_clock::time_point now_sc = std::chrono::steady_clock::now(); EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe(); // Wait for a little while. std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Then take a new timestamp with each and compare. rcl_steady_time_point_t later; ret = rcl_steady_time_point_now(&later); std::chrono::steady_clock::time_point later_sc = std::chrono::steady_clock::now(); EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string_safe(); int64_t steady_diff = later.nanoseconds - now.nanoseconds; int64_t sc_diff = std::chrono::duration_cast<std::chrono::nanoseconds>(later_sc - now_sc).count(); const int k_tolerance_ms = 1; EXPECT_LE(llabs(steady_diff - sc_diff), RCL_MS_TO_NS(k_tolerance_ms)) << "steady_clock differs"; }
/* Tests the rcl_init(), rcl_ok(), and rcl_shutdown() functions. */ TEST_F(TestRCLFixture, test_rcl_init_and_ok_and_shutdown) { rcl_ret_t ret; // A shutdown before any init has been called should fail. ret = rcl_shutdown(); EXPECT_EQ(RCL_RET_NOT_INIT, ret); rcl_reset_error(); ASSERT_FALSE(rcl_ok()); // If argc is not 0, but argv is, it should be an invalid argument. ret = rcl_init(42, nullptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret); rcl_reset_error(); ASSERT_FALSE(rcl_ok()); // If either the allocate or deallocate function pointers are not set, it should be invalid arg. rcl_allocator_t invalid_allocator = rcl_get_default_allocator(); invalid_allocator.allocate = nullptr; ret = rcl_init(0, nullptr, invalid_allocator); EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret); rcl_reset_error(); ASSERT_FALSE(rcl_ok()); invalid_allocator.allocate = rcl_get_default_allocator().allocate; invalid_allocator.deallocate = nullptr; ret = rcl_init(0, nullptr, invalid_allocator); EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret); rcl_reset_error(); ASSERT_FALSE(rcl_ok()); // If the malloc call fails (with some valid arguments to copy), it should be a bad alloc. { FakeTestArgv test_args; rcl_allocator_t failing_allocator = rcl_get_default_allocator(); failing_allocator.allocate = &failing_malloc; failing_allocator.deallocate = failing_free; failing_allocator.reallocate = failing_realloc; ret = rcl_init(test_args.argc, test_args.argv, failing_allocator); EXPECT_EQ(RCL_RET_BAD_ALLOC, ret); rcl_reset_error(); ASSERT_FALSE(rcl_ok()); } // If argc is 0 and argv is nullptr and the allocator is valid, it should succeed. ret = rcl_init(0, nullptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret); ASSERT_TRUE(rcl_ok()); // Then shutdown should work. ret = rcl_shutdown(); EXPECT_EQ(ret, RCL_RET_OK); ASSERT_FALSE(rcl_ok()); // Valid argc/argv values and a valid allocator should succeed. { FakeTestArgv test_args; ret = rcl_init(test_args.argc, test_args.argv, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret); ASSERT_TRUE(rcl_ok()); } // Then shutdown should work. ret = rcl_shutdown(); EXPECT_EQ(RCL_RET_OK, ret); ASSERT_FALSE(rcl_ok()); // A repeat call to shutdown should not work. ret = rcl_shutdown(); EXPECT_EQ(RCL_RET_NOT_INIT, ret); rcl_reset_error(); ASSERT_FALSE(rcl_ok()); // Repeat, but valid, calls to rcl_init() should fail. { FakeTestArgv test_args; ret = rcl_init(test_args.argc, test_args.argv, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret); ASSERT_TRUE(rcl_ok()); ret = rcl_init(test_args.argc, test_args.argv, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_ALREADY_INIT, ret); rcl_reset_error(); ASSERT_TRUE(rcl_ok()); } // But shutdown should still work. ret = rcl_shutdown(); EXPECT_EQ(ret, RCL_RET_OK); ASSERT_FALSE(rcl_ok()); }