Skip to content

Commit

Permalink
Merge pull request #333 from DNKpp/feature/DYN_TIMES
Browse files Browse the repository at this point in the history
add runtime ``TIMES``
  • Loading branch information
rollbear authored Oct 6, 2024
2 parents cb96b7b + c77789f commit 74cf8e7
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 10 deletions.
41 changes: 41 additions & 0 deletions compilation_errors/mixed_limits_with_rt_limits.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Trompeloeil C++ mocking framework
*
* Copyright Björn Fahller
*
* Use, modification and distribution is subject to the
* Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Project home: https://github.com/rollbear/trompeloeil
*/

// pass: Only one RT_TIMES call limit is allowed, but it can express an interval
#include <trompeloeil.hpp>

struct MS
{
MAKE_MOCK0(f, int());
};

int main()
{
MS obj;

#if (TROMPELOEIL_CPLUSPLUS == 201103L)

REQUIRE_CALL_V(obj, f(),
.TIMES(AT_LEAST(1))
.RT_TIMES(AT_MOST(3))
.RETURN(0));

#else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */

REQUIRE_CALL(obj, f())
.TIMES(AT_LEAST(1))
.RT_TIMES(AT_MOST(3))
.RETURN(0);

#endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */
}
41 changes: 41 additions & 0 deletions compilation_errors/mixed_rt_limits_with_limits.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Trompeloeil C++ mocking framework
*
* Copyright Björn Fahller
*
* Use, modification and distribution is subject to the
* Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Project home: https://github.com/rollbear/trompeloeil
*/

// pass: Only one TIMES call limit is allowed, but it can express an interval
#include <trompeloeil.hpp>

struct MS
{
MAKE_MOCK0(f, int());
};

int main()
{
MS obj;

#if (TROMPELOEIL_CPLUSPLUS == 201103L)

REQUIRE_CALL_V(obj, f(),
.RT_TIMES(AT_LEAST(1))
.TIMES(AT_MOST(3))
.RETURN(0));

#else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */

REQUIRE_CALL(obj, f())
.RT_TIMES(AT_LEAST(1))
.TIMES(AT_MOST(3))
.RETURN(0);

#endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */
}
41 changes: 41 additions & 0 deletions compilation_errors/multiple_rt_limits.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Trompeloeil C++ mocking framework
*
* Copyright Björn Fahller
*
* Use, modification and distribution is subject to the
* Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* Project home: https://github.com/rollbear/trompeloeil
*/

// pass: Only one RT_TIMES call limit is allowed, but it can express an interval
#include <trompeloeil.hpp>

struct MS
{
MAKE_MOCK0(f, int());
};

int main()
{
MS obj;

#if (TROMPELOEIL_CPLUSPLUS == 201103L)

REQUIRE_CALL_V(obj, f(),
.RT_TIMES(AT_LEAST(1))
.RT_TIMES(AT_MOST(3))
.RETURN(0));

#else /* (TROMPELOEIL_CPLUSPLUS == 201103L) */

REQUIRE_CALL(obj, f())
.RT_TIMES(AT_LEAST(1))
.RT_TIMES(AT_MOST(3))
.RETURN(0);

#endif /* !(TROMPELOEIL_CPLUSPLUS == 201103L) */
}
5 changes: 3 additions & 2 deletions docs/CookBook.md
Original file line number Diff line number Diff line change
Expand Up @@ -1803,8 +1803,9 @@ control with the Trompeloeil C\+\+14 Mocking Framework](http://playfulprogrammin

By default [**`REQUIRE_CALL(...)`**](reference.md/#REQUIRE_CALL) needs exactly
one matching call, otherwise a violation is reported. Sometimes the need is
for something else. A modifier [**`TIMES(...)`**](reference.md/#TIMES) is used
to change that. You can either specify an exact number of times matching calls
for something else. The modifiers [**`TIMES(...)`**](reference.md/#TIMES-and-RT_TIMES) or
[**`RT_TIMES(...)`**](reference.md/#TIMES-and-RT_TIMES) can be used to change that.
You can either specify an exact number of times matching calls
must be made, or a range of numbers.

Example:
Expand Down
22 changes: 14 additions & 8 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@
- [**`REQUIRE_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#REQUIRE_CALL)
- [**`REQUIRE_DESTRUCTION(`** *mock_object* **`)`**](#REQUIRE_DESTRUCTION)
- [**`RETURN(`** *expr* **`)`**](#RETURN)
- [**`RT_TIMES(`** *limit* **`)`**](#TIMES-and-RT_TIMES)
- [**`SIDE_EFFECT(`** *expr* **`)`**](#SIDE_EFFECT)
- [**`THROW(`** *expr* **`)`**](#THROW)
- [**`TIMES(`** *limit* **`)`**](#TIMES)
- [**`TIMES(`** *limit* **`)`**](#TIMES-and-RT_TIMES)
- [**`WITH(`** *expr* **`)`**](#WITH)
- [Types and Type Templates](#types_and_templates) (alphabetical order)
- [`trompeloeil::deathwatched<T>`](#deathwatched_type)
Expand Down Expand Up @@ -2781,9 +2782,9 @@ Above, **`THROW(...)`** will refer to a copy of the string `what` with the value
See also [**`LR_THROW(...)`**](#LR_THROW) which accesses copies of local objects.
<A name="TIMES"/>
<A name="TIMES-and-RT_TIMES"/>
### **`TIMES(`** *limits* **`)`**
### **`TIMES(`** *limits* **`)`** and **`RT_TIMES(`** *limits* **`)`**
Used in [**`REQUIRE_CALL(...)`**](#REQUIRE_CALL) and
[**`NAMED_REQUIRE_CALL(...)`**](#NAMED_REQUIRE_CALL) to set the limits on
Expand All @@ -2795,15 +2796,19 @@ matching calls required.
*limits* may also be two numbers, describing a range *min-inclusive*,
*max-inclusive*.
If the minimum number of matching calls in not met before the end of the
If the minimum number of matching calls is not met before the end of the
lifetime of the [expectation](#expectation), a violation is reported.
If the maximum number of matching calls is exceeded, a violation is reported.
*limits* must be
[`constexpr`](http://en.cppreference.com/w/cpp/language/constexpr).
The difference between **`TIMES(...)`** and **`RT_TIMES(...)`** is, that the
prior only supports [`constexpr`](http://en.cppreference.com/w/cpp/language/constexpr)
arguments, while the latter is designed to accept also runtime arguements.
If invalid bounds are provided, **`TIMES(...)`** issues a compile-error.
**`RT_TIMES(...)`** will compile successfully, but will raise a ``std::logic_error``
during construction.
**`TIMES(...)`** may only be used once for each
Either a single **`TIMES(...)`** or **`RT_TIMES(...)`** may be used for each
[**`REQUIRE_CALL(..)`**](#REQUIRE_CALL) or
[**`NAMED_REQUIRE_CALL(...)`**](#NAMED_REQUIRE_CALL).
Expand Down Expand Up @@ -2837,7 +2842,8 @@ See also the helpers [**`AT_LEAST(...)`**](#AT_LEAST) and
[**`AT_MOST(...)`**](#AT_MOST).

See also [**`IN_SEQUENCE(...)`**](#IN_SEQUENCE) for information about how
`.TIMES(...)` works together with [**`sequence`**](#sequence_type) objects.
`.TIMES(...)` and `.RT_TIMES(...)` work together with [**`sequence`**](#sequence_type)
objects.

<A name="WITH"/>

Expand Down
43 changes: 43 additions & 0 deletions include/trompeloeil/mock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2507,6 +2507,24 @@ template <typename T>
template <size_t L, size_t H = L>
struct multiplicity { };

struct rt_multiplicity
{
std::size_t low{};
std::size_t high{};

explicit rt_multiplicity(std::size_t _low) noexcept
: low{_low},
high{_low}
{
}

explicit rt_multiplicity(std::size_t _low, std::size_t _high) noexcept
: low{_low},
high{_high}
{
}
};

template <typename R, typename Parent>
struct co_return_injector : Parent
{
Expand Down Expand Up @@ -2802,6 +2820,29 @@ template <typename T>
}
};

struct runtime_times
{
template <
typename Matcher, typename modifier_tag, typename Parent,
bool times_set = Parent::call_limit_set>
static
call_modifier<Matcher, modifier_tag, call_limit_injector<Parent, std::numeric_limits<std::size_t>::max()>>
action(call_modifier<Matcher, modifier_tag, Parent>&& m,
rt_multiplicity bounds)
{
static_assert(!times_set,
"Only one RT_TIMES call limit is allowed, but it can express an interval");

if (bounds.high < bounds.low)
{
throw std::logic_error{"In RT_TIMES the first value must not exceed the second"};
}

m.matcher->sequences->set_limits(bounds.low, bounds.high);
return std::move(m).matcher;
}
};

inline
void
report_unfulfilled(
Expand Down Expand Up @@ -4125,6 +4166,7 @@ template <typename T>


#define TROMPELOEIL_TIMES(...) template action<trompeloeil::times>(::trompeloeil::multiplicity<__VA_ARGS__>{})
#define TROMPELOEIL_RT_TIMES(...) template action<trompeloeil::runtime_times>(::trompeloeil::rt_multiplicity{__VA_ARGS__})
#define TROMPELOEIL_INFINITY_TIMES() TROMPELOEIL_TIMES(0, ~static_cast<size_t>(0))

#define TROMPELOEIL_AT_LEAST(num) num, ~static_cast<size_t>(0)
Expand Down Expand Up @@ -4261,6 +4303,7 @@ template <typename T>
#define THROW TROMPELOEIL_THROW
#define LR_THROW TROMPELOEIL_LR_THROW
#define TIMES TROMPELOEIL_TIMES
#define RT_TIMES TROMPELOEIL_RT_TIMES
#define AT_LEAST TROMPELOEIL_AT_LEAST
#define AT_MOST TROMPELOEIL_AT_MOST

Expand Down
2 changes: 2 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_compile_options(/permissive-)
endif()

add_compile_definitions(NOMINMAX)

endif() # MSVC

if (${CMAKE_CXX_STANDARD} GREATER_EQUAL 20)
Expand Down
Loading

0 comments on commit 74cf8e7

Please sign in to comment.