2020-01-20 10:45:53 -06:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
|
|
/*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2020-04-18 03:39:50 -05:00
|
|
|
#pragma once
|
2020-01-20 10:45:53 -06:00
|
|
|
|
2021-09-10 09:16:02 -05:00
|
|
|
#include <vector>
|
|
|
|
#include <ostream>
|
2020-12-20 17:35:31 -06:00
|
|
|
|
2021-09-10 09:16:02 -05:00
|
|
|
#include "testlog.hpp"
|
2020-01-20 10:45:53 -06:00
|
|
|
#include <assert.h>
|
2023-01-29 08:54:23 -06:00
|
|
|
|
|
|
|
#include <cppunit/TestAssert.h>
|
2020-01-20 10:45:53 -06:00
|
|
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const std::vector<char>& v)
|
|
|
|
{
|
2020-11-15 11:03:45 -06:00
|
|
|
const std::size_t size = v.size();
|
2020-01-20 10:45:53 -06:00
|
|
|
if (size <= 32)
|
|
|
|
os << std::string(v.data(), size);
|
|
|
|
else
|
|
|
|
os << std::string(v.data(), 32) << "...";
|
|
|
|
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
|
2021-09-19 10:03:40 -05:00
|
|
|
template <typename T, typename U>
|
2022-11-17 18:25:39 -06:00
|
|
|
inline std::string lokFormatAssertEq(const char* expectedName, const T& expected,
|
|
|
|
const char* actualName, const U& actual)
|
2021-09-19 10:03:40 -05:00
|
|
|
{
|
|
|
|
std::ostringstream oss;
|
2022-11-17 18:25:39 -06:00
|
|
|
oss << "Expected " << actualName << " [" << std::boolalpha << (actual)
|
|
|
|
<< "] == " << expectedName << " [" << (expected) << ']';
|
2021-09-19 10:03:40 -05:00
|
|
|
return oss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
2022-11-17 18:25:39 -06:00
|
|
|
std::string inline lokFormatAssertEq(const char* expected_name, const std::string& expected,
|
|
|
|
const char* actual_name, const std::string& actual)
|
2021-09-19 10:03:40 -05:00
|
|
|
{
|
|
|
|
std::ostringstream oss;
|
2023-01-19 19:18:33 -06:00
|
|
|
oss << "Expected (" << expected_name << "): [";
|
|
|
|
const std::string expected_prefix = oss.str();
|
|
|
|
oss.str("");
|
|
|
|
|
|
|
|
oss << "Actual (" << actual_name << "): [";
|
|
|
|
const std::string actual_prefix = oss.str();
|
|
|
|
oss.str("");
|
|
|
|
|
2021-09-19 10:03:40 -05:00
|
|
|
oss << '\n';
|
2023-01-19 19:18:33 -06:00
|
|
|
oss << expected_prefix << expected << "]\n";
|
|
|
|
oss << actual_prefix << actual << "]\n";
|
|
|
|
|
|
|
|
auto space_count = std::max(expected_prefix.size(), actual_prefix.size());
|
|
|
|
while (--space_count > 0)
|
|
|
|
{
|
|
|
|
oss << ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
oss << '[';
|
2021-09-19 10:03:40 -05:00
|
|
|
|
|
|
|
const auto minSize = std::min(expected.size(), actual.size());
|
|
|
|
for (std::size_t i = 0; i < minSize; ++i)
|
|
|
|
{
|
|
|
|
oss << (expected[i] == actual[i] ? ' ' : '^');
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto maxSize = std::max(expected.size(), actual.size());
|
|
|
|
for (std::size_t i = minSize; i < maxSize; ++i)
|
|
|
|
{
|
|
|
|
oss << '^';
|
|
|
|
}
|
|
|
|
|
|
|
|
oss << "]\n";
|
|
|
|
|
|
|
|
return oss.str();
|
|
|
|
}
|
|
|
|
|
2023-10-08 17:24:42 -05:00
|
|
|
#if defined(LOK_ABORT_ON_ASSERTION) || defined(__COVERITY__)
|
2020-01-20 10:45:53 -06:00
|
|
|
#define LOK_ASSERT_IMPL(X) assert(X);
|
|
|
|
#else
|
|
|
|
#define LOK_ASSERT_IMPL(X)
|
2020-04-16 06:14:23 -05:00
|
|
|
#endif //LOK_ABORT_ON_ASSERTION
|
2020-01-20 10:45:53 -06:00
|
|
|
|
2021-11-12 08:42:16 -06:00
|
|
|
// When enabled, assertions that pass will be logged.
|
|
|
|
// configure with --enable-logging-test-assert
|
|
|
|
#if LOK_LOG_ASSERTIONS
|
|
|
|
#define LOK_TRACE(X) \
|
|
|
|
do \
|
|
|
|
{ \
|
2022-02-16 16:22:18 -06:00
|
|
|
TST_LOG(X); \
|
2021-11-12 08:42:16 -06:00
|
|
|
} while (false)
|
|
|
|
#else
|
|
|
|
#define LOK_TRACE(X) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
} while (false)
|
|
|
|
#endif
|
|
|
|
|
2022-12-11 15:07:30 -06:00
|
|
|
namespace test
|
|
|
|
{
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
/// For tests that don't have a 'failed' member.
|
|
|
|
inline constexpr bool failed() { return false; }
|
|
|
|
} // namespace detail
|
|
|
|
} // namespace test
|
|
|
|
|
2023-10-16 03:37:34 -05:00
|
|
|
#if !defined(__COVERITY__)
|
|
|
|
#define LOK_ASSERT_MESSAGE_PRIOR_FAILURE failed()
|
|
|
|
#else
|
|
|
|
#define LOK_ASSERT_MESSAGE_PRIOR_FAILURE false
|
|
|
|
#endif
|
|
|
|
|
2022-02-10 17:12:43 -06:00
|
|
|
/// Assert the truth of a condition, with a custom message.
|
2022-12-10 10:28:29 -06:00
|
|
|
#define LOK_ASSERT_MESSAGE_IMPL(message, condition, silent) \
|
2020-01-20 10:45:53 -06:00
|
|
|
do \
|
|
|
|
{ \
|
2022-12-11 15:07:30 -06:00
|
|
|
using namespace test::detail; \
|
2023-10-16 03:37:34 -05:00
|
|
|
if (!LOK_ASSERT_MESSAGE_PRIOR_FAILURE) \
|
2022-02-10 17:12:43 -06:00
|
|
|
{ \
|
2023-10-08 17:24:42 -05:00
|
|
|
if (!(condition)) \
|
2022-12-11 15:07:30 -06:00
|
|
|
{ \
|
|
|
|
std::ostringstream oss##__LINE__; \
|
|
|
|
oss##__LINE__ << message; \
|
|
|
|
const auto msg##__LINE__ = oss##__LINE__.str(); \
|
|
|
|
TST_LOG("ERROR: Assertion failure: " \
|
|
|
|
<< (msg##__LINE__.empty() ? "" : msg##__LINE__ + ". ") \
|
|
|
|
<< "Condition: " << (#condition)); \
|
2023-10-08 17:24:42 -05:00
|
|
|
LOK_ASSERT_IMPL(!#condition); /* NOLINT(misc-static-assert) */ \
|
2022-12-11 15:07:30 -06:00
|
|
|
CPPUNIT_ASSERT_MESSAGE((msg##__LINE__), condition); \
|
|
|
|
} \
|
|
|
|
else if (!silent) \
|
|
|
|
{ \
|
|
|
|
LOK_TRACE("PASS: " << (#condition) << " [true]"); \
|
|
|
|
} \
|
2022-02-10 17:12:43 -06:00
|
|
|
} \
|
2020-01-20 10:45:53 -06:00
|
|
|
} while (false)
|
|
|
|
|
2022-12-10 10:28:29 -06:00
|
|
|
/// Assert the truth of a condition, with a custom message, logging on success.
|
|
|
|
#define LOK_ASSERT_MESSAGE(message, condition) LOK_ASSERT_MESSAGE_IMPL(message, condition, false)
|
|
|
|
|
|
|
|
/// Assert the truth of a condition, with a custom message, without logging on success.
|
|
|
|
#define LOK_ASSERT_MESSAGE_SILENT(message, condition) \
|
|
|
|
LOK_ASSERT_MESSAGE_IMPL(message, condition, true)
|
|
|
|
|
|
|
|
/// Assert the truth of a condition, logging on success.
|
|
|
|
#define LOK_ASSERT(condition) LOK_ASSERT_MESSAGE_IMPL("", condition, false)
|
|
|
|
|
|
|
|
/// Assert the truth of a condition without logging on success.
|
|
|
|
#define LOK_ASSERT_SILENT(condition) LOK_ASSERT_MESSAGE_IMPL("", condition, true)
|
2022-02-10 17:12:43 -06:00
|
|
|
|
2021-11-09 18:03:21 -06:00
|
|
|
/// Assert the equality of two expressions. WARNING: Multiple evaluations!
|
|
|
|
/// Captures full expressions, but only meaningful when they have no side-effects when evaluated.
|
|
|
|
#define LOK_ASSERT_EQUAL_UNSAFE(expected, actual) \
|
2022-11-17 18:25:39 -06:00
|
|
|
LOK_ASSERT_EQUAL_MESSAGE_UNSAFE("", #expected, expected, #actual, actual)
|
2020-01-20 10:45:53 -06:00
|
|
|
|
2021-11-09 18:03:21 -06:00
|
|
|
/// Assert the equality of two expressions with a custom message. WARNING: Multiple evaluations!
|
|
|
|
/// Captures full expressions, but only meaningful when they have no side-effects when evaluated.
|
2022-11-17 18:25:39 -06:00
|
|
|
#define LOK_ASSERT_EQUAL_MESSAGE_UNSAFE(message, expected_name, expected, actual_name, actual) \
|
2020-01-20 10:45:53 -06:00
|
|
|
do \
|
|
|
|
{ \
|
2022-12-11 15:07:30 -06:00
|
|
|
using namespace test::detail; \
|
|
|
|
if (!failed() && !((expected) == (actual))) \
|
2020-01-20 10:45:53 -06:00
|
|
|
{ \
|
2021-03-15 15:35:39 -05:00
|
|
|
std::ostringstream oss##__LINE__; \
|
|
|
|
oss##__LINE__ << message; \
|
|
|
|
const auto msg##__LINE__ = oss##__LINE__.str(); \
|
2022-02-16 16:22:18 -06:00
|
|
|
TST_LOG("ERROR: Assertion failure: " \
|
|
|
|
<< (msg##__LINE__.empty() ? "" : msg##__LINE__ + ' ') \
|
2022-11-17 18:25:39 -06:00
|
|
|
<< lokFormatAssertEq(expected_name, expected, actual_name, actual)); \
|
2021-04-05 09:59:33 -05:00
|
|
|
LOK_ASSERT_IMPL((expected) == (actual)); \
|
2021-03-15 15:35:39 -05:00
|
|
|
CPPUNIT_ASSERT_EQUAL_MESSAGE(msg##__LINE__, (expected), (actual)); \
|
2020-01-20 10:45:53 -06:00
|
|
|
} \
|
|
|
|
} while (false)
|
|
|
|
|
2021-11-09 18:03:21 -06:00
|
|
|
/// Assert the equality of two expressions, and a custom message, with guaranteed single evaluation.
|
|
|
|
#define LOK_ASSERT_EQUAL_MESSAGE(MSG, EXP, ACT) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
auto&& exp##__LINE__ = EXP; \
|
|
|
|
auto&& act##__LINE__ = ACT; \
|
2022-02-10 17:12:43 -06:00
|
|
|
if (!(exp##__LINE__ == act##__LINE__)) \
|
|
|
|
{ \
|
2022-11-17 18:25:39 -06:00
|
|
|
LOK_ASSERT_EQUAL_MESSAGE_UNSAFE(MSG, #EXP, exp##__LINE__, #ACT, act##__LINE__); \
|
2022-02-10 17:12:43 -06:00
|
|
|
} \
|
|
|
|
else \
|
|
|
|
{ \
|
|
|
|
LOK_TRACE("PASS: " << #EXP << " == " << #ACT << " == [" << act##__LINE__ << ']'); \
|
|
|
|
} \
|
2021-11-09 18:03:21 -06:00
|
|
|
} while (false)
|
|
|
|
|
|
|
|
/// Assert the equality of two expressions with guarantees of single evaluation.
|
2022-02-10 17:12:43 -06:00
|
|
|
#define LOK_ASSERT_EQUAL(EXP, ACT) LOK_ASSERT_EQUAL_MESSAGE((#EXP) << " != " << (#ACT), EXP, ACT)
|
2021-11-09 18:03:21 -06:00
|
|
|
|
|
|
|
/// Assert the equality of two expressions with guarantees of single evaluation.
|
|
|
|
#define LOK_ASSERT_EQUAL_STR(EXP, ACT) \
|
2022-02-10 17:12:43 -06:00
|
|
|
LOK_ASSERT_EQUAL_MESSAGE((#EXP) << " != " << (#ACT), Util::toString(EXP), Util::toString(ACT))
|
2020-01-20 10:45:53 -06:00
|
|
|
|
|
|
|
#define LOK_ASSERT_FAIL(message) \
|
|
|
|
do \
|
|
|
|
{ \
|
2022-02-16 16:22:18 -06:00
|
|
|
TST_LOG("ERROR: Forced failure: " << (message)); \
|
2022-11-16 19:30:35 -06:00
|
|
|
LOK_ASSERT_IMPL(!"Forced failure: " #message); /* NOLINT(misc-static-assert) */ \
|
2020-01-20 10:45:53 -06:00
|
|
|
CPPUNIT_FAIL((message)); \
|
|
|
|
} while (false)
|