Slides

Download as pdf or txt
Download as pdf or txt
You are on page 1of 115

Backporting to the Future

Andrew Paxie

Pacific++, 18-19 October 2018

”Ex Ignorantia Ad Sapientiam; Ex Luce Ad Tenebras”

Paxie Backporting to the Future Pacific++ 2018 1 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 2 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 3 / 87


Motivation

Project needed more unit tests.

Catch was the unit testing framework.

What would be the mocking framework?

Paxie Backporting to the Future Pacific++ 2018 4 / 87


Motivation

Project needed more unit tests.

Catch was the unit testing framework.

What would be the mocking framework?

Requirements for a mock object framework:


I Integrates with Catch
I Header-only library
I Portable: desktop and embedded
I Thread-safe
I Supports C++11

Paxie Backporting to the Future Pacific++ 2018 4 / 87


Alternatives

I Google Mock
I Turtle
I HippoMocks
I FakeIt
I Mockator
I Trompeloeil
I Upgrade compiler to C++14
I Avoid mocking frameworks in unit tests

Paxie Backporting to the Future Pacific++ 2018 5 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 6 / 87


Trompeloeil
A header only C++ mocking framework

https://github.com/rollbear/trompeloeil

Björn Fahller Andrew Paxie


(Code Owner) (Contributor)
mailto:[email protected] mailto:[email protected]

https://github.com/rollbear https://github.com/AndrewPaxie

https://playfulprogramming.blogspot.com https://blog.andrew.paxie.org

Paxie Backporting to the Future Pacific++ 2018 7 / 87


Trompe l’oeil

(c) 2006, Lee Snider / Alamy Stock Photo

Paxie Backporting to the Future Pacific++ 2018 8 / 87


Trompe l’oeil
Paintings that create the illusion of a real object or scene...

(c) 2006, Lee Snider / Alamy Stock Photo

Paxie Backporting to the Future Pacific++ 2018 8 / 87


Trompeloeil

Main features:
I Mock functions
I Expectations
I Matchers
I Modifiers

Paxie Backporting to the Future Pacific++ 2018 9 / 87


Trompeloeil

Main features:
I Mock functions
I Expectations
I Matchers
I Modifiers
Other features:
I Sequencing expectations
I Object-lifetime monitoring
I Integration into test framework reporting
I Tracing

Paxie Backporting to the Future Pacific++ 2018 9 / 87


Trompeloeil
Mock classes and functions

Interface
struct Interface
{
virtual void setValue(int v) = 0;
virtual int getValue() const = 0;
};

Paxie Backporting to the Future Pacific++ 2018 10 / 87


Trompeloeil
Mock classes and functions

Interface
struct Interface
{
virtual void setValue(int v) = 0;
virtual int getValue() const = 0;
};

Mock class
struct Mock: Interface
{
MAKE_MOCK1(setValue, void(int), override);
MAKE_CONST_MOCK0(getValue, int(), override);
};

Paxie Backporting to the Future Pacific++ 2018 10 / 87


Trompeloeil
Mock classes and functions

Interface
struct Interface
{
virtual void setValue(int v) = 0;
virtual int getValue() const = 0;
};

Mock class
struct Mock: Interface mock functions ----+
{ |
MAKE_MOCK1(setValue, void(int), override); <-+
MAKE_CONST_MOCK0(getValue, int(), override); <-+
};

Paxie Backporting to the Future Pacific++ 2018 11 / 87


Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup

Mock obj;

REQUIRE_CALL(obj, setValue(lt(7))
.WITH(obj.getValue() == 3)
.RETURN(_1 + 2);
// :::
}
Paxie Backporting to the Future Pacific++ 2018 12 / 87
Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup

Mock obj;

REQUIRE_CALL(obj, setValue(lt(7)) <- expectation


.WITH(obj.getValue() == 3)
.RETURN(_1 + 2);
// :::
}
Paxie Backporting to the Future Pacific++ 2018 13 / 87
Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup
+---------------------- mock object
|
|
Mock obj; |
v
REQUIRE_CALL(obj, setValue(lt(7)) <- expectation
.WITH(obj.getValue() == 3)
.RETURN(_1 + 2);
// :::
}
Paxie Backporting to the Future Pacific++ 2018 14 / 87
Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup
+---------------------- mock object
| +----------------- mock function
| |
Mock obj; | |
v v
REQUIRE_CALL(obj, setValue(lt(7)) <- expectation
.WITH(obj.getValue() == 3)
.RETURN(_1 + 2);
// :::
}
Paxie Backporting to the Future Pacific++ 2018 15 / 87
Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup
+---------------------- mock object
| +----------------- mock function
| | +-------- matcher
Mock obj; | | |
v v v
REQUIRE_CALL(obj, setValue(lt(7)) <- expectation
.WITH(obj.getValue() == 3)
.RETURN(_1 + 2);
// :::
}
Paxie Backporting to the Future Pacific++ 2018 16 / 87
Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup
+---------------------- mock object
| +----------------- mock function
| | +-------- matcher
Mock obj; | | |
v v v
REQUIRE_CALL(obj, setValue(lt(7)) <- expectation
.WITH(obj.getValue() == 3) <- modifier
.RETURN(_1 + 2);
// :::
}
Paxie Backporting to the Future Pacific++ 2018 17 / 87
Trompeloeil
Example
struct Interface struct Mock: Interface
{ {
virtual void setValue(int v) = 0; MAKE_MOCK1(setValue, void(int), override);
virtual int getValue() const = 0; MAKE_CONST_MOCK0(getValue, int(), override);
}; };

TEST_CASE("Unit test", "[Sample]")


{ // Setup
+---------------------- mock object
| +----------------- mock function
| | +-------- matcher
Mock obj; | | |
v v v
REQUIRE_CALL(obj, setValue(lt(7)) <- expectation
.WITH(obj.getValue() == 3) <- modifier
.RETURN(_1 + 2); <- modifier
// :::
}
Paxie Backporting to the Future Pacific++ 2018 18 / 87
Trompeloeil
Expectations

I REQUIRE_CALL(obj, func(params))
I ALLOW_CALL(obj, func(params))
I FORBID_CALL(obj, func(params))

TEST_CASE("Unit test", "[Sample]")


{
// Setup
Mock obj;

REQUIRE_CALL(obj, setValue(ANY(int));
FORBID_CALL(obj, getValue());

// :::
}
Also: Named variants of the above
Paxie Backporting to the Future Pacific++ 2018 19 / 87
Trompeloeil
Matchers

Matchers Notes
_ ANY(type) wildcards
eq(mark) ne(mark) equal, not equal
ge(mark) le(mark) [greater or less] than or equal
gt(mark) lt(mark) greater than, less than
re(mark, ...) regular expression
! negating matcher
* pointer dereference

Paxie Backporting to the Future Pacific++ 2018 20 / 87


Trompeloeil
Modifiers

I WITH(condition)
I SIDE_EFFECT(statement)
I RETURN(expression)
I THROW(expression)

Parameters named using _1 ... _15 placeholder variables

Also: local reference (LR_) versions of the above

Paxie Backporting to the Future Pacific++ 2018 21 / 87


Trompeloeil
Example

// Interface class // System Under Test (SUT) // Unit test


struct IDb struct Engine TEST_CASE(
{ virtual int { "Compute, key exists",
lookup(const char*) = 0; explicit "[Engine]")
}; Engine(IDb& db_) { // Setup
: db(db_) const char* key = "k";
// Production class {} MockDb db;
struct Db: IDb
{ int int REQUIRE_CALL(
lookup(const char*) compute( db,
override; const char* key) lookup(eq(key)))
}; { .RETURN(2);
return
// Mock class
3 * db.lookup(key); Engine sut(db);
struct MockDb final: IDb
} // Exercise
{ // Mock function
int ret =
MAKE_MOCK1(
private: sut.compute(key);
lookup,
IDb& db; // Verify
int(const char*),
}; REQUIRE(ret == 6);
final);
// Teardown
};
}

Paxie Backporting to the Future Pacific++ 2018 22 / 87


Trompeloeil
Example

// Interface class // System Under Test (SUT) // Unit test


struct IDb struct Engine TEST_CASE(
{ virtual int { "Compute, key exists",
lookup(const char*) = 0; explicit "[Engine]")
}; Engine(IDb& db_) { // Setup
: db(db_) const char* key = "k";
// Production class {} MockDb db;
struct Db: IDb
{ int int REQUIRE_CALL(
lookup(const char*) compute( db,
override; const char* key) lookup(eq(key)))
}; { .RETURN(2);
return
// Mock class
3 * db.lookup(key); Engine sut(db);
struct MockDb final: IDb
} // Exercise
{ // Mock function
int ret =
MAKE_MOCK1(
private: sut.compute(key);
lookup,
IDb& db; // Verify
int(const char*),
}; REQUIRE(ret == 6);
final);
// Teardown
};
}

Paxie Backporting to the Future Pacific++ 2018 23 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 24 / 87


Goals

I Provide existing API in C++11 mode


I Expectations
I Matchers
I Modifiers
I Support same compilers, versions
I Preserve C++14 capability

Paxie Backporting to the Future Pacific++ 2018 25 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 26 / 87


C++14 Features Used: Library

constexpr for <tuple> [N3471]


User-defined literals for <chrono> and <string> [N3642]
TransformationTraits Redux, v2 [N3655]
std::make_unique [N3656]
std::integer_sequence [N3658]
std::exchange [N3668]
Dual-range std::equal [N3671]

Paxie Backporting to the Future Pacific++ 2018 27 / 87


C++14 Features Used: Library

constexpr for <tuple> [N3471]


User-defined literals for <chrono> and <string> [N3642]
TransformationTraits Redux, v2 [N3655]
std::make_unique [N3656]
std::integer_sequence [N3658]
std::exchange [N3668]
Dual-range std::equal, [N3671]

Paxie Backporting to the Future Pacific++ 2018 28 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 29 / 87


C++14 Features Used: Language

decltype(auto) [N3638]
Return type deduction for normal functions [N3638]
Generalized lambda captures [N3648]
Generic lambda expressions [N3649]

Paxie Backporting to the Future Pacific++ 2018 30 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 31 / 87


Backporting: Library
Approach

I Define a namespace detail


I Define C++11 versions of the C++14 API.

Paxie Backporting to the Future Pacific++ 2018 32 / 87


Backporting: Library
Approach

I Define a namespace detail


I Define C++11 versions of the C++14 API.
I Call the namespace detail entities.
I std::make_unique becomes detail::make_unique.

Paxie Backporting to the Future Pacific++ 2018 32 / 87


Backporting: Library
Approach

I Define a namespace detail


I Define C++11 versions of the C++14 API.
I Call the namespace detail entities.
I std::make_unique becomes detail::make_unique.
I For C++14 and later, make std:: entities accessible in
namespace detail.
I Maybe a namespace alias: namespace detail = std;
I Maybe using declarations in namespace detail
I Maybe alias templates in namespace detail

Paxie Backporting to the Future Pacific++ 2018 32 / 87


Backporting: Library

<memory> <type_traits> <utility>


I make_unique I conditional_t I exchange

Stephan T. Lavavej [N3656] I decay_t I integer_sequence


I enable_if_t I index_sequence
I remove_pointer_t I make_integer_sequence
I remove_reference_t I make_index_sequence
I index_sequence_for
Walter E. Brown [N3655]
Jeffrey Yasskin [N3668]
Jonathan Wakely [N3658]
Peter Dimov [Boost.mp11]

Paxie Backporting to the Future Pacific++ 2018 33 / 87


Backporting: Library

<memory> <type_traits> <utility>


I make_unique I conditional_t I exchange

Stephan T. Lavavej [N3656] I decay_t I integer_sequence


I enable_if_t I index_sequence
I remove_pointer_t I make_integer_sequence
I remove_reference_t I make_index_sequence
I index_sequence_for
Walter E. Brown [N3655]
Jeffrey Yasskin [N3668]
Jonathan Wakely [N3658]
Peter Dimov [Boost.mp11]

Paxie Backporting to the Future Pacific++ 2018 34 / 87


Backporting: Library

<memory> <type_traits> <utility>


I make_unique I conditional_t I exchange

Stephan T. Lavavej [N3656] I decay_t I integer_sequence


I enable_if_t I index_sequence
I remove_pointer_t I make_integer_sequence
I remove_reference_t I make_index_sequence
I index_sequence_for
Walter E. Brown [N3655]
Jeffrey Yasskin [N3668]
Jonathan Wakely [N3658]
Peter Dimov [Boost.mp11]

Paxie Backporting to the Future Pacific++ 2018 35 / 87


Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 36 / 87


Backporting: Language

I Generic lambda expressions


I Generalized lambda captures
I Return type deduction for normal functions
I decltype(auto)

Paxie Backporting to the Future Pacific++ 2018 37 / 87


Generic Lambda Expressions
Definition

I Lambdas that use auto in their parameter specifications

C++14
[](auto x)
{
return x + x;
}

Paxie Backporting to the Future Pacific++ 2018 38 / 87


Generic Lambda Expressions
Definition

I Lambdas that use auto in their parameter specifications


I In C++14, lambdas may also be variadic

C++14 C++14
[](auto x) [](auto&&... xs)
{ {
return x + x; return sum(
} std::forward<
decltype(xs)
>(xs)...);
}

Paxie Backporting to the Future Pacific++ 2018 38 / 87


Replace Generic Lambdas
Approach

I Replace generic lambda with lambda


I Use a functor (FunctionObject) with function call operator
member template (generic functor )
I Replace functions returning generic lambda with generic
functor

Paxie Backporting to the Future Pacific++ 2018 39 / 87


Replace Generic Lambdas
Example

C++14
[](auto x)
{
return x + x;
}

Paxie Backporting to the Future Pacific++ 2018 40 / 87


Replace Generic Lambdas
Example

C++14 C++11/14
[](auto x) class ClosureType
{ {
return x + x; public:
} template <typename T>
auto
operator()(T x) const
{
return x + x;
}
};

Paxie Backporting to the Future Pacific++ 2018 40 / 87


Replace Generic Lambdas
Trompeloeil

C++14
[](
std::ostream& os,
auto const& value)
{
os << " == ";
print(os, value);
}

Paxie Backporting to the Future Pacific++ 2018 41 / 87


Replace Generic Lambdas
Trompeloeil

C++14 C++11/14
[]( struct equal_printer
std::ostream& os, {
auto const& value) template <typename T>
{ void
os << " == "; operator()(
print(os, value); std::ostream& os,
} T const& value)
const
{
os << " == ";
print(os, value);
}
};

Paxie Backporting to the Future Pacific++ 2018 41 / 87


Generalized Lambda Capture
Definition

An init-capture may specify


I A name of the data member in the closure type
I An expression to initialize that data member

Paxie Backporting to the Future Pacific++ 2018 42 / 87


Generalized Lambda Capture
Definition

An init-capture may specify


I A name of the data member in the closure type
I An expression to initialize that data member

C++14
auto p = std::make_unique<std::vector<int>>();

[ptr = std::move(p)]
{
return ptr->empty();
}

Paxie Backporting to the Future Pacific++ 2018 42 / 87


Replace Generalized Lambda Capture
Approaches

Create a functor like ClosureType


I Declare member variables
I Define constructor to initialize members

Paxie Backporting to the Future Pacific++ 2018 43 / 87


Replace Generalized Lambda Capture
Approaches

Create a functor like ClosureType


I Declare member variables
I Define constructor to initialize members

Use std::bind [Meyers[2], Item 32]


I Move object to be captured into a function object produced
by std::bind
I Give the lambda a reference to the captured object

Paxie Backporting to the Future Pacific++ 2018 43 / 87


Replace Generalized Lambda Capture
Example

C++14
auto p =
std::make_unique<
std::vector<int>>();

[ptr = std::move(p)]
{
return ptr->empty();
}

Paxie Backporting to the Future Pacific++ 2018 44 / 87


Replace Generalized Lambda Capture
Example

C++14 C++11/14
auto p = struct ClosureType
std::make_unique< {
std::vector<int>>(); using T = std::unique_ptr<
std::vector<int>>;
[ptr = std::move(p)]
{ explicit ClosureType(T&& p)
return ptr->empty(); : ptr(std::move(p))
} {}

bool operator()() const


{ return ptr->empty(); }

private:
T ptr;
};

Paxie Backporting to the Future Pacific++ 2018 44 / 87


Replace Generalized Lambda Capture
Trompeloeil

C++14
inline auto
regex_check(std::regex&& re)
{
return [re = std::move(re)](
/* args */ )
-> decltype(std::regex_search(
/* args */ ,
re))
{
return std::regex_search(
/* args */ ,
re);
}
}

Paxie Backporting to the Future Pacific++ 2018 45 / 87


Replace Generalized Lambda Capture
Trompeloeil

C++14 C++11/14
inline auto struct regex_check
regex_check(std::regex&& re) {
{ regex_check(std::regex&& re_)
return [re = std::move(re)]( : re(std::move(re_))
/* args */ ) {}
-> decltype(std::regex_search(
/* args */ , template <typename T>
re)) bool
{ operator()(/* args */ ) const
return std::regex_search( {
/* args */ , return std::regex_search(
re); /* args */ ,
} re);
} }

std::regex_check re;
};

Paxie Backporting to the Future Pacific++ 2018 45 / 87


Return Type Deduction
Definition
Jason Merrill, [N3638]:
Write auto on your function declaration and
have the return type deduced

C++14
auto foo(int var)
{
if (var)
{
return 0;
}
else
{
return var + 1;
}
}
Paxie Backporting to the Future Pacific++ 2018 46 / 87
Replace Return Type Deduction
Approach

Use trailing return type

Paxie Backporting to the Future Pacific++ 2018 47 / 87


Replace Return Type Deduction
Example

C++14
auto
foo(int var)

{
if (var)
{
return 0;
}
else
{
return var + 1;
}
}

Paxie Backporting to the Future Pacific++ 2018 48 / 87


Replace Return Type Deduction
Example

C++14 C++11/14
auto auto
foo(int var) foo(int var)
-> int
{ {
if (var) if (var)
{ {
return 0; return 0;
} }
else else
{ {
return var + 1; return var + 1;
} }
} }

Paxie Backporting to the Future Pacific++ 2018 48 / 87


Replace Return Type Deduction
Trompeloeil

C++14
template <
typename Kind = wildcard

>
auto
re(
std::string s,
match_flag_type match_type)

{
return make_matcher<Kind>(
lambdas::regex_check(
std::regex(s), match_type),
lambdas::regex_printer(),
std::move(s));
}

Paxie Backporting to the Future Pacific++ 2018 49 / 87


Replace Return Type Deduction
Trompeloeil

C++14 C++11/14
template < template <
typename Kind = wildcard typename Kind = wildcard,
typename R = /* omitted */
> >
auto auto
re( re(
std::string s, std::string s,
match_flag_type match_type) match_flag_type match_type)
-> decltype(R)
{ {
return make_matcher<Kind>( return make_matcher<Kind>(
lambdas::regex_check( lambdas::regex_check(
std::regex(s), match_type), std::regex(s), match_type),
lambdas::regex_printer(), lambdas::regex_printer(),
std::move(s)); std::move(s));
} }

Paxie Backporting to the Future Pacific++ 2018 49 / 87


decltype(auto)
Definition

Use the rules of decltype() to deduce a type.

Jason Merrill, [N3638]:


Plain auto never deduces to a reference, and auto&& al-
ways deduces to a reference. [...] forwarding functions
can’t use auto.

Paxie Backporting to the Future Pacific++ 2018 50 / 87


Replace decltype(auto)
Approach

I Replace decltype(auto) with explicit type


I Use auto and trailing return type

Paxie Backporting to the Future Pacific++ 2018 51 / 87


Replace decltype(auto)
Example: Use explicit type

From macro RETURN(...):

C++14
handle_return(
[&](auto& x)
-> decltype(auto)
{
// Define placeholders
// _1 ... _15 from x

return __VA_ARGS__;
})

Paxie Backporting to the Future Pacific++ 2018 52 / 87


Replace decltype(auto)
Example: Use explicit type

From macro RETURN(...):

C++14 C++11/14
handle_return( handle_return(
[&](auto& x) [&](/* ::: */ & x)
-> decltype(auto) -> return_of_t
{ {
// Define placeholders // Define placeholders
// _1 ... _15 from x // _1 ... _15 from x

return __VA_ARGS__; return __VA_ARGS__;


}) })

Paxie Backporting to the Future Pacific++ 2018 52 / 87


Replace decltype(auto)
Example: Use auto and trailing return type
From placeholder naming code (simplified):

C++14
template <
int N,
typename T
>
constexpr
decltype(auto)
arg(
T* t,
std::true_type)

{
return std::get<N-1>(*t);
}

Paxie Backporting to the Future Pacific++ 2018 53 / 87


Replace decltype(auto)
Example: Use auto and trailing return type
From placeholder naming code (simplified):

C++14 C++11/14
template < template <
int N, int N,
typename T typename T
> >
constexpr constexpr
decltype(auto) auto
arg( arg(
T* t, T* t,
std::true_type) std::true_type)
-> decltype(
{ std::get<N-1>(*t))
return std::get<N-1>(*t); {
} return std::get<N-1>(*t);
}
Paxie Backporting to the Future Pacific++ 2018 53 / 87
Outline

Introduction
Motivation
Trompeloeil
Backporting Goals

C++14 Features Used


Library
Language

Backporting to C++11
Library
Language
Issues

Summary

Paxie Backporting to the Future Pacific++ 2018 54 / 87


Issue: Expectation API Changed

Consider the definition of an expectation:

REQUIRE_CALL(...)

RETURN(...)

Paxie Backporting to the Future Pacific++ 2018 55 / 87


Issue: Expectation API Changed

Consider the definition of an expectation:

REQUIRE_CALL(...) an expression yielding an object

RETURN(...)

Paxie Backporting to the Future Pacific++ 2018 55 / 87


Issue: Expectation API Changed

Consider the definition of an expectation:

REQUIRE_CALL(...) an expression yielding an object

. is the member access operator


(cannot overload)

RETURN(...)

Paxie Backporting to the Future Pacific++ 2018 55 / 87


Issue: Expectation API Changed

Consider the definition of an expectation:

REQUIRE_CALL(...) an expression yielding an object

. is the member access operator


(cannot overload)

RETURN(...) yields a member function call


invoked with an argument

Paxie Backporting to the Future Pacific++ 2018 55 / 87


Issue: Expectation API Changed

Consider the definition of an expectation:

REQUIRE_CALL(...) an expression yielding an object

. is the member access operator


(cannot overload)

RETURN(...) yields a member function call


invoked with an argument

The result is still an expression, for more modifiers to be added.

Issue: Have not found a way, so far, to transmit type information


between expectation macros and modifiers.

Paxie Backporting to the Future Pacific++ 2018 55 / 87


Issue: Expectation API Changed

Changed API to allow access to type. A subtle change:

REQUIRE_CALL(obj, foo(_)) REQUIRE_CALL_V(obj, foo(_),


.WITH(_1 == 42); .WITH(_1 == 42));

_V is for ’variadic’

Paxie Backporting to the Future Pacific++ 2018 56 / 87


Issue: Expectation API Changed

Changed API to allow access to type. A subtle change:

REQUIRE_CALL(obj, foo(_)) REQUIRE_CALL_V(obj, foo(_),


.WITH(_1 == 42); .WITH(_1 == 42));

_V is for ’variadic’

I API didn’t change once but three times.


I Two APIs are available in C++14 mode or later.
I Can incrementally transform from C++11 API to C++14 API
in unit tests.

Paxie Backporting to the Future Pacific++ 2018 56 / 87


Issue: RETURN(...) Macro doesn’t Quite Work

I C++14 API provides type check of expression and gives


helpful error messages, via static_assert.
I C++11 API performs implicit conversion of __VA_ARGS__ to
return_of_t before type checking.

Result: Less helpful compiler error messages in C++11 mode.

Paxie Backporting to the Future Pacific++ 2018 57 / 87


Issue: Compilers Have Defects Too

Other limitations because of compiler defects:

I <regex> partial implementation (PR61582)


I Ambiguous conversion operator error
I negating matcher (!)
I wildcard matcher (_)
I <tuple> broken (PR61947)

These just for GCC 4.8.3.

Paxie Backporting to the Future Pacific++ 2018 58 / 87


Backporting Goals
Review

I Provide existing API in C++11 mode


I Expectations
I Matchers
I Modifiers
I Support same compilers, versions
I Preserve C++14 capability

Paxie Backporting to the Future Pacific++ 2018 59 / 87


Backporting Goals
Review

I Provide existing API in C++11 mode


I Expectations 7
I Matchers
I Modifiers
I Support same compilers, versions
I Preserve C++14 capability

Paxie Backporting to the Future Pacific++ 2018 59 / 87


Backporting Goals
Review

I Provide existing API in C++11 mode


I Expectations 7
I Matchers 3/7
I Modifiers
I Support same compilers, versions
I Preserve C++14 capability

Paxie Backporting to the Future Pacific++ 2018 59 / 87


Backporting Goals
Review

I Provide existing API in C++11 mode


I Expectations 7
I Matchers 3/7
I Modifiers 3/7
I Support same compilers, versions
I Preserve C++14 capability

Paxie Backporting to the Future Pacific++ 2018 59 / 87


Backporting Goals
Review

I Provide existing API in C++11 mode


I Expectations 7
I Matchers 3/7
I Modifiers 3/7
I Support same compilers, versions 3
I Preserve C++14 capability

Paxie Backporting to the Future Pacific++ 2018 59 / 87


Backporting Goals
Review

I Provide existing API in C++11 mode


I Expectations 7
I Matchers 3/7
I Modifiers 3/7
I Support same compilers, versions 3
I Preserve C++14 capability 3

Paxie Backporting to the Future Pacific++ 2018 59 / 87


Backporting to the Future

How do I port a C++11 program to C++14?

Paxie Backporting to the Future Pacific++ 2018 60 / 87


Backporting to the Future

How do I port a C++11 program to C++14?

Reverse the direction of these code transformations


and
Use library and and language features that are also part of C++14
(see Appendix)

Paxie Backporting to the Future Pacific++ 2018 60 / 87


Trompeloeil

https://github.com/rollbear/trompeloeil

Björn Fahller Andrew Paxie


(Code Owner) (Contributor)
mailto:[email protected] mailto:[email protected]

https://github.com/rollbear https://github.com/AndrewPaxie

https://playfulprogramming.blogspot.com https://blog.andrew.paxie.org

Paxie Backporting to the Future Pacific++ 2018 61 / 87


Appendix: Unused Features from C++14
Library (1)

constexpr for <complex> [N3302]


Making operator functors greater<> [N3421]
std::result_of and SFINAE [N3462]
constexpr for <chrono> [N3469]
constexpr for <array> [N3470]
Improved std::integral_constant [N3545]

Paxie Backporting to the Future Pacific++ 2018 62 / 87


Appendix: Unused Features from C++14
Library (2)

Null forward iterators [N3644]


std::quoted [N3654]
Heterogeneous associative lookup [N3657]
Shared locking in C++ [N3659]
Fixing constexpr member functions without const [N3669]
std::get<T> [N3670]

Paxie Backporting to the Future Pacific++ 2018 63 / 87


Appendix: Unused Features from C++14
Language

Binary literals [N3472]


Variable templates [N3651]
Extended constexpr [N3652]
Member initializers and aggregates [N3653]
[[deprecated]] attribute [N3760]
Single quote as digit separator [N3781]

Paxie Backporting to the Future Pacific++ 2018 64 / 87


Appendix: Unused Features from C++14
Miscellaneous

Tweak to certain contextual conversions [N3323]


Clarifying memory allocation [N3664]
Sized deallocation [N3778]

Paxie Backporting to the Future Pacific++ 2018 65 / 87


References
Motivation

Catch,
Available: https://github.com/catchorg/catch2
Accessed: 13 October 2018

Paxie Backporting to the Future Pacific++ 2018 66 / 87


References
Alternatives (1)

Google Mock
Available: https://github.com/google/googletest
Accessed: 10 October 2018
Turtle
Available: https://github.com/mat007/turtle
Accessed: 10 October 2018
HippoMocks
Available: http://hippomocks.com/Main_Page
Available: https://github.com/dascandy/hippomocks
Accessed: 10 October 2018

Paxie Backporting to the Future Pacific++ 2018 67 / 87


References
Alternatives (2)

FakeIt
Available: https://github.com/eranpeer/FakeIt
Accessed: 10 October 2018
Mockator
Available: https://www.cevelop.com/
Accessed: 10 October 2018
Trompeloeil
Available: https://github.com/rollbear/trompeloeil
Accessed: 15 October 2018

Paxie Backporting to the Future Pacific++ 2018 68 / 87


References
Trompe l’oeil

Trompe l’oeil definition


Available: https:
//www.tate.org.uk/art/art-terms/t/trompe-loeil
Accessed: 13 October 2018

Paxie Backporting to the Future Pacific++ 2018 69 / 87


References
C++14 Features Used: Library (1)

Benjamin Kosnik and Daniel Krügler,


“Constexpr Library Additions: utilities, v3,” N3471, 18
October 2012.
Available: http://wg21.link/n3471
Accessed: 22 September 2018
Peter Sommerlad,
“User-defined Literals for Standard Library Types (part 1 -
version 4),” N3642, 18 April 2013.
Available: http://wg21.link/n3642
Accessed: 22 September 2018
Walter E. Brown,
“TransformationTraits Redux, v2,” N3655, 18 April 2013.
Available: http://wg21.link/n3655
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 70 / 87


References
C++14 Features Used: Library (2)

Jonathan Wakely,
“Compile-time integer sequences,” N3658, 18 April 2013.
Available: http://wg21.link/n3658
Accessed: 22 September 2018
Stephan T. Lavavej,
“make unique (Revision 1),” N3656, 18 April 2013.
Available: http://wg21.link/n3656
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 71 / 87


References
C++14 Features Used: Library (3)

Jeffrey Yasskin,
“exchange() utility function, revision 3,” N3668, 19 April
2013.
Available: http://wg21.link/n3668
Accessed: 22 September 2018
Mike Spertus and Attila Pall,
“Making non-modifying sequence operations more robust:
Revision 2,” N3671, 19 April 2013.
Available: http://wg21.link/n3671
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 72 / 87


References
C++14 Features Used: Language (1)

Walter E. Brown,
“A Proposal to Tweak Certain C++ Contextual Conversions,
v3,” N3323, 8 December 2012.
Available: http://wg21.link/n3323
Accessed: 22 September 2018
Jason Merrill,
“Return type deduction for normal functions,” N3638, 17 April
2013.
Available: http://wg21.link/n3638
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 73 / 87


References
C++14 Features Used: Language (2)

Daveed Vandevoorde and Ville Voutilainen,


“Wording Changes for Generalized Lambda-capture,” N3648,
17 April 2013.
Available: http://wg21.link/n3648
Accessed: 22 September 2018
Faisal Vali, Herb Sutter, and Dave Abrahams,
“Generic (Polymorphic) Lambda Expressions (Revision 3),”
N3649, 19 April 2013.
Available: http://wg21.link/n3649
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 74 / 87


References
Generic lambdas

[Meyers[2], Item 33]


“Use decltype on auto&& parameters to std::forward
them,” pp. 229-32.
cppreference.com,
“Lambda expressions,” last modified 19 September 2018.
Available:
https://en.cppreference.com/w/cpp/language/lambda
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 75 / 87


References
Generalized lambda capture

[Meyers[2], Item 32]


“Use init capture to move objects into closures,” pp. 224-29.

Paxie Backporting to the Future Pacific++ 2018 76 / 87


References
Issue: Compilers Have Defects Too

GCC Bugzilla,
“Bug 61582 - C++11 regex memory corruption,” 23 June
2014.
Available:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61582
Accessed: 9 November 2017
GCC Bugzilla,
“Bug 61947 - [4.8/4.9 Regression] Ambiguous calls when
constructing std::tuple,” 29 July 2014.
Available:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61947
Accessed: 8 November 2017

Paxie Backporting to the Future Pacific++ 2018 77 / 87


References
Unused Features from C++14: Library (1)(a)

Benjamin Kosnik, Gabriel Dos Reis, and Daniel Krügler,


“Constexpr Library Additions: complex, v2,” N3302, 20
August 2011.
Available: http://wg21.link/n3302
Accessed: 22 September 2018
Stephan T. Lavavej,
“Making Operator Functors greater<>,” N3421, 20
September 2012.
Available: http://wg21.link/n3421
Accessed: 22 September 2018
Eric Niebler, Daniel Walker, and Joel de Guzman,
“std::result_of and SFINAE,” N3462, 18 October 2012.
Available: http://wg21.link/n3462
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 78 / 87


References
Unused Features from C++14: Library (1)(b)

Benjamin Kosnik and Daniel Krügler,


“Constexpr Library Additions: chrono, v3,” N3469, 18 October
2012.
Available: http://wg21.link/n3469
Accessed: 22 September 2018
Benjamin Kosnik and Daniel Krügler,
“Constexpr Library Additions: containers, v2,” N3470, 18
October 2012.
Available: http://wg21.link/n3470
Accessed: 22 September 2018
Walter E. Brown,
“An Incremental Improvement to integral_constant,”
N3545, 12 March 2013.
Available: http://wg21.link/n3545
Accessed: 22 September 2018
Paxie Backporting to the Future Pacific++ 2018 79 / 87
References
Unused Features from C++14: Library (2)(a)

Alan Talbot,
“Null forward iterators,” N3644, 18 April 2013.
Available: http://wg21.link/n3644
Accessed: 22 September 2018
Berman Dawes,
“Quoted Strings Library Proposal (Revision 2),” N3654, 19
April 2013.
Available: http://wg21.link/n3654
Accessed: 22 September 2018
Jonathan Wakely, Stephan T. Lavavej, and Joaquı́n Mª López
Muñoz,
“Adding heterogeneous comparison lookup to associative
containers (rev 4),” N3657, 19 March 2013.
Available: http://wg21.link/n3657
Accessed: 22 September 2018
Paxie Backporting to the Future Pacific++ 2018 80 / 87
References
Unused Features from C++14: Library (2)(b)

Howard Hinnant, Detlef Vollmann, and Hans Boehm,


“Shared locking in C++, Revision 2,” N3659, 19 April 2013.
Available: http://wg21.link/n3659
Accessed: 22 September 2018
Nicolai Josuttis,
“Fixing constexpr member functions without const,” N3669,
19 April 2013.
Available: http://wg21.link/n3669
Accessed: 22 September 2018
Mike Spertus,
“Wording for Addressing Tuples by Type: Revision 2,” N3670,
19 April 2013.
Available: http://wg21.link/n3670
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 81 / 87


References
Unused Features from C++14: Language (1)

James Dennett,
“Binary Literals in the C++ Core Language,” N3472, 19
October 2012.
Available: http://wg21.link/n3472
Accessed: 22 September 2018
Gabriel Dos Reis,
“Variable Templates (Revision 1),” N3651, 19 April 2013.
Available: http://wg21.link/n3651
Accessed: 22 September 2018
Richard Smith,
“Relaxing constraints on constexpr functions, constexpr
member functions and implicit const,” N3652, 18 April 2013.
Available: http://wg21.link/n3652
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 82 / 87


References
Unused Features from C++14: Language (2)

Ville Voutilainen and Richard Smith,


“Member initializers and aggregates,” N3653, 17 April 2013.
Available: http://wg21.link/n3653
Accessed: 22 September 2018
Alberto Ganesh Barbati,
“[[deprecated]] attribute,” N3760, 1 September 2013.
Available: http://wg21.link/n3760
Accessed: 22 September 2018
Lawrence Crowl, Richard Smith, Jeff Snyder, and Daveed
Vandevoorde,
“Single-Quotation-Mark as a Digit Separator,” N3781, 25
September 2013.
Available: http://wg21.link/n3781
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 83 / 87


References
Unused Features from C++14: Miscellaneous

Lawrence Crowl, Chandler Carruth, and Richard Smith,


“Clarifying Memory Allocation,” N3664, 19 April 2013.
Available: http://wg21.link/n3664
Accessed: 22 September 2018
Lawrence Crowl,
“C++ Sized Deallocation,” N3778, 27 September 2013.
Available: http://wg21.link/n3778
Accessed: 22 September 2018

Paxie Backporting to the Future Pacific++ 2018 84 / 87


References
Other

Gerard Meszaros,
“xUnit Test Patterns: Refactoring Test Code,”
Addison-Wesley, Upper Saddle River, NJ, 2007.
Scott Meyers,
“Effective Modern C++,” O’Reilly Media, Inc., Sebastopol,
CA, 2015.
Scott Meyers,
“Modification History and Errata List for ’Effective Modern
C++’,” last updated 18 May 2018.
Available: https:
//www.aristeia.com/BookErrata/emc++-errata.html
Accessed: 23 September 2018

Paxie Backporting to the Future Pacific++ 2018 85 / 87


Acknowledgements
Special mention is given to the following individuals,
C++ Meetup Group Presentation Library Testers
26 September 2018 27 September 2018

Biswajit Banerjee Benjamin Deeming Ben Morelli


Christian Blume Jacqueline Lewis Bill McCroskey
Nick Sarten Ralf Haeusler Cooper Li
Paul Leslie Saeid Shahosseini Greg Sumner
Shane Powell Edward Peek
Toby Allsopp Mike Hiatt
Tom Isaacson Sam McArdle
Shawn Crawford
Sian Phillips
Toby Collett
Vadim Fuchs
Walt Conley
Will Sember
Thank you all for your valuable feedback.
Paxie Backporting to the Future Pacific++ 2018 86 / 87
Image Credit

Photo by: Lee Snider / Alamy Stock Photo


Date taken: 22 July 2006
Image ID: E9RNMX
Available: https://www.alamy.com

Original wall mural


by Richard Haas, 1978,
depicting the Brooklyn Bridge
and 19th century storefronts
painted on a windowless warehouse
on Peck Slip.

Paxie Backporting to the Future Pacific++ 2018 87 / 87

You might also like