bind_objc_block_unittest_arc.mm 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 !defined(__has_feature) || !__has_feature(objc_arc)
  12. #error "This file requires ARC support."
  13. #endif
  14. namespace {
  15. TEST(BindObjcBlockTestARC, 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. TEST(BindObjcBlockTestARC, TestScopedClosureRunnerRelease) {
  27. int run_count = 0;
  28. int* ptr = &run_count;
  29. base::OnceClosure c;
  30. {
  31. base::ScopedClosureRunner runner(base::BindOnce(^{
  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(BindObjcBlockTestARC, TestReturnValue) {
  42. const int kReturnValue = 42;
  43. base::OnceCallback<int(void)> c = base::BindOnce(^{
  44. return kReturnValue;
  45. });
  46. EXPECT_EQ(kReturnValue, std::move(c).Run());
  47. }
  48. TEST(BindObjcBlockTestARC, TestArgument) {
  49. const int kArgument = 42;
  50. base::OnceCallback<int(int)> c = base::BindOnce(^(int a) {
  51. return a + 1;
  52. });
  53. EXPECT_EQ(kArgument + 1, std::move(c).Run(kArgument));
  54. }
  55. TEST(BindObjcBlockTestARC, TestTwoArguments) {
  56. std::string result;
  57. std::string* ptr = &result;
  58. base::OnceCallback<void(const std::string&, const std::string&)> c =
  59. base::BindOnce(^(const std::string& a, const std::string& b) {
  60. *ptr = a + b;
  61. });
  62. std::move(c).Run("forty", "two");
  63. EXPECT_EQ(result, "fortytwo");
  64. }
  65. TEST(BindObjcBlockTestARC, TestThreeArguments) {
  66. std::string result;
  67. std::string* ptr = &result;
  68. base::OnceCallback<void(const std::string&, const std::string&,
  69. const std::string&)>
  70. cb = base::BindOnce(
  71. ^(const std::string& a, const std::string& b, const std::string& c) {
  72. *ptr = a + b + c;
  73. });
  74. std::move(cb).Run("six", "times", "nine");
  75. EXPECT_EQ(result, "sixtimesnine");
  76. }
  77. TEST(BindObjcBlockTestARC, TestSixArguments) {
  78. std::string result1;
  79. std::string* ptr = &result1;
  80. int result2;
  81. int* ptr2 = &result2;
  82. base::OnceCallback<void(int, int, const std::string&, const std::string&, int,
  83. const std::string&)>
  84. cb = base::BindOnce(^(int a, int b, const std::string& c,
  85. const std::string& d, int e, const std::string& f) {
  86. *ptr = c + d + f;
  87. *ptr2 = a + b + e;
  88. });
  89. std::move(cb).Run(1, 2, "infinite", "improbability", 3, "drive");
  90. EXPECT_EQ(result1, "infiniteimprobabilitydrive");
  91. EXPECT_EQ(result2, 6);
  92. }
  93. TEST(BindObjcBlockTestARC, TestBlockMoveable) {
  94. base::OnceClosure c;
  95. __block BOOL invoked_block = NO;
  96. @autoreleasepool {
  97. c = base::BindOnce(
  98. ^(std::unique_ptr<BOOL> v) {
  99. invoked_block = *v;
  100. },
  101. std::make_unique<BOOL>(YES));
  102. }
  103. std::move(c).Run();
  104. EXPECT_TRUE(invoked_block);
  105. }
  106. // Tests that the bound block is retained until the end of its execution,
  107. // even if the callback itself is destroyed during the invocation. It was
  108. // found that some code depends on this behaviour (see crbug.com/845687).
  109. TEST(BindObjcBlockTestARC, TestBlockDeallocation) {
  110. base::RepeatingClosure closure;
  111. __block BOOL invoked_block = NO;
  112. closure = base::BindRepeating(
  113. ^(base::RepeatingClosure* this_closure) {
  114. *this_closure = base::RepeatingClosure();
  115. invoked_block = YES;
  116. },
  117. &closure);
  118. closure.Run();
  119. EXPECT_TRUE(invoked_block);
  120. }
  121. #if BUILDFLAG(IS_IOS)
  122. TEST(BindObjcBlockTestARC, TestBlockReleased) {
  123. __weak NSObject* weak_nsobject;
  124. @autoreleasepool {
  125. NSObject* nsobject = [[NSObject alloc] init];
  126. weak_nsobject = nsobject;
  127. auto callback = base::BindOnce(^{
  128. [nsobject description];
  129. });
  130. }
  131. EXPECT_NSEQ(nil, weak_nsobject);
  132. }
  133. #endif
  134. } // namespace