Fix memory leak in DocumentRecentTabsManager
[chromium-blink-merge.git] / ios / web / crw_browsing_data_store_unittest.mm
blob4fd5b41abf60f163038f168bb37444005b74682b
1 // Copyright 2015 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.
5 #import "ios/web/public/crw_browsing_data_store.h"
7 #include "base/ios/ios_util.h"
8 #include "base/logging.h"
9 #import "base/mac/scoped_nsobject.h"
10 #include "base/memory/scoped_ptr.h"
11 #import "base/test/ios/wait_util.h"
12 #include "ios/web/public/active_state_manager.h"
13 #include "ios/web/public/browser_state.h"
14 #include "ios/web/public/test/test_browser_state.h"
15 #include "ios/web/public/test/test_web_thread_bundle.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
19 // An observer to observe the |mode| key changes to a CRWBrowsingDataStore.
20 // Used for testing purposes.
21 @interface CRWTestBrowsingDataStoreObserver : NSObject
22 // The number of times that the mode of the underlying CRWBrowsingDataStore
23 // changed.
24 @property(nonatomic, assign) NSUInteger modeChangeCount;
26 // |browsingDataStore| cannot be null.
27 - (instancetype)initWithBrowsingDataStore:
28     (CRWBrowsingDataStore*)browsingDataStore NS_DESIGNATED_INITIALIZER;
29 - (instancetype)init NS_UNAVAILABLE;
30 @end
32 @implementation CRWTestBrowsingDataStoreObserver {
33   // The underlying CRWBrowsingDataStore.
34   __weak CRWBrowsingDataStore* _browsingDataStore;
37 @synthesize modeChangeCount = _modeChangeCount;
39 - (instancetype)initWithBrowsingDataStore:
40     (CRWBrowsingDataStore*)browsingDataStore {
41   self = [super init];
42   if (self) {
43     DCHECK(browsingDataStore);
44     [browsingDataStore addObserver:self
45                         forKeyPath:@"mode"
46                            options:0
47                            context:nil];
48     _browsingDataStore = browsingDataStore;
49   }
50   return self;
53 - (void)dealloc {
54   [_browsingDataStore removeObserver:self forKeyPath:@"mode"];
55   [super dealloc];
58 - (void)observeValueForKeyPath:(NSString*)keyPath
59                       ofObject:(id)object
60                         change:(NSDictionary*)change
61                        context:(void*)context {
62   DCHECK([keyPath isEqual:@"mode"]);
63   DCHECK_EQ(_browsingDataStore, object);
65   ++self.modeChangeCount;
68 @end
70 namespace web {
71 namespace {
73 class BrowsingDataStoreTest : public PlatformTest {
74  protected:
75   void SetUp() override {
76     PlatformTest::SetUp();
77     browser_state_.reset(new TestBrowserState());
78     BrowserState::GetActiveStateManager(browser_state_.get())->SetActive(true);
79     browsing_data_store_.reset([[CRWBrowsingDataStore alloc]
80         initWithBrowserState:browser_state_.get()]);
81   }
82   void TearDown() override {
83     // The BrowserState needs to be destroyed first so that it is outlived by
84     // the WebThreadBundle.
85     BrowserState::GetActiveStateManager(browser_state_.get())->SetActive(false);
86     browser_state_.reset();
87     PlatformTest::TearDown();
88   }
90   // Sets the mode of the |browsing_data_store_| to |ACTIVE| and blocks until
91   // the mode has actually been changed.
92   void MakeActive() {
93     [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
94       DCHECK(success);
95     }];
96     base::test::ios::WaitUntilCondition(^bool() {
97       return [browsing_data_store_ mode] == ACTIVE;
98     });
99   }
101   // Sets the mode of the |browsing_data_store_| to |INACTIVE| and blocks until
102   // the mode has actually been changed.
103   void MakeInactive() {
104     [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
105       DCHECK(success);
106     }];
107     base::test::ios::WaitUntilCondition(^bool() {
108       return [browsing_data_store_ mode] == INACTIVE;
109     });
110   }
112   // Removes browsing data of |browsingDataTypes| from the underlying
113   // CRWBrowsingDataStore and waits until the operation finished.
114   void RemoveDataOfTypes(web::BrowsingDataTypes browsing_data_types) {
115     __block BOOL block_was_called = NO;
116     [browsing_data_store_ removeDataOfTypes:browsing_data_types
117                           completionHandler:^{
118                             block_was_called = YES;
119                           }];
120     base::test::ios::WaitUntilCondition(^bool() {
121       return block_was_called;
122     });
123   }
125   // The CRWBrowsingDataStore used for testing purposes.
126   base::scoped_nsobject<CRWBrowsingDataStore> browsing_data_store_;
128  private:
129   // The WebThreadBundle used for testing purposes.
130   TestWebThreadBundle thread_bundle_;
131   // The BrowserState used for testing purposes.
132   scoped_ptr<BrowserState> browser_state_;
135 }  // namespace
137 // Tests that a CRWBrowsingDataStore's initial mode is set correctly and that it
138 // has no pending operations.
139 TEST_F(BrowsingDataStoreTest, InitialModeAndNoPendingOperations) {
140   if (!base::ios::IsRunningOnIOS8OrLater()) {
141     return;
142   }
144   EXPECT_EQ(ACTIVE, [browsing_data_store_ mode]);
145   EXPECT_FALSE([browsing_data_store_ hasPendingOperations]);
148 // Tests that CRWBrowsingDataStore handles several consecutive calls to
149 // |makeActive| and |makeInactive| correctly.
150 TEST_F(BrowsingDataStoreTest, MakeActiveAndInactiveOperations) {
151   if (!base::ios::IsRunningOnIOS8OrLater()) {
152     return;
153   }
155   MakeInactive();
156   base::scoped_nsobject<CRWTestBrowsingDataStoreObserver> observer(
157       [[CRWTestBrowsingDataStoreObserver alloc]
158           initWithBrowsingDataStore:browsing_data_store_]);
159   EXPECT_EQ(0U, [observer modeChangeCount]);
161   __block int callbacks_received_count = 0;
162   void (^unsucessfullCallback)(BOOL) = ^(BOOL success) {
163     ASSERT_TRUE([NSThread isMainThread]);
164     ++callbacks_received_count;
165     BrowsingDataStoreMode mode = [browsing_data_store_ mode];
166     EXPECT_FALSE(success);
167     EXPECT_EQ(CHANGING, mode);
168   };
170   [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
171     EXPECT_EQ(0, callbacks_received_count);
172     unsucessfullCallback(success);
173   }];
174   EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
175   EXPECT_EQ(1U, [observer modeChangeCount]);
177   [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
178     EXPECT_EQ(1, callbacks_received_count);
179     unsucessfullCallback(success);
180   }];
181   EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
183   [browsing_data_store_ makeActiveWithCompletionHandler:^(BOOL success) {
184     EXPECT_EQ(2, callbacks_received_count);
185     unsucessfullCallback(success);
186   }];
187   EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
189   __block BOOL block_was_called = NO;
190   [browsing_data_store_ makeInactiveWithCompletionHandler:^(BOOL success) {
191     ASSERT_TRUE([NSThread isMainThread]);
192     EXPECT_EQ(3, callbacks_received_count);
193     BrowsingDataStoreMode mode = [browsing_data_store_ mode];
194     EXPECT_TRUE(success);
195     EXPECT_EQ(INACTIVE, mode);
196     block_was_called = YES;
197   }];
198   EXPECT_EQ(CHANGING, [browsing_data_store_ mode]);
200   base::test::ios::WaitUntilCondition(^bool{
201     return block_was_called;
202   });
204   EXPECT_EQ(INACTIVE, [browsing_data_store_ mode]);
205   EXPECT_EQ(2U, [observer modeChangeCount]);
208 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:|.
209 TEST_F(BrowsingDataStoreTest, RemoveDataOperations) {
210   if (!base::ios::IsRunningOnIOS8OrLater()) {
211     return;
212   }
214   ASSERT_EQ(ACTIVE, [browsing_data_store_ mode]);
215   // |removeDataOfTypes| is called when the mode was ACTIVE.
216   RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
218   MakeInactive();
219   ASSERT_EQ(INACTIVE, [browsing_data_store_ mode]);
220   // |removeDataOfTypes| is called when the mode was INACTIVE.
221   RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
224 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:| after
225 // a |makeActive| call.
226 TEST_F(BrowsingDataStoreTest, RemoveDataOperationAfterMakeActiveCall) {
227   if (!base::ios::IsRunningOnIOS8OrLater()) {
228     return;
229   }
231   MakeInactive();
232   ASSERT_EQ(INACTIVE, [browsing_data_store_ mode]);
234   [browsing_data_store_ makeActiveWithCompletionHandler:nil];
235   // |removeDataOfTypes| is called immediately after a |makeActive| call.
236   RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
237   EXPECT_EQ(ACTIVE, [browsing_data_store_ mode]);
240 // Tests that CRWBrowsingDataStore correctly handles |removeDataOfTypes:| after
241 // a |makeActive| call.
242 TEST_F(BrowsingDataStoreTest, RemoveDataOperationAfterMakeInactiveCall) {
243   if (!base::ios::IsRunningOnIOS8OrLater()) {
244     return;
245   }
247   ASSERT_EQ(ACTIVE, [browsing_data_store_ mode]);
249   [browsing_data_store_ makeInactiveWithCompletionHandler:nil];
250   // |removeDataOfTypes| is called immediately after a |makeInactive| call.
251   RemoveDataOfTypes(BROWSING_DATA_TYPE_COOKIES);
252   EXPECT_EQ(INACTIVE, [browsing_data_store_ mode]);
255 }  // namespace web