diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/rtc_base/untyped_function_unittest.cc | |
parent | Initial commit. (diff) | |
download | firefox-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.cc | 309 |
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 |