1// Copyright 2012 The Chromium Authors 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <string> 6 7#include "base/functional/bind.h" 8#include "base/functional/callback.h" 9#include "base/functional/callback_helpers.h" 10#include "testing/gtest/include/gtest/gtest.h" 11#include "testing/gtest_mac.h" 12 13namespace { 14 15TEST(BindObjcBlockTest, TestScopedClosureRunnerExitScope) { 16 int run_count = 0; 17 int* ptr = &run_count; 18 { 19 base::ScopedClosureRunner runner(base::BindOnce(^{ 20 (*ptr)++; 21 })); 22 EXPECT_EQ(0, run_count); 23 } 24 EXPECT_EQ(1, run_count); 25} 26 27TEST(BindObjcBlockTest, TestScopedClosureRunnerRelease) { 28 int run_count = 0; 29 int* ptr = &run_count; 30 base::OnceClosure c; 31 { 32 base::ScopedClosureRunner runner(base::BindOnce(^{ 33 (*ptr)++; 34 })); 35 c = runner.Release(); 36 EXPECT_EQ(0, run_count); 37 } 38 EXPECT_EQ(0, run_count); 39 std::move(c).Run(); 40 EXPECT_EQ(1, run_count); 41} 42 43TEST(BindObjcBlockTest, TestReturnValue) { 44 const int kReturnValue = 42; 45 base::OnceCallback<int(void)> c = base::BindOnce(^{ 46 return kReturnValue; 47 }); 48 EXPECT_EQ(kReturnValue, std::move(c).Run()); 49} 50 51TEST(BindObjcBlockTest, TestArgument) { 52 const int kArgument = 42; 53 base::OnceCallback<int(int)> c = base::BindOnce(^(int a) { 54 return a + 1; 55 }); 56 EXPECT_EQ(kArgument + 1, std::move(c).Run(kArgument)); 57} 58 59TEST(BindObjcBlockTest, TestTwoArguments) { 60 std::string result; 61 std::string* ptr = &result; 62 base::OnceCallback<void(const std::string&, const std::string&)> c = 63 base::BindOnce(^(const std::string& a, const std::string& b) { 64 *ptr = a + b; 65 }); 66 std::move(c).Run("forty", "two"); 67 EXPECT_EQ(result, "fortytwo"); 68} 69 70TEST(BindObjcBlockTest, TestThreeArguments) { 71 std::string result; 72 std::string* ptr = &result; 73 base::OnceCallback<void(const std::string&, const std::string&, 74 const std::string&)> 75 cb = base::BindOnce( 76 ^(const std::string& a, const std::string& b, const std::string& c) { 77 *ptr = a + b + c; 78 }); 79 std::move(cb).Run("six", "times", "nine"); 80 EXPECT_EQ(result, "sixtimesnine"); 81} 82 83TEST(BindObjcBlockTest, TestSixArguments) { 84 std::string result1; 85 std::string* ptr = &result1; 86 int result2; 87 int* ptr2 = &result2; 88 base::OnceCallback<void(int, int, const std::string&, const std::string&, int, 89 const std::string&)> 90 cb = base::BindOnce(^(int a, int b, const std::string& c, 91 const std::string& d, int e, const std::string& f) { 92 *ptr = c + d + f; 93 *ptr2 = a + b + e; 94 }); 95 std::move(cb).Run(1, 2, "infinite", "improbability", 3, "drive"); 96 EXPECT_EQ(result1, "infiniteimprobabilitydrive"); 97 EXPECT_EQ(result2, 6); 98} 99 100TEST(BindObjcBlockTest, TestBlockMoveable) { 101 base::OnceClosure c; 102 __block BOOL invoked_block = NO; 103 @autoreleasepool { 104 c = base::BindOnce( 105 ^(std::unique_ptr<BOOL> v) { 106 invoked_block = *v; 107 }, 108 std::make_unique<BOOL>(YES)); 109 } 110 std::move(c).Run(); 111 EXPECT_TRUE(invoked_block); 112} 113 114// Tests that the bound block is retained until the end of its execution, even 115// if the callback itself is destroyed during the invocation. It was found that 116// some code depends on this behaviour (see https://crbug.com/845687). 117TEST(BindObjcBlockTest, TestBlockDeallocation) { 118 base::RepeatingClosure closure; 119 __block BOOL invoked_block = NO; 120 closure = base::BindRepeating( 121 ^(base::RepeatingClosure* this_closure) { 122 *this_closure = base::RepeatingClosure(); 123 invoked_block = YES; 124 }, 125 &closure); 126 closure.Run(); 127 EXPECT_TRUE(invoked_block); 128} 129 130TEST(BindObjcBlockTest, TestBlockReleased) { 131 __weak NSObject* weak_nsobject; 132 @autoreleasepool { 133 NSObject* nsobject = [[NSObject alloc] init]; 134 weak_nsobject = nsobject; 135 136 auto callback = base::BindOnce(^{ 137 [nsobject description]; 138 }); 139 } 140 EXPECT_NSEQ(nil, weak_nsobject); 141} 142 143} // namespace 144