OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 | |
5 #include "chrome/browser/android/offline_pages/background_loader_offliner.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/run_loop.h" | |
9 #include "base/threading/thread_task_runner_handle.h" | |
10 #include "chrome/test/base/testing_profile.h" | |
11 #include "components/offline_pages/content/background_loader/background_loader_c ontents_stub.h" | |
12 #include "components/offline_pages/core/background/offliner.h" | |
13 #include "components/offline_pages/core/background/save_page_request.h" | |
14 #include "components/offline_pages/core/stub_offline_page_model.h" | |
15 #include "content/public/test/test_browser_thread_bundle.h" | |
16 #include "content/public/test/web_contents_tester.h" | |
17 #include "testing/gtest/include/gtest/gtest.h" | |
18 | |
19 namespace offline_pages { | |
20 | |
21 namespace { | |
22 | |
23 const int64_t kRequestId = 7; | |
24 const GURL kHttpUrl("http://www.tunafish.com"); | |
25 const GURL kFileUrl("file://salmon.png"); | |
26 const ClientId kClientId("AsyncLoading", "88"); | |
27 const bool kUserRequested = true; | |
28 | |
29 // Mock OfflinePageModel for testing the SavePage calls | |
30 class MockOfflinePageModel : public StubOfflinePageModel { | |
Pete Williamson
2016/12/10 01:52:54
I wonder if this could be split out into a separat
| |
31 public: | |
32 MockOfflinePageModel() : mock_saving_(false) {} | |
33 ~MockOfflinePageModel() override {} | |
34 | |
35 void SavePage(const SavePageParams& save_page_params, | |
36 std::unique_ptr<OfflinePageArchiver> archiver, | |
37 const SavePageCallback& callback) override { | |
38 mock_saving_ = true; | |
39 save_page_callback_ = callback; | |
40 } | |
41 | |
42 void CompleteSavingAsArchiveCreationFailed() { | |
43 DCHECK(mock_saving_); | |
44 mock_saving_ = false; | |
45 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
46 FROM_HERE, base::Bind(save_page_callback_, | |
47 SavePageResult::ARCHIVE_CREATION_FAILED, 0)); | |
48 } | |
49 | |
50 void CompleteSavingAsSuccess() { | |
51 DCHECK(mock_saving_); | |
52 mock_saving_ = false; | |
53 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
54 FROM_HERE, | |
55 base::Bind(save_page_callback_, SavePageResult::SUCCESS, 123456)); | |
56 } | |
57 | |
58 bool mock_saving() const { return mock_saving_; } | |
59 | |
60 private: | |
61 bool mock_saving_; | |
62 SavePageCallback save_page_callback_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(MockOfflinePageModel); | |
65 }; | |
66 | |
67 void PumpLoop() { | |
68 base::RunLoop().RunUntilIdle(); | |
69 } | |
70 } // namespace | |
71 | |
72 // A BackgroundLoader that we can run tests on. | |
73 // Overrides the ResetState so we don't actually try to create any web contents. | |
74 // This is a temporary solution to test core BackgroundLoaderOffliner | |
75 // functionality until we straighten out assumptions made by RequestCoordinator | |
76 // so that the ResetState method is no longer needed. | |
77 class TestBackgroundLoaderOffliner : public BackgroundLoaderOffliner { | |
78 public: | |
79 explicit TestBackgroundLoaderOffliner( | |
80 content::BrowserContext* browser_context, | |
81 const OfflinerPolicy* policy, | |
82 OfflinePageModel* offline_page_model); | |
83 ~TestBackgroundLoaderOffliner() override; | |
84 content::WebContentsTester* web_contents() { | |
85 return content::WebContentsTester::For(stub_->web_contents()); | |
86 } | |
87 | |
88 bool is_loading() { return stub_->is_loading(); } | |
89 | |
90 protected: | |
91 void ResetState() override; | |
92 | |
93 private: | |
94 background_loader::BackgroundLoaderContentsStub* stub_; | |
95 }; | |
96 | |
97 TestBackgroundLoaderOffliner::TestBackgroundLoaderOffliner( | |
98 content::BrowserContext* browser_context, | |
99 const OfflinerPolicy* policy, | |
100 OfflinePageModel* offline_page_model) | |
101 : BackgroundLoaderOffliner(browser_context, policy, offline_page_model) {} | |
102 | |
103 TestBackgroundLoaderOffliner::~TestBackgroundLoaderOffliner() {} | |
104 | |
105 void TestBackgroundLoaderOffliner::ResetState() { | |
106 stub_ = new background_loader::BackgroundLoaderContentsStub(browser_context_); | |
107 loader_.reset(stub_); | |
108 content::WebContentsObserver::Observe(stub_->web_contents()); | |
109 } | |
110 | |
111 class BackgroundLoaderOfflinerTest : public testing::Test { | |
112 public: | |
113 BackgroundLoaderOfflinerTest(); | |
114 ~BackgroundLoaderOfflinerTest() override; | |
115 | |
116 void SetUp() override; | |
117 | |
118 TestBackgroundLoaderOffliner* offliner() const { return offliner_.get(); } | |
Pete Williamson
2016/12/10 01:52:54
Can this return the BackgroundLoaderOffliner inste
chili
2016/12/15 10:34:39
The Test has methods to call is_loading() (returns
| |
119 Offliner::CompletionCallback const callback() { | |
120 return base::Bind(&BackgroundLoaderOfflinerTest::OnCompletion, | |
121 base::Unretained(this)); | |
122 } | |
123 Profile* profile() { return &profile_; } | |
124 bool completion_callback_called() { return completion_callback_called_; } | |
125 Offliner::RequestStatus request_status() { return request_status_; } | |
126 bool SaveInProgress() const { return model_->mock_saving(); } | |
127 MockOfflinePageModel* model() const { return model_; } | |
128 | |
129 void CompleteLoading() { | |
130 offliner()->web_contents()->TestSetIsLoading(false); | |
131 } | |
132 | |
133 private: | |
134 void OnCompletion(const SavePageRequest& request, | |
135 Offliner::RequestStatus status); | |
136 content::TestBrowserThreadBundle thread_bundle_; | |
137 TestingProfile profile_; | |
138 std::unique_ptr<TestBackgroundLoaderOffliner> offliner_; | |
139 MockOfflinePageModel* model_; | |
140 bool completion_callback_called_; | |
141 Offliner::RequestStatus request_status_; | |
142 | |
143 DISALLOW_COPY_AND_ASSIGN(BackgroundLoaderOfflinerTest); | |
144 }; | |
145 | |
146 BackgroundLoaderOfflinerTest::BackgroundLoaderOfflinerTest() | |
147 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | |
Pete Williamson
2016/12/10 01:52:54
Why use TestBrowserThreadBundle instead of ThreadT
dougarnett
2016/12/12 19:24:17
Not sure but I have faint recollection of needing
chili
2016/12/15 10:34:39
thread_task_runner_handle.cc fails with a "Must be
| |
148 completion_callback_called_(false), | |
149 request_status_(Offliner::RequestStatus::UNKNOWN) {} | |
150 | |
151 BackgroundLoaderOfflinerTest::~BackgroundLoaderOfflinerTest() {} | |
152 | |
153 void BackgroundLoaderOfflinerTest::SetUp() { | |
154 model_ = new MockOfflinePageModel(); | |
155 offliner_.reset(new TestBackgroundLoaderOffliner(profile(), nullptr, model_)); | |
156 } | |
157 | |
158 void BackgroundLoaderOfflinerTest::OnCompletion( | |
159 const SavePageRequest& request, | |
160 Offliner::RequestStatus status) { | |
161 DCHECK(!completion_callback_called_); // Expect 1 callback per request. | |
162 completion_callback_called_ = true; | |
163 request_status_ = status; | |
164 } | |
165 | |
166 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoading) { | |
167 base::Time creation_time = base::Time::Now(); | |
168 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
169 kUserRequested); | |
170 EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); | |
171 EXPECT_TRUE(offliner()->is_loading()); | |
172 | |
173 offliner()->Cancel(); | |
174 EXPECT_FALSE(offliner()->is_loading()); | |
175 } | |
176 | |
177 TEST_F(BackgroundLoaderOfflinerTest, CancelWhenLoaded) { | |
178 base::Time creation_time = base::Time::Now(); | |
179 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
180 kUserRequested); | |
181 EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); | |
182 EXPECT_TRUE(offliner()->is_loading()); | |
183 | |
184 CompleteLoading(); | |
185 PumpLoop(); | |
186 EXPECT_FALSE(completion_callback_called()); | |
187 // Save still in progress because does not support canceling. | |
Pete Williamson
2016/12/10 01:52:54
So what happens on a call to cancel when save is i
dougarnett
2016/12/12 19:24:17
This is a hole. We should have some bug opened or
dougarnett
2016/12/12 19:33:28
Actually, what happens to WebContents when ResetSt
chili
2016/12/15 10:34:39
This is a good point. ResetState would delete the
| |
188 EXPECT_TRUE(SaveInProgress()); | |
189 offliner()->Cancel(); | |
190 | |
191 // Subsequent save callback cause no crash. | |
192 model()->CompleteSavingAsArchiveCreationFailed(); | |
193 PumpLoop(); | |
194 EXPECT_FALSE(completion_callback_called()); | |
195 EXPECT_FALSE(SaveInProgress()); | |
196 } | |
197 | |
198 TEST_F(BackgroundLoaderOfflinerTest, LoadedButSaveFails) { | |
199 base::Time creation_time = base::Time::Now(); | |
200 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
201 kUserRequested); | |
202 EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); | |
203 EXPECT_TRUE(offliner()->is_loading()); | |
204 | |
205 CompleteLoading(); | |
206 PumpLoop(); | |
207 model()->CompleteSavingAsArchiveCreationFailed(); | |
208 PumpLoop(); | |
209 EXPECT_TRUE(completion_callback_called()); | |
210 EXPECT_EQ(Offliner::RequestStatus::SAVE_FAILED, request_status()); | |
211 EXPECT_FALSE(offliner()->is_loading()); | |
212 EXPECT_FALSE(SaveInProgress()); | |
213 } | |
214 | |
215 TEST_F(BackgroundLoaderOfflinerTest, LoadAndSaveSuccess) { | |
216 base::Time creation_time = base::Time::Now(); | |
217 SavePageRequest request(kRequestId, kHttpUrl, kClientId, creation_time, | |
218 kUserRequested); | |
219 EXPECT_TRUE(offliner()->LoadAndSave(request, callback())); | |
220 EXPECT_TRUE(offliner()->is_loading()); | |
221 EXPECT_EQ(Offliner::RequestStatus::UNKNOWN, request_status()); | |
222 | |
223 CompleteLoading(); | |
224 PumpLoop(); | |
225 EXPECT_FALSE(completion_callback_called()); | |
226 EXPECT_TRUE(SaveInProgress()); | |
227 | |
228 model()->CompleteSavingAsSuccess(); | |
229 PumpLoop(); | |
230 EXPECT_TRUE(completion_callback_called()); | |
231 EXPECT_EQ(Offliner::RequestStatus::SAVED, request_status()); | |
232 EXPECT_FALSE(offliner()->is_loading()); | |
233 EXPECT_FALSE(SaveInProgress()); | |
234 } | |
235 | |
236 } // namespace offline_pages | |
OLD | NEW |