summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/rtc_base/untyped_function_unittest.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_base/untyped_function_unittest.cc
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/rtc_base/untyped_function_unittest.cc')
-rw-r--r--third_party/libwebrtc/rtc_base/untyped_function_unittest.cc309
1 files changed, 309 insertions, 0 deletions
diff --git a/third_party/libwebrtc/rtc_base/untyped_function_unittest.cc b/third_party/libwebrtc/rtc_base/untyped_function_unittest.cc
new file mode 100644
index 0000000000..8ea26e7a43
--- /dev/null
+++ b/third_party/libwebrtc/rtc_base/untyped_function_unittest.cc
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/untyped_function.h"
+
+#include <memory>
+#include <vector>
+
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::Pointee;
+
+TEST(UntypedFunction, Empty1) {
+ UntypedFunction uf;
+ EXPECT_FALSE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+}
+
+TEST(UntypedFunction, Empty2) {
+ UntypedFunction uf = nullptr;
+ EXPECT_FALSE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+}
+
+TEST(UntypedFunction, Empty3) {
+ UntypedFunction uf = UntypedFunction::Create<int(int)>(nullptr);
+ EXPECT_FALSE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+}
+
+TEST(UntypedFunction, CallTrivialWithInt) {
+ auto uf = UntypedFunction::Create<int(int)>([](int x) { return x + 5; });
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int(int)>(17), 22);
+}
+
+TEST(UntypedFunction, CallTrivialWithPointer) {
+ auto uf = UntypedFunction::Create<int(int*)>([](int* x) { return *x; });
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ int x = 12;
+ EXPECT_EQ(uf.Call<int(int*)>(&x), 12);
+}
+
+TEST(UntypedFunction, CallTrivialWithReference) {
+ auto uf = UntypedFunction::Create<void(int&)>([](int& x) { x = 3; });
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ int x = 12;
+ uf.Call<void(int&)>(x);
+ EXPECT_EQ(x, 3);
+}
+
+TEST(UntypedFunction, CallTrivialWithRvalueReference) {
+ auto uf = UntypedFunction::Create<int(int&&)>([](int&& x) { return x - 2; });
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int(int&&)>(34), 32);
+}
+
+TEST(UntypedFunction, CallNontrivialWithInt) {
+ std::vector<int> list;
+ auto uf = UntypedFunction::Create<int(int)>([list](int x) mutable {
+ list.push_back(x);
+ return list.size();
+ });
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int(int)>(17), 1);
+ EXPECT_EQ(uf.Call<int(int)>(17), 2);
+}
+
+TEST(UntypedFunction, CallNontrivialWithPointer) {
+ std::vector<int> list;
+ auto uf = UntypedFunction::Create<int*(int*)>([list](int* x) mutable {
+ list.push_back(*x);
+ return list.data();
+ });
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ int x = 12;
+ EXPECT_THAT(uf.Call<int*(int*)>(&x), Pointee(12));
+}
+
+TEST(UntypedFunction, CallNontrivialWithReference) {
+ std::vector<int> list = {34, 35, 36};
+ auto uf =
+ UntypedFunction::Create<void(int&)>([list](int& x) { x = list[1]; });
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ int x = 12;
+ uf.Call<void(int&)>(x);
+ EXPECT_EQ(x, 35);
+}
+
+TEST(UntypedFunction, CallNontrivialWithRvalueReference) {
+ std::vector<int> list;
+ auto uf = UntypedFunction::Create<int(int&&)>([list](int&& x) mutable {
+ list.push_back(x);
+ return list.size();
+ });
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int(int&&)>(34), 1);
+ EXPECT_EQ(uf.Call<int(int&&)>(34), 2);
+}
+
+int AddFive(int x) {
+ return x + 5;
+}
+int DereferencePointer(int* x) {
+ return *x;
+}
+void AssignThree(int& x) {
+ x = 3;
+}
+int SubtractTwo(int&& x) {
+ return x - 2;
+}
+
+TEST(UntypedFunction, CallFunctionPointerWithInt) {
+ auto uf = UntypedFunction::Create<int(int)>(AddFive);
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int(int)>(17), 22);
+}
+
+TEST(UntypedFunction, CallFunctionPointerWithPointer) {
+ auto uf = UntypedFunction::Create<int(int*)>(DereferencePointer);
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ int x = 12;
+ EXPECT_EQ(uf.Call<int(int*)>(&x), 12);
+}
+
+TEST(UntypedFunction, CallFunctionPointerWithReference) {
+ auto uf = UntypedFunction::Create<void(int&)>(AssignThree);
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ int x = 12;
+ uf.Call<void(int&)>(x);
+ EXPECT_EQ(x, 3);
+}
+
+TEST(UntypedFunction, CallFunctionPointerWithRvalueReference) {
+ auto uf = UntypedFunction::Create<int(int&&)>(SubtractTwo);
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int(int&&)>(34), 32);
+}
+
+TEST(UntypedFunction, CallTrivialWithNoArgs) {
+ int arr[] = {1, 2, 3};
+ static_assert(sizeof(arr) <= UntypedFunction::kInlineStorageSize, "");
+ auto uf = UntypedFunction::Create<int()>([arr] { return arr[1]; });
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int()>(), 2);
+}
+
+TEST(UntypedFunction, CallLargeTrivialWithNoArgs) {
+ int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
+ static_assert(sizeof(arr) > UntypedFunction::kInlineStorageSize, "");
+ auto uf = UntypedFunction::Create<int()>([arr] { return arr[4]; });
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int()>(), 5);
+}
+
+TEST(UntypedFunction, MoveonlyReturnValue) {
+ auto uf = UntypedFunction::Create<std::unique_ptr<int>()>(
+ [] { return std::make_unique<int>(567); });
+ EXPECT_THAT(uf.Call<std::unique_ptr<int>()>(), Pointee(567));
+}
+
+TEST(UntypedFunction, MoveonlyArgument) {
+ auto uf = UntypedFunction::Create<int(std::unique_ptr<int>)>(
+ [](std::unique_ptr<int> x) { return *x + 19; });
+ EXPECT_EQ(uf.Call<int(std::unique_ptr<int>)>(std::make_unique<int>(40)), 59);
+}
+
+TEST(UntypedFunction, MoveOnlyCallable) {
+ auto uf = UntypedFunction::Create<int()>(
+ [x = std::make_unique<int>(17)] { return ++*x; });
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int()>(), 18);
+ EXPECT_EQ(uf.Call<int()>(), 19);
+ UntypedFunction uf2 = std::move(uf);
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_FALSE(uf2.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int()>(), 20);
+ EXPECT_EQ(uf.Call<int()>(), 21);
+}
+
+class Destroyer {
+ public:
+ explicit Destroyer(int& destroy_count) : destroy_count_(&destroy_count) {}
+ ~Destroyer() { ++*destroy_count_; }
+ int operator()() { return 72; }
+ int* destroy_count_;
+};
+
+TEST(UntypedFunction, CallableIsDestroyed) {
+ int destroy_count = 0;
+ {
+ auto uf = UntypedFunction::Create<int()>(Destroyer(destroy_count));
+ // Destruction count is 1 here, because the temporary we created above was
+ // destroyed.
+ EXPECT_EQ(destroy_count, 1);
+ {
+ auto uf2 = std::move(uf);
+ EXPECT_EQ(destroy_count, 1);
+ }
+ // `uf2` was destroyed.
+ EXPECT_EQ(destroy_count, 2);
+ }
+ // `uf` was destroyed, but it didn't contain a Destroyer since we moved it to
+ // `uf2` above.
+ EXPECT_EQ(destroy_count, 2);
+}
+
+TEST(UntypedFunction, MoveAssign) {
+ int destroy_count = 0;
+ auto uf = UntypedFunction::Create<int()>(Destroyer(destroy_count));
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ // Destruction count is 1 here, because the temporary we created above was
+ // destroyed.
+ EXPECT_EQ(destroy_count, 1);
+ UntypedFunction uf2 = nullptr;
+ EXPECT_FALSE(uf2);
+ EXPECT_TRUE(uf2.IsTriviallyDestructible());
+
+ uf2 = std::move(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_TRUE(uf2);
+ EXPECT_FALSE(uf2.IsTriviallyDestructible());
+ EXPECT_EQ(destroy_count, 1); // The callable was not destroyed.
+ EXPECT_EQ(uf2.Call<int()>(), 72);
+
+ UntypedFunction uf3 = nullptr;
+ uf2 = std::move(uf3);
+ EXPECT_FALSE(uf2);
+ EXPECT_TRUE(uf2.IsTriviallyDestructible());
+ EXPECT_EQ(destroy_count, 2); // The callable was destroyed by the assignment.
+}
+
+TEST(UntypedFunction, NullptrAssign) {
+ int destroy_count = 0;
+ auto uf = UntypedFunction::Create<int()>(Destroyer(destroy_count));
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ // Destruction count is 1 here, because the temporary we created above was
+ // destroyed.
+ EXPECT_EQ(destroy_count, 1);
+
+ uf = nullptr;
+ EXPECT_FALSE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_EQ(destroy_count, 2); // The callable was destroyed by the assignment.
+}
+
+TEST(UntypedFunction, Swap) {
+ int x = 13;
+ auto uf = UntypedFunction::Create<int()>([x]() mutable { return ++x; });
+ EXPECT_TRUE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ auto y = std::make_unique<int>(113);
+ auto uf2 =
+ UntypedFunction::Create<int()>([y = std::move(y)] { return ++*y; });
+ EXPECT_TRUE(uf2);
+ EXPECT_FALSE(uf2.IsTriviallyDestructible());
+ UntypedFunction uf3 = nullptr;
+ EXPECT_FALSE(uf3);
+ EXPECT_TRUE(uf3.IsTriviallyDestructible());
+
+ EXPECT_EQ(uf.Call<int()>(), 14);
+ swap(uf, uf2);
+ EXPECT_TRUE(uf);
+ EXPECT_FALSE(uf.IsTriviallyDestructible());
+ EXPECT_TRUE(uf2);
+ EXPECT_TRUE(uf2.IsTriviallyDestructible());
+ EXPECT_EQ(uf.Call<int()>(), 114);
+ EXPECT_EQ(uf2.Call<int()>(), 15);
+
+ swap(uf, uf3);
+ EXPECT_FALSE(uf);
+ EXPECT_TRUE(uf.IsTriviallyDestructible());
+ EXPECT_TRUE(uf3);
+ EXPECT_FALSE(uf3.IsTriviallyDestructible());
+ EXPECT_EQ(uf3.Call<int()>(), 115);
+}
+
+} // namespace
+} // namespace webrtc