blob: 6ee78e58e1edd264da15b1c432163e68b35d6010 [file] [log] [blame]
drogerc67626592014-12-12 17:39:021// 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
drogerc67626592014-12-12 17:39:025#include "base/ios/weak_nsobject.h"
Sami Kyostila21f4d4c2018-11-29 11:11:366#include "base/bind.h"
drogerc67626592014-12-12 17:39:027#include "base/mac/scoped_nsobject.h"
fdoray2df4a9e2016-07-18 23:47:168#include "base/run_loop.h"
droger4f05f5a82015-01-16 11:33:529#include "base/single_thread_task_runner.h"
Sami Kyostila21f4d4c2018-11-29 11:11:3610#include "base/test/scoped_task_environment.h"
droger4f05f5a82015-01-16 11:33:5211#include "base/threading/thread.h"
Sami Kyostila21f4d4c2018-11-29 11:11:3612#include "base/threading/thread_task_runner_handle.h"
drogerc67626592014-12-12 17:39:0213#include "testing/gtest/include/gtest/gtest.h"
14
droger4f05f5a82015-01-16 11:33:5215namespace base {
drogerc67626592014-12-12 17:39:0216namespace {
17
18TEST(WeakNSObjectTest, WeakNSObject) {
droger4f05f5a82015-01-16 11:33:5219 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0220 WeakNSObject<NSObject> w1(p1);
21 EXPECT_TRUE(w1);
22 p1.reset();
23 EXPECT_FALSE(w1);
24}
25
26TEST(WeakNSObjectTest, MultipleWeakNSObject) {
droger4f05f5a82015-01-16 11:33:5227 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0228 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
38TEST(WeakNSObjectTest, WeakNSObjectDies) {
droger4f05f5a82015-01-16 11:33:5239 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0240 {
41 WeakNSObject<NSObject> w1(p1);
42 EXPECT_TRUE(w1);
43 }
44}
45
46TEST(WeakNSObjectTest, WeakNSObjectReset) {
droger4f05f5a82015-01-16 11:33:5247 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0248 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
56TEST(WeakNSObjectTest, WeakNSObjectResetWithObject) {
droger4f05f5a82015-01-16 11:33:5257 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
58 scoped_nsobject<NSObject> p2([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0259 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
67TEST(WeakNSObjectTest, WeakNSObjectEmpty) {
droger4f05f5a82015-01-16 11:33:5268 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0269 WeakNSObject<NSObject> w1;
70 EXPECT_FALSE(w1);
71 w1.reset(p1);
72 EXPECT_TRUE(w1);
73 p1.reset();
74 EXPECT_FALSE(w1);
75}
76
77TEST(WeakNSObjectTest, WeakNSObjectCopy) {
droger4f05f5a82015-01-16 11:33:5278 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0279 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
88TEST(WeakNSObjectTest, WeakNSObjectAssignment) {
droger4f05f5a82015-01-16 11:33:5289 scoped_nsobject<NSObject> p1([[NSObject alloc] init]);
drogerc67626592014-12-12 17:39:0290 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
droger4f05f5a82015-01-16 11:33:52101// Touches |weak_data| by increasing its length by 1. Used to check that the
102// weak object can be dereferenced.
103void 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.
111void CopyWeakNSObjectAndPost(const WeakNSObject<NSMutableData>& weak_object,
112 scoped_refptr<SingleThreadTaskRunner> runner) {
droger1fd547a2015-03-17 15:13:08113 // Copy using constructor.
114 WeakNSObject<NSMutableData> weak_copy1(weak_object);
kylechar60486b02019-02-19 19:00:04115 runner->PostTask(FROM_HERE, BindOnce(&TouchWeakData, weak_copy1));
droger1fd547a2015-03-17 15:13:08116 // Copy using assignment operator.
117 WeakNSObject<NSMutableData> weak_copy2 = weak_object;
kylechar60486b02019-02-19 19:00:04118 runner->PostTask(FROM_HERE, BindOnce(&TouchWeakData, weak_copy2));
droger4f05f5a82015-01-16 11:33:52119}
120
121// Tests that the weak object can be copied on a different thread.
122TEST(WeakNSObjectTest, WeakNSObjectCopyOnOtherThread) {
Gabriel Charette694c3c332019-08-19 14:53:05123 test::TaskEnvironment task_environment;
droger4f05f5a82015-01-16 11:33:52124 Thread other_thread("WeakNSObjectCopyOnOtherThread");
125 other_thread.Start();
126
127 scoped_nsobject<NSMutableData> data([[NSMutableData alloc] init]);
128 WeakNSObject<NSMutableData> weak(data);
129
Sami Kyostila21f4d4c2018-11-29 11:11:36130 scoped_refptr<SingleThreadTaskRunner> runner = ThreadTaskRunnerHandle::Get();
droger4f05f5a82015-01-16 11:33:52131 other_thread.task_runner()->PostTask(
kylechar60486b02019-02-19 19:00:04132 FROM_HERE, BindOnce(&CopyWeakNSObjectAndPost, weak, runner));
droger4f05f5a82015-01-16 11:33:52133 other_thread.Stop();
fdoray2df4a9e2016-07-18 23:47:16134 RunLoop().RunUntilIdle();
droger4f05f5a82015-01-16 11:33:52135
droger1fd547a2015-03-17 15:13:08136 // Check that TouchWeakData was called and the object touched twice.
137 EXPECT_EQ(2u, [data length]);
droger4f05f5a82015-01-16 11:33:52138}
139
drogerc67626592014-12-12 17:39:02140} // namespace
droger4f05f5a82015-01-16 11:33:52141} // namespace base