Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions for C++ assertions #31

Merged
merged 9 commits into from
Feb 6, 2020
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ include_directories(include)
ament_export_include_directories(include)

add_library(${PROJECT_NAME}
src/asserts.cpp
src/find_library.cpp)
target_include_directories(${PROJECT_NAME}
PUBLIC
Expand All @@ -46,6 +47,16 @@ if(BUILD_TESTING)

ament_lint_auto_find_test_dependencies()

ament_add_gtest(test_asserts_ndebug test/test_asserts.cpp)
target_link_libraries(test_asserts_ndebug ${PROJECT_NAME})
zmichaels11 marked this conversation as resolved.
Show resolved Hide resolved

if(TARGET test_asserts_ndebug)
target_compile_definitions(test_asserts_ndebug PUBLIC NDEBUG)
endif()

ament_add_gtest(test_asserts_debug test/test_asserts.cpp)
target_link_libraries(test_asserts_debug ${PROJECT_NAME})

ament_add_gtest(test_thread_safety_annotations test/test_thread_safety_annotations.cpp)

ament_add_gtest(test_join test/test_join.cpp)
Expand Down
106 changes: 106 additions & 0 deletions include/rcpputils/asserts.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// 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.

#ifndef RCPPUTILS__ASSERTS_HPP_
#define RCPPUTILS__ASSERTS_HPP_

#include <exception>
#include <stdexcept>
#include <string>

#include "rcpputils/visibility_control.hpp"

// Needed to disable compiler warning for exporting a class that extends a
// non-DLL-interface class.
// This should be fine since its extending an STL class.
#ifdef _WIN32
# pragma warning(push)
zmichaels11 marked this conversation as resolved.
Show resolved Hide resolved
# pragma warning(disable:4251)
# pragma warning(disable:4275)
#endif

namespace rcpputils
{

class RCPPUTILS_PUBLIC AssertionException : public std::exception
{
std::string msg_;

public:
explicit AssertionException(const char * msg);

virtual const char * what() const throw();
};

class RCPPUTILS_PUBLIC IllegalStateException : public std::exception
{
std::string msg_;

public:
explicit IllegalStateException(const char * msg);

virtual const char * what() const throw();
};

/**
* Checks that an argument condition passes.
*
* \param condition
* \throw std::invalid_argument if the condition is not met.
*/
inline void require_true(bool condition)
{
if (!condition) {
throw std::invalid_argument{"Invalid argument passed!"};
}
}

/**
* Checks that a state condition passes.
*
* \param condition
* \throw rcpputils::IllegalStateException if the condition is not met.
*/
inline void check_true(bool condition)
{
if (!condition) {
throw rcpputils::IllegalStateException{"Check reported invalid state!"};
}
}

/**
* Asserts that a condition passes.
*
* This function behaves similar to assert, except that it throws instead of invoking abort().
* \param condition
* \throw rcpputils::AssertionException if the macro NDEBUG is not set and the condition is not met.
*/
inline void assert_true(bool condition)
{
// Same macro definition used by cassert
#ifndef NDEBUG
if (!condition) {
throw rcpputils::AssertionException{"Assertion failed!"};
}
#else
(void) condition;
#endif
}
} // namespace rcpputils

#ifdef _WIN32
# pragma warning(pop)
#endif

#endif // RCPPUTILS__ASSERTS_HPP_
38 changes: 38 additions & 0 deletions src/asserts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// 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 "rcpputils/asserts.hpp"

namespace rcpputils
{
AssertionException::AssertionException(const char * msg)
{
msg_ = msg;
}

const char * AssertionException::what() const throw()
{
return msg_.c_str();
}

IllegalStateException::IllegalStateException(const char * msg)
{
msg_ = msg;
}

const char * IllegalStateException::what() const throw()
{
return msg_.c_str();
}
} // namespace rcpputils
52 changes: 52 additions & 0 deletions test/test_asserts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// 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 <stdexcept>

#include "gtest/gtest.h"

#include "rcpputils/asserts.hpp"

TEST(test_asserts, require_throws_if_condition_is_false) {
EXPECT_THROW(rcpputils::require_true(false), std::invalid_argument);
}

TEST(test_asserts, require_does_not_throw_if_condition_is_true) {
EXPECT_NO_THROW(rcpputils::require_true(true));
}

TEST(test_asserts, check_throws_if_condition_is_false) {
EXPECT_THROW(rcpputils::check_true(false), rcpputils::IllegalStateException);
}

TEST(test_asserts, check_does_not_throw_if_condition_is_true) {
EXPECT_NO_THROW(rcpputils::check_true(true));
}

#ifndef NDEBUG
TEST(test_asserts, ros_assert_throws_if_condition_is_false_and_ndebug_not_set) {
EXPECT_THROW(rcpputils::assert_true(false), rcpputils::AssertionException);
}

TEST(test_asserts, ros_assert_does_not_throw_if_condition_is_true_and_ndebug_not_set)
{
EXPECT_NO_THROW(rcpputils::assert_true(true));
}

#else
TEST(test_asserts, ros_assert_does_not_throw_if_ndebug_set) {
EXPECT_NO_THROW(rcpputils::assert_true(false));
EXPECT_NO_THROW(rcpputils::assert_true(true));
}
#endif