/* * Copyright 2016 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 "api/function_view.h" #include #include #include "test/gtest.h" namespace rtc { namespace { int CallWith33(rtc::FunctionView fv) { return fv ? fv(33) : -1; } int Add33(int x) { return x + 33; } } // namespace // Test the main use case of FunctionView: implicitly converting a callable // argument. TEST(FunctionViewTest, ImplicitConversion) { EXPECT_EQ(38, CallWith33([](int x) { return x + 5; })); EXPECT_EQ(66, CallWith33(Add33)); EXPECT_EQ(-1, CallWith33(nullptr)); } TEST(FunctionViewTest, IntIntLambdaWithoutState) { auto f = [](int x) { return x + 1; }; EXPECT_EQ(18, f(17)); rtc::FunctionView fv(f); EXPECT_TRUE(fv); EXPECT_EQ(18, fv(17)); } TEST(FunctionViewTest, IntVoidLambdaWithState) { int x = 13; auto f = [x]() mutable { return ++x; }; rtc::FunctionView fv(f); EXPECT_TRUE(fv); EXPECT_EQ(14, f()); EXPECT_EQ(15, fv()); EXPECT_EQ(16, f()); EXPECT_EQ(17, fv()); } TEST(FunctionViewTest, IntIntFunction) { rtc::FunctionView fv(Add33); EXPECT_TRUE(fv); EXPECT_EQ(50, fv(17)); } TEST(FunctionViewTest, IntIntFunctionPointer) { rtc::FunctionView fv(&Add33); EXPECT_TRUE(fv); EXPECT_EQ(50, fv(17)); } TEST(FunctionViewTest, Null) { // These two call constructors that statically construct null FunctionViews. EXPECT_FALSE(rtc::FunctionView()); EXPECT_FALSE(rtc::FunctionView(nullptr)); // This calls the constructor for function pointers. EXPECT_FALSE(rtc::FunctionView(reinterpret_cast(0))); } // Ensure that FunctionView handles move-only arguments and return values. TEST(FunctionViewTest, UniquePtrPassthrough) { auto f = [](std::unique_ptr x) { return x; }; rtc::FunctionView(std::unique_ptr)> fv(f); std::unique_ptr x(new int); int* x_addr = x.get(); auto y = fv(std::move(x)); EXPECT_EQ(x_addr, y.get()); } TEST(FunctionViewTest, CopyConstructor) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); rtc::FunctionView fv2(fv1); EXPECT_EQ(17, fv1()); EXPECT_EQ(17, fv2()); } TEST(FunctionViewTest, MoveConstructorIsCopy) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); rtc::FunctionView fv2(std::move(fv1)); // NOLINT EXPECT_EQ(17, fv1()); EXPECT_EQ(17, fv2()); } TEST(FunctionViewTest, CopyAssignment) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); auto f23 = [] { return 23; }; rtc::FunctionView fv2(f23); EXPECT_EQ(17, fv1()); EXPECT_EQ(23, fv2()); fv2 = fv1; EXPECT_EQ(17, fv1()); EXPECT_EQ(17, fv2()); } TEST(FunctionViewTest, MoveAssignmentIsCopy) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); auto f23 = [] { return 23; }; rtc::FunctionView fv2(f23); EXPECT_EQ(17, fv1()); EXPECT_EQ(23, fv2()); fv2 = std::move(fv1); // NOLINT EXPECT_EQ(17, fv1()); EXPECT_EQ(17, fv2()); } TEST(FunctionViewTest, Swap) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); auto f23 = [] { return 23; }; rtc::FunctionView fv2(f23); EXPECT_EQ(17, fv1()); EXPECT_EQ(23, fv2()); using std::swap; swap(fv1, fv2); EXPECT_EQ(23, fv1()); EXPECT_EQ(17, fv2()); } // Ensure that when you copy-construct a FunctionView, the new object points to // the same function as the old one (as opposed to the new object pointing to // the old one). TEST(FunctionViewTest, CopyConstructorChaining) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); rtc::FunctionView fv2(fv1); EXPECT_EQ(17, fv1()); EXPECT_EQ(17, fv2()); auto f23 = [] { return 23; }; fv1 = f23; EXPECT_EQ(23, fv1()); EXPECT_EQ(17, fv2()); } // Ensure that when you assign one FunctionView to another, we actually make a // copy (as opposed to making the second FunctionView point to the first one). TEST(FunctionViewTest, CopyAssignmentChaining) { auto f17 = [] { return 17; }; rtc::FunctionView fv1(f17); rtc::FunctionView fv2; EXPECT_TRUE(fv1); EXPECT_EQ(17, fv1()); EXPECT_FALSE(fv2); fv2 = fv1; EXPECT_EQ(17, fv1()); EXPECT_EQ(17, fv2()); auto f23 = [] { return 23; }; fv1 = f23; EXPECT_EQ(23, fv1()); EXPECT_EQ(17, fv2()); } } // namespace rtc