void runTest() override
    {
        FunctionTestsHelpers::BigData bigData;

        {
            beginTest ("Functions");

            std::function<void(int&)> f1 (FunctionTestsHelpers::incrementArgument);

            auto x = 0;
            f1 (x);
            expectEquals (x, 1);

            std::function<double(double, double)> f2 (FunctionTestsHelpers::multiply);
            expectEquals (6.0, f2 (2.0, 3.0));

        }

        {
            beginTest ("Function objects");
            std::function<int(int)> f1 = FunctionTestsHelpers::FunctionObject();
            expectEquals (f1 (5), FunctionTestsHelpers::BigData::bigDataSum + 5);
        }

        {
            beginTest ("Lambdas");

            std::function<int()> fStack ([] { return 3; });
            expectEquals (fStack(), 3);

            std::function<int()> fHeap ([=] { return bigData.sum(); });
            expectEquals (fHeap(), FunctionTestsHelpers::BigData::bigDataSum);
        }

        {
            beginTest ("Boolean");

            std::function<void(int&)> f1;

            if (f1)
                expect (false);

            std::function<int()> f2 ([]() { return 3; });

            if (! f2)
                expect (false);
        }

        std::function<int()> fEmpty;

        std::function<int()> fStack ([] { return 3; });

        std::function<int()> fHeap ([=] { return bigData.sum(); });

        {
            beginTest ("copy constructor");

            std::function<int()> f1 (fStack);
            expectEquals (f1(), 3);

            std::function<int()> f2 (fHeap);
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            std::function<int()> f3 (fEmpty);
            if (f3)
                expect (false);
        }

        {
            beginTest ("assignment");

            std::function<int()> f1;
            f1 = fStack;
            expectEquals (f1(), 3);

            std::function<int()> f2;
            f2 = fHeap;
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            f1 = fHeap;
            expectEquals (f1(), FunctionTestsHelpers::BigData::bigDataSum);

            f2 = fStack;
            expectEquals (f2(), 3);

            f1 = fEmpty;
            if (f1)
                expect (false);
        }

        {
            beginTest ("move constructor");

            ScopedPointer<std::function<int()>> fStackTmp (new std::function<int()> (fStack));
            std::function<int()> f1 (static_cast<std::function<int()>&&> (*fStackTmp));

            fStackTmp.reset();
            expectEquals (f1(), 3);

            ScopedPointer<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));
            std::function<int()> f2 (static_cast<std::function<int()>&&> (*fHeapTmp));
            if (*fHeapTmp)
                expect (false);

            fHeapTmp.reset();
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            ScopedPointer<std::function<int()>> fEmptyTmp (new std::function<int()>());
            std::function<int()> f3 (static_cast<std::function<int()>&&> (*fEmptyTmp));
            fEmptyTmp.reset();
            if (f3)
                expect (false);
        }

        {
            beginTest ("move assignment");

            std::function<int()> f1 (fHeap);
            ScopedPointer<std::function<int()>> fStackTmp (new std::function<int()> (fStack));
            f1 = static_cast<std::function<int()>&&> (*fStackTmp);

            fStackTmp.reset();
            expectEquals (f1(), 3);

            std::function<int()> f2 (fStack);
            ScopedPointer<std::function<int()>> fHeapTmp (new std::function<int()> (fHeap));
            f2 = static_cast<std::function<int()>&&> (*fHeapTmp);
            if (*fHeapTmp)
                expect (false);

            fHeapTmp.reset();
            expectEquals (f2(), FunctionTestsHelpers::BigData::bigDataSum);

            std::function<int()> f3 (fHeap);
            ScopedPointer<std::function<int()>> fEmptyTmp (new std::function<int()>());
            f3 = static_cast<std::function<int()>&&> (*fEmptyTmp);
            fEmptyTmp.reset();
            if (f3)
                expect (false);
        }

        {
            beginTest ("nullptr");

            std::function<int()> f1 (nullptr);
            if (f1)
                expect (false);

            std::function<int()> f2 ([]() { return 11; });
            f2 = nullptr;
            if (f2)
                expect (false);
        }

        {
            beginTest ("Swap");

            std::function<int()> f1;
            std::function<int()> f2 (fStack);
            f2.swap (f1);
            expectEquals (f1(), 3);
            if (f2)
                expect (false);

            std::function<int()> f3 (fHeap);
            f3.swap (f1);
            expectEquals (f3(), 3);
            expectEquals (f1(), FunctionTestsHelpers::BigData::bigDataSum);
        }
    }