Skip to content

Commit

Permalink
test(rate_checker): add unit tests (#269)
Browse files Browse the repository at this point in the history
* test(rate_checker): add unit tests

Signed-off-by: Max SCHMELLER <[email protected]>

* chore: add license to unit test

Co-authored-by: Kenzo Lobos Tsunekawa <[email protected]>

---------

Signed-off-by: Max SCHMELLER <[email protected]>
Co-authored-by: Kenzo Lobos Tsunekawa <[email protected]>
  • Loading branch information
mojomex and knzo25 authored Feb 18, 2025
1 parent edac135 commit 8efeaf0
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
8 changes: 8 additions & 0 deletions nebula_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ endif(NOT ${YAML_CPP_VERSION} VERSION_LESS "0.5")

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
find_package(ament_cmake_gtest REQUIRED)
ament_lint_auto_find_test_dependencies()

ament_add_gtest(test_rate_checker
test/test_rate_checker.cpp
)
target_link_libraries(test_rate_checker
nebula_common
)
endif()

include_directories(
Expand Down
9 changes: 6 additions & 3 deletions nebula_common/include/nebula_common/util/rate_checker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include "nebula_common/util/ring_buffer.hpp"

#include <optional>

namespace nebula::util
{

Expand All @@ -27,7 +29,7 @@ class RateChecker
{
}

bool is_full() const { return ring_buffer_.is_full(); }
[[nodiscard]] bool is_full() const { return ring_buffer_.is_full(); }

void update(double stamp)
{
Expand All @@ -38,13 +40,14 @@ class RateChecker
last_stamp_ = stamp;
}

bool is_valid() const
[[nodiscard]] bool is_valid() const
{
if (ring_buffer_.size() == 0) return false;
double average = get_average();
return average >= min_rate_hz_ && average <= max_rate_hz_;
}

double get_average() const { return 1.0 / ring_buffer_.get_average(); }
[[nodiscard]] double get_average() const { return 1.0 / ring_buffer_.get_average(); }

private:
std::optional<double> last_stamp_;
Expand Down
12 changes: 9 additions & 3 deletions nebula_common/include/nebula_common/util/ring_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,17 @@ class RingBuffer
index_ = (index_ + 1) % buffer_.capacity();
}

std::size_t size() const { return buffer_.size(); }
[[nodiscard]] std::size_t size() const { return buffer_.size(); }

bool is_full() const { return buffer_.size() == buffer_.capacity(); }
[[nodiscard]] bool is_full() const { return buffer_.size() == buffer_.capacity(); }

T get_average() const { return sum_ / buffer_.size(); }
[[nodiscard]] T get_average() const
{
if (buffer_.size() == 0) {
throw std::runtime_error("Buffer is empty");
}
return sum_ / buffer_.size();
}

private:
T sum_{};
Expand Down
63 changes: 63 additions & 0 deletions nebula_common/test/test_rate_checker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2025 TIER IV, 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 "nebula_common/util/rate_checker.hpp"

#include <gtest/gtest.h>

static void feed_at_rate(nebula::util::RateChecker & checker, double rate_hz, uint32_t num_updates)
{
double interval = 1.0 / rate_hz;
for (uint32_t i = 0; i < num_updates; ++i) {
checker.update(i * interval);
}
}

TEST(RateCheckerTest, BasicFunctionality)
{
nebula::util::RateChecker checker(8.0, 12.0, 5);

EXPECT_FALSE(checker.is_full());
EXPECT_FALSE(checker.is_valid());
EXPECT_THROW(static_cast<void>(checker.get_average()), std::runtime_error);

feed_at_rate(checker, 10.0, 6);

EXPECT_TRUE(checker.is_full());
EXPECT_NO_THROW(static_cast<void>(checker.get_average()));
EXPECT_NEAR(checker.get_average(), 10.0, 0.1);
EXPECT_TRUE(checker.is_valid());
}

TEST(RateCheckerTest, InvalidRate)
{
nebula::util::RateChecker checker(8.0, 12.0, 3);

feed_at_rate(checker, 5.0, 4);

EXPECT_NEAR(checker.get_average(), 5.0, 0.1);
EXPECT_FALSE(checker.is_valid());

checker = nebula::util::RateChecker(8.0, 12.0, 3);
feed_at_rate(checker, 15.0, 4);

EXPECT_NEAR(checker.get_average(), 15.0, 0.1);
EXPECT_FALSE(checker.is_valid());
}

int main(int argc, char ** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

0 comments on commit 8efeaf0

Please sign in to comment.