Test

API reference

Short, example driven introduction to basic rili test framework features

#include <regex>
#include <rili/Test.hpp>
#include <string>

int main(int /*argc*/, char** /*argv*/) {
    rili::test::runner::run([](std::string const& /*fixture*/, std::string const& scenario) {
        if (std::regex_match(scenario, std::regex("(SKIP_)(.*)"))) {
            return rili::test::runner::FilteringResult::Skip;
        } else if (std::regex_match(scenario, std::regex("(DISABLE_)(.*)"))) {
            return rili::test::runner::FilteringResult::Disable;
        } else {
            return rili::test::runner::FilteringResult::Run;
        }
    });
    return 0;
}

As you see there is used simply rili::test::runner::run(). This function return test result (true, if all pass, false in case of any failure). Additionally is defined custom "filtering function" which in example mark test:

Note:

If you not need filtering function at all you can use rili::test::runner::run() without parameter - then all your test will be implicit marked as FilteringResult::Run if test name not starts with DISABLED_(in this situation it will be marked FilteringResult::Disable) This function will be called for each registered test, before it will be executed (and even constructed!).

#include <iostream>
#include <rili/Test.hpp>
#include <rili/test/Config.hpp>
#include <stdexcept>
#include "Assert.hpp"

/*
 * simple test without fixture
 */
TEST(WithoutFixture, emptyTest) { std::cout << "WithoutFixture: emptyTest" << std::endl; }

#ifdef RILI_TEST_WITH_EXCEPTIONS
/*
 *  Tests can throw exceptions
 */
TEST(WithoutFixture, throwingTest1) {
    std::cout << "WithoutFixture: throwingTest" << std::endl;
    throw std::runtime_error("Ouch!");
}

TEST(WithoutFixture, throwingTest2) {
    std::cout << "WithoutFixture: throwingTest" << std::endl;
    throw 5;
}
#endif

/*
 * fixture which show that, first test execution sequence is ctor()->before()->test_body()->after()->dctor()
 */
class WithFixture : public rili::test::TestBaseFixture {
 public:
    WithFixture() : rili::test::TestBaseFixture() { std::cout << "WithFixture: ctor" << std::endl; }
    virtual ~WithFixture() { std::cout << "WithFixture: dctor" << std::endl; }
    void before() override { std::cout << "WithFixture: before" << std::endl; }
    void after() override { std::cout << "WithFixture: after" << std::endl; }
};

class BeforeFailFixture : public rili::test::TestBaseFixture {
 public:
    BeforeFailFixture() : rili::test::TestBaseFixture() {}
    virtual ~BeforeFailFixture() {}
    void before() override { EXPECT_EQ(1, 2); }
};

TEST_F(BeforeFailFixture, ShouldNotRunTestBody) { EXAMPLES_ASSERT(false); }

/*
 * first test which use WithFixture
 */
TEST_F(WithFixture, emptyTest1) { std::cout << "WithFixture: emptyTest1" << std::endl; }

/*
 * second test which use WithFixture. As you see fixture class can be shared, however test object instance not.
 */
TEST_F(WithFixture, emptyTest2) { std::cout << "WithFixture: emptyTest2" << std::endl; }

#ifdef RILI_TEST_WITH_EXCEPTIONS
/*
 * Bellow examples shows what will happen if fixture Ctor(), before() or after() will throw.
 */
class WithThrowingCtor : public rili::test::TestBaseFixture {
 public:
    WithThrowingCtor() : rili::test::TestBaseFixture() {
        std::cout << "WithThrowingCtor: ctor" << std::endl;
        throw std::runtime_error("some exception");
    }
    virtual ~WithThrowingCtor() { std::cout << "WithThrowingCtor: dctor" << std::endl; }
    void before() override { std::cout << "WithThrowingCtor: before" << std::endl; }
    void after() override { std::cout << "WithThrowingCtor: after" << std::endl; }
};
TEST_F(WithThrowingCtor, emptyTest) { std::cout << "WithThrowingCtor: emptyTest" << std::endl; }

class WithThrowingBefore : public rili::test::TestBaseFixture {
 public:
    WithThrowingBefore() : rili::test::TestBaseFixture() { std::cout << "WithThrowingBefore: ctor" << std::endl; }
    virtual ~WithThrowingBefore() { std::cout << "WithThrowingBefore: dctor" << std::endl; }
    void before() override {
        std::cout << "WithThrowingBefore: before" << std::endl;
        throw std::runtime_error("some exception");
    }
    void after() override { std::cout << "WithThrowingBefore: after" << std::endl; }
};
TEST_F(WithThrowingBefore, emptyTest) { std::cout << "WithThrowingBefore: emptyTest" << std::endl; }

class WithThrowingAfter : public rili::test::TestBaseFixture {
 public:
    WithThrowingAfter() : rili::test::TestBaseFixture() { std::cout << "WithThrowingAfter: ctor" << std::endl; }
    virtual ~WithThrowingAfter() { std::cout << "WithThrowingAfter: dctor" << std::endl; }
    void before() override { std::cout << "WithThrowingAfter: before" << std::endl; }
    void after() override {
        std::cout << "WithThrowingAfter: after" << std::endl;
        throw std::runtime_error("some exception");
    }
};
TEST_F(WithThrowingAfter, emptyTest) { std::cout << "WithThrowingAfter: emptyTest" << std::endl; }
#endif
Note:

Fixture public members are visible in test scope, so you can define there test helpers, constants shared between tests, perform environment preparation etc.

Now, when we know how to run tests and define scenario pleceholders we should learn how to use expectations.

As rili test framework is strongly influenced by gtest semantics, most of gtest like expectations should work similarly(except mocks and throw expectations). If you know gtest expectations you know also rili test expectations.

#include <rili/Test.hpp>
#include <rili/test/Config.hpp>
#include <rili/test/EventHandler.hpp>
#include "Assert.hpp"
/*
 * EXAMPLES_ASSERTs are not needed when you use rtest expectations - however in rtest project we use examples as self
 * tests, so EXAMPLES_ASSERTs are here only because of that.
 */

class ExpectSuccess : public rili::test::TestBaseFixture {
 public:
    void after() override { EXAMPLES_ASSERT(!rili::test::EventHandler::getInstance().currentTestFailed()); }
};

class ExpectFailure : public rili::test::TestBaseFixture {
 public:
    void after() override { EXAMPLES_ASSERT(rili::test::EventHandler::getInstance().currentTestFailed()); }
};

TEST_F(ExpectFailure, AddFailure) {
    ADD_FAILURE("some message");
    ADD_FAILURE();
}

TEST_F(ExpectSuccess, EQ) {
    EXAMPLES_ASSERT(EXPECT_EQ(1, 1, "1 should be always equal to 1"));
    EXAMPLES_ASSERT(EXPECT_EQ(2, 2));
}

TEST_F(ExpectFailure, EQ) {
    EXAMPLES_ASSERT(!EXPECT_EQ(1, 2, "1 should never be equal to 2"));
    EXAMPLES_ASSERT(!EXPECT_EQ(2, 1));
}

TEST_F(ExpectSuccess, NE) {
    EXAMPLES_ASSERT(EXPECT_NE(1, 2, "1 should always be not equal to 2"));
    EXAMPLES_ASSERT(EXPECT_NE(2, 1));
}

TEST_F(ExpectFailure, NE) {
    EXAMPLES_ASSERT(!EXPECT_NE(1, 1, "1 should never be not equal to 1"));
    EXAMPLES_ASSERT(!EXPECT_NE(2, 2));
}

TEST_F(ExpectSuccess, LT) {
    EXAMPLES_ASSERT(EXPECT_LT(1, 2, "1 should be always less than to 2"));
    EXAMPLES_ASSERT(EXPECT_LT(2, 3));
}

TEST_F(ExpectFailure, LT) {
    EXAMPLES_ASSERT(!EXPECT_LT(2, 1, "2 should never be less than to 1"));
    EXAMPLES_ASSERT(!EXPECT_LT(3, 2));
}

TEST_F(ExpectSuccess, LE) {
    EXAMPLES_ASSERT(EXPECT_LE(1, 2, "1 should be always less or equal 2"));
    EXAMPLES_ASSERT(EXPECT_LE(2, 3));

    EXAMPLES_ASSERT(EXPECT_LE(1, 1, "1 should be always less or equal 1"));
    EXAMPLES_ASSERT(EXPECT_LE(2, 2));
}

TEST_F(ExpectFailure, LE) {
    EXAMPLES_ASSERT(!EXPECT_LE(2, 1, "2 should never be less or equal 1"));
    EXAMPLES_ASSERT(!EXPECT_LE(3, 2));
}

TEST_F(ExpectSuccess, GT) {
    EXAMPLES_ASSERT(EXPECT_GT(2, 1, "2 should be always greater than to 1"));
    EXAMPLES_ASSERT(EXPECT_GT(3, 2));
}

TEST_F(ExpectFailure, GT) {
    EXAMPLES_ASSERT(!EXPECT_GT(1, 2, "1 should never be greater than to 2"));
    EXAMPLES_ASSERT(!EXPECT_GT(2, 3));
}

TEST_F(ExpectSuccess, GE) {
    EXAMPLES_ASSERT(EXPECT_GE(2, 1, "2 should be always greater or equal 1"));
    EXAMPLES_ASSERT(EXPECT_GE(3, 2));

    EXAMPLES_ASSERT(EXPECT_GE(1, 1, "1 should be always greater or equal 1"));
    EXAMPLES_ASSERT(EXPECT_GE(2, 2));
}

TEST_F(ExpectFailure, GE) {
    EXAMPLES_ASSERT(!EXPECT_GE(1, 2, "1 should never be greater or equal 2"));
    EXAMPLES_ASSERT(!EXPECT_GE(2, 3));
}

TEST_F(ExpectSuccess, TRUE) {
    EXAMPLES_ASSERT(EXPECT_TRUE(true, "true should be always true"));
    EXAMPLES_ASSERT(EXPECT_TRUE(!false));
}

TEST_F(ExpectFailure, TRUE) {
    EXAMPLES_ASSERT(!EXPECT_TRUE(!true, "!true should never be true"));
    EXAMPLES_ASSERT(!EXPECT_TRUE(false));
}

TEST_F(ExpectSuccess, FALSE) {
    EXAMPLES_ASSERT(EXPECT_FALSE(false, "false should be always false"));
    EXAMPLES_ASSERT(EXPECT_FALSE(!true));
}

TEST_F(ExpectFailure, FALSE) {
    EXAMPLES_ASSERT(!EXPECT_FALSE(!false, "!false should never be false"));
    EXAMPLES_ASSERT(!EXPECT_FALSE(true));
}
#ifdef RILI_TEST_WITH_EXCEPTIONS
TEST_F(ExpectSuccess, ANY_THROW) {
    EXAMPLES_ASSERT(EXPECT_ANY_THROW([]() { throw 1; }, "throwing function should always throw"));
    EXAMPLES_ASSERT(EXPECT_ANY_THROW([]() { throw 2; }));
}

TEST_F(ExpectFailure, ANY_THROW) {
    EXAMPLES_ASSERT(!EXPECT_ANY_THROW([]() {}, "empty function should never throw"));
    EXAMPLES_ASSERT(!EXPECT_ANY_THROW([]() {}));
}

TEST_F(ExpectSuccess, THROW) {
    EXAMPLES_ASSERT(EXPECT_THROW(std::runtime_error, []() { throw std::runtime_error("expected"); },
                                 "throwing function should always throw"));
    EXAMPLES_ASSERT(EXPECT_THROW(std::exception, []() { throw std::runtime_error("some other"); }));
}

TEST_F(ExpectFailure, THROW) {
    EXAMPLES_ASSERT(!EXPECT_THROW(std::exception, []() {}, "empty function should never throw"));
    EXAMPLES_ASSERT(!EXPECT_THROW(std::exception, []() {}));

    EXAMPLES_ASSERT(
        !EXPECT_THROW(std::exception, []() { throw 1; }, "int throwing function should never throw std::excaption"));
    EXAMPLES_ASSERT(!EXPECT_THROW(std::exception, []() { throw 2; }));
}
#endif

TEST_F(ExpectSuccess, NumberOfTestGreaterThanZero) { EXPECT_GT(rili::test::TestStorage::getInstance().size(), 0u); }

Rili test support not only EXPECT_* but also ASSERT_* which in case of failure immedietely stop current test(if compiled without exceptions will terminate test application gracefully)

#include <rili/Test.hpp>
#include <rili/test/Config.hpp>
#include <rili/test/EventHandler.hpp>
#include <string>

TEST(Asserts, Pass) {
    ASSERT_EQ(1, 1);
    ASSERT_FALSE(false);
    ASSERT_GE(3, 3);
    ASSERT_GE(3, 2);
    ASSERT_GT(3, 2);
    ASSERT_LE(2, 3);
    ASSERT_LE(3, 3);
    ASSERT_LT(2, 3);
    ASSERT_NE(3, 7);
    ASSERT_TRUE(true);

#ifdef RILI_TEST_WITH_EXCEPTIONS
    ASSERT_ANY_THROW([]() { throw 5; });
    ASSERT_THROW(std::string, []() { throw std::string("10"); });
#endif
}

#ifdef RILI_TEST_WITH_EXCEPTIONS
TEST(Asserts, eqFailure) {
    ASSERT_EQ(1, 5);
    std::terminate();
}

TEST(Asserts, falseFailure) {
    ASSERT_FALSE(true);
    std::terminate();
}

TEST(Asserts, geFailure) {
    ASSERT_GE(1, 2);
    std::terminate();
}

TEST(Asserts, gtFailure) {
    ASSERT_GT(1, 2);
    std::terminate();
}

TEST(Asserts, leFailure) {
    ASSERT_LE(2, 1);
    std::terminate();
}

TEST(Asserts, ltFailure) {
    ASSERT_LT(1, 1);
    std::terminate();
}

TEST(Asserts, neFailure) {
    ASSERT_NE(1, 1);
    std::terminate();
}

TEST(Asserts, trueFailure) {
    ASSERT_TRUE(false);
    std::terminate();
}

TEST(Asserts, anyThrowFailure) {
    ASSERT_ANY_THROW([]() {});
    std::terminate();
}

TEST(Asserts, throw1Failure) {
    ASSERT_THROW(int, []() { throw std::string(":)"); });
    std::terminate();
}

TEST(Asserts, throw2Failure) {
    ASSERT_THROW(int, []() {});
    std::terminate();
}
#endif

This example show how tests can be disabled or skipped.

#include <rili/Test.hpp>
#include "Assert.hpp"
TEST(DisabledTest, DISABLE_SomeTest) { EXAMPLES_ASSERT(false); }
TEST(SkippedTest, SKIP_SomeTest) { EXAMPLES_ASSERT(false); }
Note:

please look how main is defined in previous example - there is used filtering function which mark as skipped these tests, which scenario name starts with "SKIP_" and as disabled these, which scenario name starts with "DISABLE_"

Note:

in your project you can define filtering function as you like

This example show how to define mock methods and create expectations

#include <iostream>
#include <rili/Test.hpp>
#include <rili/test/CallHandler.hpp>
#include <rili/test/Config.hpp>
#include <rili/test/EventHandler.hpp>
#include "Assert.hpp"

class MocksSuccess : public rili::test::TestBaseFixture {
 public:
    void after() override {
        rili::test::CallHandler::getInstance().tearDown();  // normally you not need this - it is called anyway by
        // runner after every test, however this is our self test, so we
        // would like to assert if any unexpected stuff dangling
        EXAMPLES_ASSERT(!rili::test::EventHandler::getInstance().currentTestFailed());
    }
};

class MocksFailure : public rili::test::TestBaseFixture {
 public:
    void after() override {
        rili::test::CallHandler::getInstance().tearDown();  // normally you not need this - it is called anyway by
        // runner after every test, however this is our self test, so we
        // would like to assert if any unexpected stuff dangling
        EXAMPLES_ASSERT(rili::test::EventHandler::getInstance().currentTestFailed());
    }
};

class Class {
 public:
    virtual void foo() {}
    virtual void foo() const {}
    virtual int bar() { return 5; }
    virtual int bar() const { return 10; }
    virtual int m1(int const& i1) const { return i1 * 0; }
    virtual int m2(int const& i1, int const& i2) const { return i1 * i2 * 0; }
    virtual int m3(int const& i1, int const& i2, int const& i3) const { return i1 * i2 * i3 * 0; }
    virtual int m4(int const& i1, int const& i2, int const& i3, int const& i4) const { return i1 * i2 * i3 * i4 * 0; }
    virtual int m5(int const& i1, int const& i2, int const& i3, int const& i4, int const& i5) const {
        return i1 * i2 * i3 * i4 * i5 * 0;
    }
    virtual int m6(int const& i1, int const& i2, int const& i3, int const& i4, int const& i5, int const& i6) const {
        return i1 * i2 * i3 * i4 * i5 * i6 * 0;
    }
    virtual int m7(int const& i1, int const& i2, int const& i3, int const& i4, int const& i5, int const& i6,
                   int const& i7) const {
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * 0;
    }
    virtual int m8(int const& i1, int const& i2, int const& i3, int const& i4, int const& i5, int const& i6,
                   int const& i7, int const& i8) const {
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8 * 0;
    }
    virtual int m9(int const& i1, int const& i2, int const& i3, int const& i4, int const& i5, int const& i6,
                   int const& i7, int const& i8, int const& i9) const {
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8 * i9 * 0;
    }
    virtual int m10(int const& i1, int const& i2, int const& i3, int const& i4, int const& i5, int const& i6,
                    int const& i7, int const& i8, int const& i9, int const& i10) const {
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8 * i9 * i10 * 0;
    }
    virtual ~Class() = default;
};

class Mock : public Class {
 public:
    Mock() {}
    virtual ~Mock() = default;

 public:
    MOCK0(void, foo)
    MOCK0(int, bar)
    MOCK0(void, foo, const)
    MOCK0(int, bar, const)
    MOCK1(int, m1, int const&, const)
    MOCK2(int, m2, int const&, int const&, const)
    MOCK3(int, m3, int const&, int const&, int const&, const)
    MOCK4(int, m4, int const&, int const&, int const&, int const&, const)
    MOCK5(int, m5, int const&, int const&, int const&, int const&, int const&, const)
    MOCK6(int, m6, int const&, int const&, int const&, int const&, int const&, int const&, const)
    MOCK7(int, m7, int const&, int const&, int const&, int const&, int const&, int const&, int const&, const)
    MOCK8(int, m8, int const&, int const&, int const&, int const&, int const&, int const&, int const&, int const&,
          const)
    MOCK9(int, m9, int const&, int const&, int const&, int const&, int const&, int const&, int const&, int const&,
          int const&, const)
    MOCK10(int, m10, int const&, int const&, int const&, int const&, int const&, int const&, int const&, int const&,
           int const&, int const&, const)
};

TEST_F(MocksSuccess, foo) {
    Mock instance;

    EXPECT_CALL(instance, foo, []() { std::cout << "foo was called" << std::endl; });
    instance.foo();
}

TEST_F(MocksSuccess, fooConst) {
    const Mock instance;

    EXPECT_CALL(instance, foo, []() { std::cout << "const foo was called" << std::endl; });
    instance.foo();
}

TEST_F(MocksSuccess, bar) {
    Mock instance;

    EXPECT_CALL(instance, bar, []() {
        std::cout << "bar was called" << std::endl;
        return 1;
    });
    EXPECT_EQ(1, instance.bar());
}

TEST_F(MocksSuccess, barConst) {
    const Mock instance;

    EXPECT_CALL(instance, bar, []() {
        std::cout << "const bar was called" << std::endl;
        return 2;
    });
    EXPECT_EQ(2, instance.bar());
}

#ifdef RILI_TEST_WITH_EXCEPTIONS
TEST_F(MocksFailure, unexpectedCall) {
    const Mock instance;
    EXPECT_EQ(0, instance.m4(1, 2, 3, 4));
}
#endif

TEST_F(MocksFailure, danglingExpectation) {
    const Mock instance;
    EXPECT_CALL(instance, bar, []() { return 5; }, "this is expected to be not called");
}

TEST_F(MocksSuccess, m1) {
    const Mock instance;

    EXPECT_CALL(instance, m1, [](int const& i) {
        EXPECT_EQ(1, i);
        std::cout << "const m1 was called" << std::endl;
        return i;
    });
    EXPECT_EQ(1, instance.m1(1));
}

TEST_F(MocksSuccess, m2) {
    const Mock instance;

    EXPECT_CALL(instance, m2, [](int const& i1, int const& i2) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        std::cout << "const m2 was called" << std::endl;
        return i1 * i2;
    });
    EXPECT_EQ(2, instance.m2(1, 2));
}

TEST_F(MocksSuccess, m3) {
    const Mock instance;

    EXPECT_CALL(instance, m3, [](int const& i1, int const& i2, int const& i3) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        std::cout << "const m3 was called" << std::endl;
        return i1 * i2 * i3;
    });
    EXPECT_EQ(6, instance.m3(1, 2, 3));
}

TEST_F(MocksSuccess, m4) {
    const Mock instance;

    EXPECT_CALL(instance, m4, [](int const& i1, int const& i2, int const& i3, int const& i4) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        EXPECT_EQ(4, i4);
        std::cout << "const m4 was called" << std::endl;
        return i1 * i2 * i3 * i4;
    });
    EXPECT_EQ(24, instance.m4(1, 2, 3, 4));
}

TEST_F(MocksSuccess, m5) {
    const Mock instance;

    EXPECT_CALL(instance, m5, [](int const& i1, int const& i2, int const& i3, int const& i4, int const& i5) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        EXPECT_EQ(4, i4);
        EXPECT_EQ(5, i5);
        std::cout << "const m5 was called" << std::endl;
        return i1 * i2 * i3 * i4 * i5;
    });
    EXPECT_EQ(120, instance.m5(1, 2, 3, 4, 5));
}

TEST_F(MocksSuccess, m6) {
    const Mock instance;

    EXPECT_CALL(instance, m6,
                [](int const& i1, int const& i2, int const& i3, int const& i4, int const& i5, int const& i6) {
                    EXPECT_EQ(1, i1);
                    EXPECT_EQ(2, i2);
                    EXPECT_EQ(3, i3);
                    EXPECT_EQ(4, i4);
                    EXPECT_EQ(5, i5);
                    EXPECT_EQ(6, i6);
                    std::cout << "const m6 was called" << std::endl;
                    return i1 * i2 * i3 * i4 * i5 * i6;
                });
    EXPECT_EQ(720, instance.m6(1, 2, 3, 4, 5, 6));
}

TEST_F(MocksSuccess, m7) {
    const Mock instance;

    EXPECT_CALL(instance, m7, [](int const& i1, int const& i2, int const& i3, int const& i4, int const& i5,
                                 int const& i6, int const& i7) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        EXPECT_EQ(4, i4);
        EXPECT_EQ(5, i5);
        EXPECT_EQ(6, i6);
        EXPECT_EQ(7, i7);
        std::cout << "const m7 was called" << std::endl;
        return i1 * i2 * i3 * i4 * i5 * i6 * i7;
    });
    EXPECT_EQ(5040, instance.m7(1, 2, 3, 4, 5, 6, 7));
}

TEST_F(MocksSuccess, m8) {
    const Mock instance;

    EXPECT_CALL(instance, m8, [](int const& i1, int const& i2, int const& i3, int const& i4, int const& i5,
                                 int const& i6, int const& i7, int const& i8) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        EXPECT_EQ(4, i4);
        EXPECT_EQ(5, i5);
        EXPECT_EQ(6, i6);
        EXPECT_EQ(7, i7);
        EXPECT_EQ(8, i8);
        std::cout << "const m8 was called" << std::endl;
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8;
    });
    EXPECT_EQ(40320, instance.m8(1, 2, 3, 4, 5, 6, 7, 8));
}

TEST_F(MocksSuccess, m9) {
    const Mock instance;

    EXPECT_CALL(instance, m9, [](int const& i1, int const& i2, int const& i3, int const& i4, int const& i5,
                                 int const& i6, int const& i7, int const& i8, int const& i9) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        EXPECT_EQ(4, i4);
        EXPECT_EQ(5, i5);
        EXPECT_EQ(6, i6);
        EXPECT_EQ(7, i7);
        EXPECT_EQ(8, i8);
        EXPECT_EQ(9, i9);
        std::cout << "const m9 was called" << std::endl;
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8 * i9;
    });
    EXPECT_EQ(362880, instance.m9(1, 2, 3, 4, 5, 6, 7, 8, 9));
}

TEST_F(MocksSuccess, m10) {
    const Mock instance;

    EXPECT_CALL(instance, m10, [](int const& i1, int const& i2, int const& i3, int const& i4, int const& i5,
                                  int const& i6, int const& i7, int const& i8, int const& i9, int const& i10) {
        EXPECT_EQ(1, i1);
        EXPECT_EQ(2, i2);
        EXPECT_EQ(3, i3);
        EXPECT_EQ(4, i4);
        EXPECT_EQ(5, i5);
        EXPECT_EQ(6, i6);
        EXPECT_EQ(7, i7);
        EXPECT_EQ(8, i8);
        EXPECT_EQ(9, i9);
        EXPECT_EQ(10, i10);
        std::cout << "const m9 was called" << std::endl;
        return i1 * i2 * i3 * i4 * i5 * i6 * i7 * i8 * i9 * i10;
    });
    EXPECT_EQ(3628800, instance.m10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
}