summaryrefslogtreecommitdiffstats
path: root/mfbt/tests/TestFunctionRef.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mfbt/tests/TestFunctionRef.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/mfbt/tests/TestFunctionRef.cpp b/mfbt/tests/TestFunctionRef.cpp
new file mode 100644
index 0000000000..0ae1d4f193
--- /dev/null
+++ b/mfbt/tests/TestFunctionRef.cpp
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "mozilla/Assertions.h"
+#include "mozilla/FunctionRef.h"
+#include "mozilla/UniquePtr.h"
+
+using mozilla::FunctionRef;
+
+#define CHECK(c) \
+ do { \
+ bool cond = !!(c); \
+ MOZ_RELEASE_ASSERT(cond, "Failed assertion: " #c); \
+ } while (false)
+
+int addConstRefs(const int& arg1, const int& arg2) { return arg1 + arg2; }
+
+void incrementPointer(int* arg) { (*arg)++; }
+
+int increment(int arg) { return arg + 1; }
+
+int incrementUnique(mozilla::UniquePtr<int> ptr) { return *ptr + 1; }
+
+static bool helloWorldCalled = false;
+
+void helloWorld() { helloWorldCalled = true; }
+
+struct S {
+ static int increment(int arg) { return arg + 1; }
+};
+
+struct Incrementor {
+ int operator()(int arg) { return arg + 1; }
+};
+
+template <typename Fn>
+struct Caller;
+
+template <typename Fn, typename... Params>
+std::invoke_result_t<Fn, Params...> CallFunctionRef(FunctionRef<Fn> aRef,
+ Params... aParams) {
+ return aRef(std::forward<Params>(aParams)...);
+}
+
+static void TestNonmemberFunction() {
+ CHECK(CallFunctionRef<int(int)>(increment, 42) == 43);
+}
+
+static void TestStaticMemberFunction() {
+ CHECK(CallFunctionRef<int(int)>(&S::increment, 42) == 43);
+}
+
+static void TestFunctionObject() {
+ auto incrementor = Incrementor();
+ CHECK(CallFunctionRef<int(int)>(incrementor, 42) == 43);
+}
+
+static void TestFunctionObjectTemporary() {
+ CHECK(CallFunctionRef<int(int)>(Incrementor(), 42) == 43);
+}
+
+static void TestLambda() {
+ // Test non-capturing lambda
+ auto lambda1 = [](int arg) { return arg + 1; };
+ CHECK(CallFunctionRef<int(int)>(lambda1, 42) == 43);
+
+ // Test capturing lambda
+ int one = 1;
+ auto lambda2 = [one](int arg) { return arg + one; };
+ CHECK(CallFunctionRef<int(int)>(lambda2, 42) == 43);
+
+ CHECK(CallFunctionRef<int(int)>([](int arg) { return arg + 1; }, 42) == 43);
+}
+
+static void TestOperatorBool() {
+ auto ToBool = [](FunctionRef<int(int)> aRef) {
+ return static_cast<bool>(aRef);
+ };
+ CHECK(!ToBool({}));
+ CHECK(ToBool(increment));
+ CHECK(!ToBool(nullptr));
+}
+
+static void TestReferenceParameters() {
+ int x = 1;
+ int y = 2;
+ CHECK(CallFunctionRef<int(const int&, const int&)>(addConstRefs, x, y) == 3);
+}
+
+static void TestVoidNoParameters() {
+ CHECK(!helloWorldCalled);
+ CallFunctionRef<void()>(helloWorld);
+ CHECK(helloWorldCalled);
+}
+
+static void TestPointerParameters() {
+ int x = 1;
+ CallFunctionRef<void(int*)>(incrementPointer, &x);
+ CHECK(x == 2);
+}
+
+static void TestImplicitFunctorTypeConversion() {
+ auto incrementor = Incrementor();
+ short x = 1;
+ CHECK(CallFunctionRef<long(short)>(incrementor, x) == 2);
+}
+
+static void TestImplicitLambdaTypeConversion() {
+ short x = 1;
+ CHECK(CallFunctionRef<long(short)>([](short arg) { return arg + 1; }, x) ==
+ 2);
+}
+
+static void TestImplicitFunctionPointerTypeConversion() {
+ short x = 1;
+ CHECK(CallFunctionRef<long(short)>(&increment, x) == 2);
+}
+
+static void TestMoveOnlyArguments() {
+ CHECK(CallFunctionRef<int(mozilla::UniquePtr<int>)>(
+ &incrementUnique, mozilla::MakeUnique<int>(5)) == 6);
+}
+
+int main() {
+ TestNonmemberFunction();
+ TestStaticMemberFunction();
+ TestFunctionObject();
+ TestFunctionObjectTemporary();
+ TestLambda();
+ TestOperatorBool();
+ TestReferenceParameters();
+ TestPointerParameters();
+ TestVoidNoParameters();
+ TestImplicitFunctorTypeConversion();
+ TestImplicitLambdaTypeConversion();
+ TestImplicitFunctionPointerTypeConversion();
+ TestMoveOnlyArguments();
+
+ printf("TestFunctionRef OK!\n");
+ return 0;
+}