From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../rtc_base/untyped_function_unittest.cc | 309 +++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 third_party/libwebrtc/rtc_base/untyped_function_unittest.cc (limited to 'third_party/libwebrtc/rtc_base/untyped_function_unittest.cc') 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 +#include + +#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(nullptr); + EXPECT_FALSE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); +} + +TEST(UntypedFunction, CallTrivialWithInt) { + auto uf = UntypedFunction::Create([](int x) { return x + 5; }); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(17), 22); +} + +TEST(UntypedFunction, CallTrivialWithPointer) { + auto uf = UntypedFunction::Create([](int* x) { return *x; }); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + int x = 12; + EXPECT_EQ(uf.Call(&x), 12); +} + +TEST(UntypedFunction, CallTrivialWithReference) { + auto uf = UntypedFunction::Create([](int& x) { x = 3; }); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + int x = 12; + uf.Call(x); + EXPECT_EQ(x, 3); +} + +TEST(UntypedFunction, CallTrivialWithRvalueReference) { + auto uf = UntypedFunction::Create([](int&& x) { return x - 2; }); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(34), 32); +} + +TEST(UntypedFunction, CallNontrivialWithInt) { + std::vector list; + auto uf = UntypedFunction::Create([list](int x) mutable { + list.push_back(x); + return list.size(); + }); + EXPECT_TRUE(uf); + EXPECT_FALSE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(17), 1); + EXPECT_EQ(uf.Call(17), 2); +} + +TEST(UntypedFunction, CallNontrivialWithPointer) { + std::vector list; + auto uf = UntypedFunction::Create([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(&x), Pointee(12)); +} + +TEST(UntypedFunction, CallNontrivialWithReference) { + std::vector list = {34, 35, 36}; + auto uf = + UntypedFunction::Create([list](int& x) { x = list[1]; }); + EXPECT_TRUE(uf); + EXPECT_FALSE(uf.IsTriviallyDestructible()); + int x = 12; + uf.Call(x); + EXPECT_EQ(x, 35); +} + +TEST(UntypedFunction, CallNontrivialWithRvalueReference) { + std::vector list; + auto uf = UntypedFunction::Create([list](int&& x) mutable { + list.push_back(x); + return list.size(); + }); + EXPECT_TRUE(uf); + EXPECT_FALSE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(34), 1); + EXPECT_EQ(uf.Call(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(AddFive); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(17), 22); +} + +TEST(UntypedFunction, CallFunctionPointerWithPointer) { + auto uf = UntypedFunction::Create(DereferencePointer); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + int x = 12; + EXPECT_EQ(uf.Call(&x), 12); +} + +TEST(UntypedFunction, CallFunctionPointerWithReference) { + auto uf = UntypedFunction::Create(AssignThree); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + int x = 12; + uf.Call(x); + EXPECT_EQ(x, 3); +} + +TEST(UntypedFunction, CallFunctionPointerWithRvalueReference) { + auto uf = UntypedFunction::Create(SubtractTwo); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(34), 32); +} + +TEST(UntypedFunction, CallTrivialWithNoArgs) { + int arr[] = {1, 2, 3}; + static_assert(sizeof(arr) <= UntypedFunction::kInlineStorageSize, ""); + auto uf = UntypedFunction::Create([arr] { return arr[1]; }); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(), 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([arr] { return arr[4]; }); + EXPECT_TRUE(uf); + EXPECT_FALSE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(), 5); +} + +TEST(UntypedFunction, MoveonlyReturnValue) { + auto uf = UntypedFunction::Create()>( + [] { return std::make_unique(567); }); + EXPECT_THAT(uf.Call()>(), Pointee(567)); +} + +TEST(UntypedFunction, MoveonlyArgument) { + auto uf = UntypedFunction::Create)>( + [](std::unique_ptr x) { return *x + 19; }); + EXPECT_EQ(uf.Call)>(std::make_unique(40)), 59); +} + +TEST(UntypedFunction, MoveOnlyCallable) { + auto uf = UntypedFunction::Create( + [x = std::make_unique(17)] { return ++*x; }); + EXPECT_TRUE(uf); + EXPECT_FALSE(uf.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(), 18); + EXPECT_EQ(uf.Call(), 19); + UntypedFunction uf2 = std::move(uf); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_FALSE(uf2.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(), 20); + EXPECT_EQ(uf.Call(), 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(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(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(), 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(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([x]() mutable { return ++x; }); + EXPECT_TRUE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + auto y = std::make_unique(113); + auto uf2 = + UntypedFunction::Create([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(), 14); + swap(uf, uf2); + EXPECT_TRUE(uf); + EXPECT_FALSE(uf.IsTriviallyDestructible()); + EXPECT_TRUE(uf2); + EXPECT_TRUE(uf2.IsTriviallyDestructible()); + EXPECT_EQ(uf.Call(), 114); + EXPECT_EQ(uf2.Call(), 15); + + swap(uf, uf3); + EXPECT_FALSE(uf); + EXPECT_TRUE(uf.IsTriviallyDestructible()); + EXPECT_TRUE(uf3); + EXPECT_FALSE(uf3.IsTriviallyDestructible()); + EXPECT_EQ(uf3.Call(), 115); +} + +} // namespace +} // namespace webrtc -- cgit v1.2.3