bind_objc_block_unittest.mm 4.3 KB

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