droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 1 | // Copyright 2013 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 | |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 5 | #include "base/ios/weak_nsobject.h" |
Sami Kyostila | 21f4d4c | 2018-11-29 11:11:36 | [diff] [blame] | 6 | #include "base/bind.h" |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 7 | #include "base/mac/scoped_nsobject.h" |
fdoray | 2df4a9e | 2016-07-18 23:47:16 | [diff] [blame] | 8 | #include "base/run_loop.h" |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 9 | #include "base/single_thread_task_runner.h" |
Sami Kyostila | 21f4d4c | 2018-11-29 11:11:36 | [diff] [blame] | 10 | #include "base/test/scoped_task_environment.h" |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 11 | #include "base/threading/thread.h" |
Sami Kyostila | 21f4d4c | 2018-11-29 11:11:36 | [diff] [blame] | 12 | #include "base/threading/thread_task_runner_handle.h" |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 13 | #include "testing/gtest/include/gtest/gtest.h" |
| 14 | |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 15 | namespace base { |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 16 | namespace { |
| 17 | |
| 18 | TEST(WeakNSObjectTest, WeakNSObject) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 19 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 20 | WeakNSObject<NSObject> w1(p1); |
| 21 | EXPECT_TRUE(w1); |
| 22 | p1.reset(); |
| 23 | EXPECT_FALSE(w1); |
| 24 | } |
| 25 | |
| 26 | TEST(WeakNSObjectTest, MultipleWeakNSObject) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 27 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 28 | WeakNSObject<NSObject> w1(p1); |
| 29 | WeakNSObject<NSObject> w2(w1); |
| 30 | EXPECT_TRUE(w1); |
| 31 | EXPECT_TRUE(w2); |
| 32 | EXPECT_TRUE(w1.get() == w2.get()); |
| 33 | p1.reset(); |
| 34 | EXPECT_FALSE(w1); |
| 35 | EXPECT_FALSE(w2); |
| 36 | } |
| 37 | |
| 38 | TEST(WeakNSObjectTest, WeakNSObjectDies) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 39 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 40 | { |
| 41 | WeakNSObject<NSObject> w1(p1); |
| 42 | EXPECT_TRUE(w1); |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | TEST(WeakNSObjectTest, WeakNSObjectReset) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 47 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 48 | WeakNSObject<NSObject> w1(p1); |
| 49 | EXPECT_TRUE(w1); |
| 50 | w1.reset(); |
| 51 | EXPECT_FALSE(w1); |
| 52 | EXPECT_TRUE(p1); |
| 53 | EXPECT_TRUE([p1 description]); |
| 54 | } |
| 55 | |
| 56 | TEST(WeakNSObjectTest, WeakNSObjectResetWithObject) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 57 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
| 58 | scoped_nsobject<NSObject> p2([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 59 | WeakNSObject<NSObject> w1(p1); |
| 60 | EXPECT_TRUE(w1); |
| 61 | w1.reset(p2); |
| 62 | EXPECT_TRUE(w1); |
| 63 | EXPECT_TRUE([p1 description]); |
| 64 | EXPECT_TRUE([p2 description]); |
| 65 | } |
| 66 | |
| 67 | TEST(WeakNSObjectTest, WeakNSObjectEmpty) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 68 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 69 | WeakNSObject<NSObject> w1; |
| 70 | EXPECT_FALSE(w1); |
| 71 | w1.reset(p1); |
| 72 | EXPECT_TRUE(w1); |
| 73 | p1.reset(); |
| 74 | EXPECT_FALSE(w1); |
| 75 | } |
| 76 | |
| 77 | TEST(WeakNSObjectTest, WeakNSObjectCopy) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 78 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 79 | WeakNSObject<NSObject> w1(p1); |
| 80 | WeakNSObject<NSObject> w2(w1); |
| 81 | EXPECT_TRUE(w1); |
| 82 | EXPECT_TRUE(w2); |
| 83 | p1.reset(); |
| 84 | EXPECT_FALSE(w1); |
| 85 | EXPECT_FALSE(w2); |
| 86 | } |
| 87 | |
| 88 | TEST(WeakNSObjectTest, WeakNSObjectAssignment) { |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 89 | scoped_nsobject<NSObject> p1([[NSObject alloc] init]); |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 90 | WeakNSObject<NSObject> w1(p1); |
| 91 | WeakNSObject<NSObject> w2; |
| 92 | EXPECT_FALSE(w2); |
| 93 | w2 = w1; |
| 94 | EXPECT_TRUE(w1); |
| 95 | EXPECT_TRUE(w2); |
| 96 | p1.reset(); |
| 97 | EXPECT_FALSE(w1); |
| 98 | EXPECT_FALSE(w2); |
| 99 | } |
| 100 | |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 101 | // Touches |weak_data| by increasing its length by 1. Used to check that the |
| 102 | // weak object can be dereferenced. |
| 103 | void TouchWeakData(const WeakNSObject<NSMutableData>& weak_data) { |
| 104 | if (!weak_data) |
| 105 | return; |
| 106 | [weak_data increaseLengthBy:1]; |
| 107 | } |
| 108 | |
| 109 | // Makes a copy of |weak_object| on the current thread and posts a task to touch |
| 110 | // the weak object on its original thread. |
| 111 | void CopyWeakNSObjectAndPost(const WeakNSObject<NSMutableData>& weak_object, |
| 112 | scoped_refptr<SingleThreadTaskRunner> runner) { |
droger | 1fd547a | 2015-03-17 15:13:08 | [diff] [blame] | 113 | // Copy using constructor. |
| 114 | WeakNSObject<NSMutableData> weak_copy1(weak_object); |
kylechar | 60486b0 | 2019-02-19 19:00:04 | [diff] [blame] | 115 | runner->PostTask(FROM_HERE, BindOnce(&TouchWeakData, weak_copy1)); |
droger | 1fd547a | 2015-03-17 15:13:08 | [diff] [blame] | 116 | // Copy using assignment operator. |
| 117 | WeakNSObject<NSMutableData> weak_copy2 = weak_object; |
kylechar | 60486b0 | 2019-02-19 19:00:04 | [diff] [blame] | 118 | runner->PostTask(FROM_HERE, BindOnce(&TouchWeakData, weak_copy2)); |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | // Tests that the weak object can be copied on a different thread. |
| 122 | TEST(WeakNSObjectTest, WeakNSObjectCopyOnOtherThread) { |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame^] | 123 | test::TaskEnvironment task_environment; |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 124 | Thread other_thread("WeakNSObjectCopyOnOtherThread"); |
| 125 | other_thread.Start(); |
| 126 | |
| 127 | scoped_nsobject<NSMutableData> data([[NSMutableData alloc] init]); |
| 128 | WeakNSObject<NSMutableData> weak(data); |
| 129 | |
Sami Kyostila | 21f4d4c | 2018-11-29 11:11:36 | [diff] [blame] | 130 | scoped_refptr<SingleThreadTaskRunner> runner = ThreadTaskRunnerHandle::Get(); |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 131 | other_thread.task_runner()->PostTask( |
kylechar | 60486b0 | 2019-02-19 19:00:04 | [diff] [blame] | 132 | FROM_HERE, BindOnce(&CopyWeakNSObjectAndPost, weak, runner)); |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 133 | other_thread.Stop(); |
fdoray | 2df4a9e | 2016-07-18 23:47:16 | [diff] [blame] | 134 | RunLoop().RunUntilIdle(); |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 135 | |
droger | 1fd547a | 2015-03-17 15:13:08 | [diff] [blame] | 136 | // Check that TouchWeakData was called and the object touched twice. |
| 137 | EXPECT_EQ(2u, [data length]); |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 138 | } |
| 139 | |
droger | c6762659 | 2014-12-12 17:39:02 | [diff] [blame] | 140 | } // namespace |
droger | 4f05f5a8 | 2015-01-16 11:33:52 | [diff] [blame] | 141 | } // namespace base |