OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | |
5 #include <map> | 6 #include <map> |
6 #include <string> | 7 #include <string> |
7 #include <vector> | 8 #include <vector> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
11 #include "base/location.h" | 12 #include "base/location.h" |
12 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
13 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
14 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
15 #include "base/values.h" | 16 #include "base/values.h" |
17 #include "components/dom_distiller/core/article_distillation_update.h" | |
16 #include "components/dom_distiller/core/distiller.h" | 18 #include "components/dom_distiller/core/distiller.h" |
17 #include "components/dom_distiller/core/distiller_page.h" | 19 #include "components/dom_distiller/core/distiller_page.h" |
18 #include "components/dom_distiller/core/proto/distilled_article.pb.h" | 20 #include "components/dom_distiller/core/proto/distilled_article.pb.h" |
19 #include "components/dom_distiller/core/proto/distilled_page.pb.h" | 21 #include "components/dom_distiller/core/proto/distilled_page.pb.h" |
20 #include "net/url_request/url_request_context_getter.h" | 22 #include "net/url_request/url_request_context_getter.h" |
21 #include "testing/gmock/include/gmock/gmock.h" | 23 #include "testing/gmock/include/gmock/gmock.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
23 | 25 |
24 using std::vector; | 26 using std::vector; |
25 using std::string; | 27 using std::string; |
26 using::testing::Invoke; | 28 using::testing::Invoke; |
27 using::testing::Return; | 29 using::testing::Return; |
28 using::testing::_; | 30 using::testing::_; |
29 | 31 |
30 namespace { | 32 namespace { |
31 const char kTitle[] = "Title"; | 33 const char kTitle[] = "Title"; |
cjhopman
2014/03/05 02:55:34
I believe that there should be no indent for a nam
shashi
2014/03/05 03:45:39
Done.
| |
32 const char kContent[] = "Content"; | 34 const char kContent[] = "Content"; |
33 const char kURL[] = "http://a.com/"; | 35 const char kURL[] = "http://a.com/"; |
34 const size_t kTotalImages = 2; | 36 const size_t kTotalImages = 2; |
35 const char* kImageURLs[kTotalImages] = {"http://a.com/img1.jpg", | 37 const char* kImageURLs[kTotalImages] = {"http://a.com/img1.jpg", |
36 "http://a.com/img2.jpg"}; | 38 "http://a.com/img2.jpg"}; |
37 const char* kImageData[kTotalImages] = {"abcde", "12345"}; | 39 const char* kImageData[kTotalImages] = {"abcde", "12345"}; |
38 | 40 |
39 const string GetImageName(int page_num, int image_num) { | 41 const string GetImageName(int page_num, int image_num) { |
40 return base::IntToString(page_num) + "_" + base::IntToString(image_num); | 42 return base::IntToString(page_num) + "_" + base::IntToString(image_num); |
41 } | 43 } |
42 | 44 |
43 scoped_ptr<base::ListValue> CreateDistilledValueReturnedFromJS( | 45 scoped_ptr<base::ListValue> CreateDistilledValueReturnedFromJS( |
44 const string& title, | 46 const string& title, |
45 const string& content, | 47 const string& content, |
46 const vector<int>& image_indices, | 48 const vector<int>& image_indices, |
47 const string& next_page_url, | 49 const string& next_page_url, |
48 const string& prev_page_url = "") { | 50 const string& prev_page_url = "") { |
49 scoped_ptr<base::ListValue> list(new base::ListValue()); | 51 scoped_ptr<base::ListValue> list(new base::ListValue()); |
50 | 52 |
51 list->AppendString(title); | 53 list->AppendString(title); |
52 list->AppendString(content); | 54 list->AppendString(content); |
53 list->AppendString(next_page_url); | 55 list->AppendString(next_page_url); |
54 list->AppendString(prev_page_url); | 56 list->AppendString(prev_page_url); |
55 for (size_t i = 0; i < image_indices.size(); ++i) { | 57 for (size_t i = 0; i < image_indices.size(); ++i) { |
56 list->AppendString(kImageURLs[image_indices[i]]); | 58 list->AppendString(kImageURLs[image_indices[i]]); |
57 } | 59 } |
58 return list.Pass(); | 60 return list.Pass(); |
59 } | 61 } |
60 | 62 |
63 // Return the sequence in which Distiller will distill pages. | |
64 // Note: ignores any delays due to fetching images etc. | |
65 vector<int> GetPagesInSequence(int start_page_num, int num_pages) { | |
66 // Distiller prefers distilling past pages first. E.g. when distillation | |
67 // starts on page 2 then pages are distilled in the order: 2, 1, 0, 3, 4. | |
68 vector<int> page_nums; | |
69 for (int page = start_page_num; page >= 0; --page) | |
70 page_nums.push_back(page); | |
71 for (int page = start_page_num + 1; page < num_pages; ++page) | |
72 page_nums.push_back(page); | |
73 return page_nums; | |
74 } | |
75 | |
76 struct MultipageDistillerData { | |
77 public: | |
78 MultipageDistillerData() {} | |
79 ~MultipageDistillerData() {} | |
80 vector<string> page_urls; | |
81 vector<string> content; | |
82 vector<vector<int> > image_ids; | |
83 // The Javascript values returned by mock distiller. | |
84 ScopedVector<base::Value> distilled_values; | |
85 | |
86 private: | |
87 DISALLOW_COPY_AND_ASSIGN(MultipageDistillerData); | |
88 }; | |
89 | |
90 void VerifyIncrementalUpdatesMatch( | |
91 const MultipageDistillerData* distiller_data, | |
92 int num_pages_in_article, | |
93 const vector<dom_distiller::ArticleDistillationUpdate>& | |
94 incremental_updates, | |
95 int start_page_num) { | |
96 vector<int> page_seq = | |
97 GetPagesInSequence(start_page_num, num_pages_in_article); | |
98 // Updates should contain a list of pages. Pages in an update should be in | |
99 // the correct ascending page order regardless of |start_page_num|. | |
100 // E.g. if distillation starts at page 2 of a 3 page article, the updates | |
101 // will be [[2], [1, 2], [1, 2, 3]]. This example assumes that image fetches | |
102 // do not delay distillation of a page. There can be scenarios when image | |
103 // fetch delays distillation of a page (E.g. 1 is delayed due to image | |
104 // fetches so updates can be in this order [[2], [2,3], [1,2,3]]. | |
105 for (size_t update_count = 0; update_count < incremental_updates.size(); | |
106 ++update_count) { | |
107 const dom_distiller::ArticleDistillationUpdate& update = | |
108 incremental_updates[update_count]; | |
109 EXPECT_EQ(update_count + 1, update.GetPagesSize()); | |
110 | |
111 vector<int> expected_page_nums_in_update( | |
112 page_seq.begin(), page_seq.begin() + update.GetPagesSize()); | |
113 std::sort(expected_page_nums_in_update.begin(), | |
114 expected_page_nums_in_update.end()); | |
115 | |
116 // If we already got the first page then there is no previous page. | |
117 EXPECT_EQ((expected_page_nums_in_update[0] != 0), update.HasPrevPage()); | |
118 | |
119 // if we already got the last page then there is no next page. | |
120 EXPECT_EQ( | |
121 (*expected_page_nums_in_update.rbegin()) != num_pages_in_article - 1, | |
122 update.HasNextPage()); | |
123 for (size_t j = 0; j < update.GetPagesSize(); ++j) { | |
124 int actual_page_num = expected_page_nums_in_update[j]; | |
125 EXPECT_EQ(distiller_data->page_urls[actual_page_num], | |
126 update.GetDistilledPage(j)->data.url()); | |
127 EXPECT_EQ(distiller_data->content[actual_page_num], | |
128 update.GetDistilledPage(j)->data.html()); | |
129 } | |
130 } | |
131 } | |
132 | |
133 scoped_ptr<MultipageDistillerData> CreateMultipageDistillerDataWithoutImages( | |
134 size_t pages_size) { | |
135 scoped_ptr<MultipageDistillerData> result(new MultipageDistillerData()); | |
136 string url_prefix = "http://a.com/"; | |
137 for (size_t page_num = 0; page_num < pages_size; ++page_num) { | |
138 result->page_urls.push_back(url_prefix + base::IntToString(page_num)); | |
139 result->content.push_back("Content for page:" + | |
140 base::IntToString(page_num)); | |
141 result->image_ids.push_back(vector<int>()); | |
142 string next_page_url = (page_num + 1 < pages_size) | |
143 ? url_prefix + base::IntToString(page_num + 1) | |
144 : ""; | |
145 string prev_page_url = | |
146 (page_num > 0) ? result->page_urls[page_num - 1] : ""; | |
147 scoped_ptr<base::ListValue> distilled_value = | |
148 CreateDistilledValueReturnedFromJS(kTitle, | |
149 result->content[page_num], | |
150 result->image_ids[page_num], | |
151 next_page_url, | |
152 prev_page_url); | |
153 result->distilled_values.push_back(distilled_value.release()); | |
154 } | |
155 return result.Pass(); | |
156 } | |
157 | |
158 void VerifyArticleProtoMatchesMultipageData( | |
159 const dom_distiller::DistilledArticleProto* article_proto, | |
160 const MultipageDistillerData* distiller_data, | |
161 size_t pages_size) { | |
162 EXPECT_EQ(pages_size, static_cast<size_t>(article_proto->pages_size())); | |
163 EXPECT_EQ(kTitle, article_proto->title()); | |
164 for (size_t page_num = 0; page_num < pages_size; ++page_num) { | |
165 const dom_distiller::DistilledPageProto& page = | |
166 article_proto->pages(page_num); | |
167 EXPECT_EQ(distiller_data->content[page_num], page.html()); | |
168 EXPECT_EQ(distiller_data->page_urls[page_num], page.url()); | |
169 EXPECT_EQ(distiller_data->image_ids[page_num].size(), | |
170 static_cast<size_t>(page.image_size())); | |
171 const vector<int>& image_ids_for_page = | |
172 distiller_data->image_ids[page_num]; | |
173 for (size_t img_num = 0; img_num < image_ids_for_page.size(); ++img_num) { | |
174 EXPECT_EQ(kImageData[image_ids_for_page[img_num]], | |
175 page.image(img_num).data()); | |
176 EXPECT_EQ(GetImageName(page_num + 1, img_num), | |
177 page.image(img_num).name()); | |
178 } | |
179 } | |
180 } | |
181 | |
61 } // namespace | 182 } // namespace |
62 | 183 |
63 namespace dom_distiller { | 184 namespace dom_distiller { |
64 | 185 |
65 class TestDistillerURLFetcher : public DistillerURLFetcher { | 186 class TestDistillerURLFetcher : public DistillerURLFetcher { |
66 public: | 187 public: |
67 TestDistillerURLFetcher() : DistillerURLFetcher(NULL) { | 188 TestDistillerURLFetcher() : DistillerURLFetcher(NULL) { |
68 responses_[kImageURLs[0]] = string(kImageData[0]); | 189 responses_[kImageURLs[0]] = string(kImageData[0]); |
69 responses_[kImageURLs[1]] = string(kImageData[1]); | 190 responses_[kImageURLs[1]] = string(kImageData[1]); |
70 } | 191 } |
71 | 192 |
72 void CallCallback(string url, const URLFetcherCallback& callback) { | 193 void CallCallback(string url, const URLFetcherCallback& callback) { |
73 callback.Run(responses_[url]); | 194 callback.Run(responses_[url]); |
74 } | 195 } |
75 | 196 |
76 virtual void FetchURL(const string& url, | 197 virtual void FetchURL(const string& url, |
77 const URLFetcherCallback& callback) OVERRIDE { | 198 const URLFetcherCallback& callback) OVERRIDE { |
78 ASSERT_TRUE(base::MessageLoop::current()); | 199 ASSERT_TRUE(base::MessageLoop::current()); |
79 base::MessageLoop::current()->PostTask( | 200 base::MessageLoop::current()->PostTask( |
80 FROM_HERE, | 201 FROM_HERE, |
81 base::Bind(&TestDistillerURLFetcher::CallCallback, | 202 base::Bind(&TestDistillerURLFetcher::CallCallback, |
82 base::Unretained(this), url, callback)); | 203 base::Unretained(this), url, callback)); |
83 } | 204 } |
84 | 205 |
85 std::map<string, string> responses_; | 206 std::map<string, string> responses_; |
86 }; | 207 }; |
87 | 208 |
88 | |
89 class TestDistillerURLFetcherFactory : public DistillerURLFetcherFactory { | 209 class TestDistillerURLFetcherFactory : public DistillerURLFetcherFactory { |
90 public: | 210 public: |
91 TestDistillerURLFetcherFactory() : DistillerURLFetcherFactory(NULL) {} | 211 TestDistillerURLFetcherFactory() : DistillerURLFetcherFactory(NULL) {} |
92 virtual ~TestDistillerURLFetcherFactory() {} | 212 virtual ~TestDistillerURLFetcherFactory() {} |
93 virtual DistillerURLFetcher* CreateDistillerURLFetcher() const OVERRIDE { | 213 virtual DistillerURLFetcher* CreateDistillerURLFetcher() const OVERRIDE { |
94 return new TestDistillerURLFetcher(); | 214 return new TestDistillerURLFetcher(); |
95 } | 215 } |
96 }; | 216 }; |
97 | 217 |
98 | |
99 class MockDistillerPage : public DistillerPage { | 218 class MockDistillerPage : public DistillerPage { |
100 public: | 219 public: |
101 MOCK_METHOD0(InitImpl, void()); | 220 MOCK_METHOD0(InitImpl, void()); |
102 MOCK_METHOD1(LoadURLImpl, void(const GURL& gurl)); | 221 MOCK_METHOD1(LoadURLImpl, void(const GURL& gurl)); |
103 MOCK_METHOD1(ExecuteJavaScriptImpl, void(const string& script)); | 222 MOCK_METHOD1(ExecuteJavaScriptImpl, void(const string& script)); |
104 | 223 |
105 explicit MockDistillerPage(DistillerPage::Delegate* delegate) | 224 explicit MockDistillerPage(DistillerPage::Delegate* delegate) |
106 : DistillerPage(delegate) {} | 225 : DistillerPage(delegate) {} |
107 }; | 226 }; |
108 | 227 |
109 | |
110 class MockDistillerPageFactory : public DistillerPageFactory { | 228 class MockDistillerPageFactory : public DistillerPageFactory { |
111 public: | 229 public: |
112 MOCK_CONST_METHOD1( | 230 MOCK_CONST_METHOD1( |
113 CreateDistillerPageMock, | 231 CreateDistillerPageMock, |
114 DistillerPage*(DistillerPage::Delegate* delegate)); | 232 DistillerPage*(DistillerPage::Delegate* delegate)); |
115 | 233 |
116 virtual scoped_ptr<DistillerPage> CreateDistillerPage( | 234 virtual scoped_ptr<DistillerPage> CreateDistillerPage( |
117 DistillerPage::Delegate* delegate) const OVERRIDE { | 235 DistillerPage::Delegate* delegate) const OVERRIDE { |
118 return scoped_ptr<DistillerPage>(CreateDistillerPageMock(delegate)); | 236 return scoped_ptr<DistillerPage>(CreateDistillerPageMock(delegate)); |
119 } | 237 } |
120 }; | 238 }; |
121 | 239 |
122 class DistillerTest : public testing::Test { | 240 class DistillerTest : public testing::Test { |
123 public: | 241 public: |
124 virtual ~DistillerTest() {} | 242 virtual ~DistillerTest() {} |
125 void OnDistillPageDone(scoped_ptr<DistilledArticleProto> proto) { | 243 void OnDistillArticleDone(scoped_ptr<DistilledArticleProto> proto) { |
126 article_proto_ = proto.Pass(); | 244 article_proto_ = proto.Pass(); |
127 } | 245 } |
128 | 246 |
247 void OnDistillArticleUpdate(const ArticleDistillationUpdate& article_update) { | |
248 in_sequence_updates_.push_back(article_update); | |
249 } | |
250 | |
251 void DistillPage(const std::string& url) { | |
252 distiller_->DistillPage(GURL(url), | |
253 base::Bind(&DistillerTest::OnDistillArticleDone, | |
254 base::Unretained(this)), | |
255 base::Bind(&DistillerTest::OnDistillArticleUpdate, | |
256 base::Unretained(this))); | |
257 } | |
258 | |
129 protected: | 259 protected: |
130 scoped_ptr<DistillerImpl> distiller_; | 260 scoped_ptr<DistillerImpl> distiller_; |
131 scoped_ptr<DistilledArticleProto> article_proto_; | 261 scoped_ptr<DistilledArticleProto> article_proto_; |
262 std::vector<ArticleDistillationUpdate> in_sequence_updates_; | |
132 MockDistillerPageFactory page_factory_; | 263 MockDistillerPageFactory page_factory_; |
133 TestDistillerURLFetcherFactory url_fetcher_factory_; | 264 TestDistillerURLFetcherFactory url_fetcher_factory_; |
134 }; | 265 }; |
135 | 266 |
136 ACTION_P3(DistillerPageOnExecuteJavaScriptDone, distiller_page, url, list) { | 267 ACTION_P3(DistillerPageOnExecuteJavaScriptDone, distiller_page, url, list) { |
137 distiller_page->OnExecuteJavaScriptDone(url, list); | 268 distiller_page->OnExecuteJavaScriptDone(url, list); |
138 } | 269 } |
139 | 270 |
140 ACTION_P2(CreateMockDistillerPage, list, kurl) { | 271 ACTION_P2(CreateMockDistillerPage, list, kurl) { |
141 DistillerPage::Delegate* delegate = arg0; | 272 DistillerPage::Delegate* delegate = arg0; |
142 MockDistillerPage* distiller_page = new MockDistillerPage(delegate); | 273 MockDistillerPage* distiller_page = new MockDistillerPage(delegate); |
143 EXPECT_CALL(*distiller_page, InitImpl()); | 274 EXPECT_CALL(*distiller_page, InitImpl()); |
144 EXPECT_CALL(*distiller_page, LoadURLImpl(kurl)) | 275 EXPECT_CALL(*distiller_page, LoadURLImpl(kurl)) |
145 .WillOnce(testing::InvokeWithoutArgs(distiller_page, | 276 .WillOnce(testing::InvokeWithoutArgs(distiller_page, |
146 &DistillerPage::OnLoadURLDone)); | 277 &DistillerPage::OnLoadURLDone)); |
147 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_)).WillOnce( | 278 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_)).WillOnce( |
148 DistillerPageOnExecuteJavaScriptDone(distiller_page, kurl, list)); | 279 DistillerPageOnExecuteJavaScriptDone(distiller_page, kurl, list)); |
149 return distiller_page; | 280 return distiller_page; |
150 } | 281 } |
151 | 282 |
152 ACTION_P4(CreateMockDistillerPages, lists, kurls, num_pages, start_page_num) { | 283 ACTION_P3(CreateMockDistillerPages, |
284 distiller_data, | |
285 pages_size, | |
286 start_page_num) { | |
153 DistillerPage::Delegate* delegate = arg0; | 287 DistillerPage::Delegate* delegate = arg0; |
154 MockDistillerPage* distiller_page = new MockDistillerPage(delegate); | 288 MockDistillerPage* distiller_page = new MockDistillerPage(delegate); |
155 EXPECT_CALL(*distiller_page, InitImpl()); | 289 EXPECT_CALL(*distiller_page, InitImpl()); |
156 { | 290 { |
157 testing::InSequence s; | 291 testing::InSequence s; |
158 // Distiller prefers distilling past pages first. E.g. when distillation | 292 vector<int> page_nums = GetPagesInSequence(start_page_num, pages_size); |
159 // starts on page 2 then pages are distilled in the order: 2, 1, 0, 3, 4. | 293 for (size_t page_num = 0; page_num < pages_size; ++page_num) { |
160 vector<int> page_nums; | |
161 for (int page = start_page_num; page >= 0; --page) | |
162 page_nums.push_back(page); | |
163 for (int page = start_page_num + 1; page < num_pages; ++page) | |
164 page_nums.push_back(page); | |
165 | |
166 for (size_t page_num = 0; page_num < page_nums.size(); ++page_num) { | |
167 int page = page_nums[page_num]; | 294 int page = page_nums[page_num]; |
168 GURL url = GURL(kurls[page]); | 295 GURL url = GURL(distiller_data->page_urls[page]); |
169 EXPECT_CALL(*distiller_page, LoadURLImpl(url)) | 296 EXPECT_CALL(*distiller_page, LoadURLImpl(url)) |
170 .WillOnce(testing::InvokeWithoutArgs(distiller_page, | 297 .WillOnce(testing::InvokeWithoutArgs(distiller_page, |
171 &DistillerPage::OnLoadURLDone)); | 298 &DistillerPage::OnLoadURLDone)); |
172 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_)) | 299 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_)) |
173 .WillOnce(DistillerPageOnExecuteJavaScriptDone( | 300 .WillOnce(DistillerPageOnExecuteJavaScriptDone( |
174 distiller_page, url, lists[page].get())); | 301 distiller_page, url, distiller_data->distilled_values[page])); |
175 } | 302 } |
176 } | 303 } |
177 return distiller_page; | 304 return distiller_page; |
178 } | 305 } |
179 | 306 |
180 TEST_F(DistillerTest, DistillPage) { | 307 TEST_F(DistillerTest, DistillPage) { |
181 base::MessageLoopForUI loop; | 308 base::MessageLoopForUI loop; |
182 scoped_ptr<base::ListValue> list = | 309 scoped_ptr<base::ListValue> list = |
183 CreateDistilledValueReturnedFromJS(kTitle, kContent, vector<int>(), ""); | 310 CreateDistilledValueReturnedFromJS(kTitle, kContent, vector<int>(), ""); |
184 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 311 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) |
185 .WillOnce(CreateMockDistillerPage(list.get(), GURL(kURL))); | 312 .WillOnce(CreateMockDistillerPage(list.get(), GURL(kURL))); |
186 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 313 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
187 distiller_->Init(); | 314 distiller_->Init(); |
188 distiller_->DistillPage( | 315 DistillPage(kURL); |
189 GURL(kURL), | |
190 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
191 base::MessageLoop::current()->RunUntilIdle(); | 316 base::MessageLoop::current()->RunUntilIdle(); |
192 EXPECT_EQ(kTitle, article_proto_->title()); | 317 EXPECT_EQ(kTitle, article_proto_->title()); |
193 EXPECT_EQ(article_proto_->pages_size(), 1); | 318 EXPECT_EQ(article_proto_->pages_size(), 1); |
194 const DistilledPageProto& first_page = article_proto_->pages(0); | 319 const DistilledPageProto& first_page = article_proto_->pages(0); |
195 EXPECT_EQ(kContent, first_page.html()); | 320 EXPECT_EQ(kContent, first_page.html()); |
196 EXPECT_EQ(kURL, first_page.url()); | 321 EXPECT_EQ(kURL, first_page.url()); |
197 } | 322 } |
198 | 323 |
199 TEST_F(DistillerTest, DistillPageWithImages) { | 324 TEST_F(DistillerTest, DistillPageWithImages) { |
200 base::MessageLoopForUI loop; | 325 base::MessageLoopForUI loop; |
201 vector<int> image_indices; | 326 vector<int> image_indices; |
202 image_indices.push_back(0); | 327 image_indices.push_back(0); |
203 image_indices.push_back(1); | 328 image_indices.push_back(1); |
204 scoped_ptr<base::ListValue> list = | 329 scoped_ptr<base::ListValue> list = |
205 CreateDistilledValueReturnedFromJS(kTitle, kContent, image_indices, ""); | 330 CreateDistilledValueReturnedFromJS(kTitle, kContent, image_indices, ""); |
206 EXPECT_CALL(page_factory_, | 331 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) |
207 CreateDistillerPageMock(_)).WillOnce( | 332 .WillOnce(CreateMockDistillerPage(list.get(), GURL(kURL))); |
208 CreateMockDistillerPage(list.get(), GURL(kURL))); | |
209 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 333 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
210 distiller_->Init(); | 334 distiller_->Init(); |
211 distiller_->DistillPage( | 335 DistillPage(kURL); |
212 GURL(kURL), | |
213 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
214 base::MessageLoop::current()->RunUntilIdle(); | 336 base::MessageLoop::current()->RunUntilIdle(); |
215 EXPECT_EQ(kTitle, article_proto_->title()); | 337 EXPECT_EQ(kTitle, article_proto_->title()); |
216 EXPECT_EQ(article_proto_->pages_size(), 1); | 338 EXPECT_EQ(article_proto_->pages_size(), 1); |
217 const DistilledPageProto& first_page = article_proto_->pages(0); | 339 const DistilledPageProto& first_page = article_proto_->pages(0); |
218 EXPECT_EQ(kContent, first_page.html()); | 340 EXPECT_EQ(kContent, first_page.html()); |
219 EXPECT_EQ(kURL, first_page.url()); | 341 EXPECT_EQ(kURL, first_page.url()); |
220 EXPECT_EQ(2, first_page.image_size()); | 342 EXPECT_EQ(2, first_page.image_size()); |
221 EXPECT_EQ(kImageData[0], first_page.image(0).data()); | 343 EXPECT_EQ(kImageData[0], first_page.image(0).data()); |
222 EXPECT_EQ(GetImageName(1, 0), first_page.image(0).name()); | 344 EXPECT_EQ(GetImageName(1, 0), first_page.image(0).name()); |
223 EXPECT_EQ(kImageData[1], first_page.image(1).data()); | 345 EXPECT_EQ(kImageData[1], first_page.image(1).data()); |
224 EXPECT_EQ(GetImageName(1, 1), first_page.image(1).name()); | 346 EXPECT_EQ(GetImageName(1, 1), first_page.image(1).name()); |
225 } | 347 } |
226 | 348 |
227 TEST_F(DistillerTest, DistillMultiplePages) { | 349 TEST_F(DistillerTest, DistillMultiplePages) { |
228 base::MessageLoopForUI loop; | 350 base::MessageLoopForUI loop; |
229 const int kNumPages = 8; | 351 const size_t kNumPages = 8; |
230 vector<int> image_indices[kNumPages]; | 352 scoped_ptr<MultipageDistillerData> distiller_data = |
231 string content[kNumPages]; | 353 CreateMultipageDistillerDataWithoutImages(kNumPages); |
232 string page_urls[kNumPages]; | |
233 scoped_ptr<base::ListValue> list[kNumPages]; | |
234 | 354 |
355 // Add images. | |
235 int next_image_number = 0; | 356 int next_image_number = 0; |
236 | 357 for (size_t page_num = 0; page_num < kNumPages; ++page_num) { |
237 for (int page_num = 0; page_num < kNumPages; ++page_num) { | |
238 // Each page has different number of images. | 358 // Each page has different number of images. |
239 int tot_images = (page_num + kTotalImages) % (kTotalImages + 1); | 359 size_t tot_images = (page_num + kTotalImages) % (kTotalImages + 1); |
240 for (int img_num = 0; img_num < tot_images; img_num++) { | 360 vector<int> image_indices; |
241 image_indices[page_num].push_back(next_image_number); | 361 for (size_t img_num = 0; img_num < tot_images; img_num++) { |
362 image_indices.push_back(next_image_number); | |
242 next_image_number = (next_image_number + 1) % kTotalImages; | 363 next_image_number = (next_image_number + 1) % kTotalImages; |
243 } | 364 } |
244 | 365 distiller_data->image_ids.push_back(image_indices); |
245 page_urls[page_num] = "http://a.com/" + base::IntToString(page_num); | |
246 content[page_num] = "Content for page:" + base::IntToString(page_num); | |
247 } | |
248 for (int i = 0; i < kNumPages; ++i) { | |
249 string next_page_url = ""; | |
250 if (i + 1 < kNumPages) | |
251 next_page_url = page_urls[i + 1]; | |
252 | |
253 list[i] = CreateDistilledValueReturnedFromJS( | |
254 kTitle, content[i], image_indices[i], next_page_url); | |
255 } | 366 } |
256 | 367 |
257 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 368 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) |
258 .WillOnce(CreateMockDistillerPages(list, page_urls, kNumPages, 0)); | 369 .WillOnce(CreateMockDistillerPages(distiller_data.get(), kNumPages, 0)); |
259 | 370 |
260 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 371 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
261 distiller_->Init(); | 372 distiller_->Init(); |
262 distiller_->DistillPage( | 373 DistillPage(distiller_data->page_urls[0]); |
263 GURL(page_urls[0]), | |
264 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
265 base::MessageLoop::current()->RunUntilIdle(); | 374 base::MessageLoop::current()->RunUntilIdle(); |
266 EXPECT_EQ(kTitle, article_proto_->title()); | 375 VerifyArticleProtoMatchesMultipageData( |
267 EXPECT_EQ(article_proto_->pages_size(), kNumPages); | 376 article_proto_.get(), distiller_data.get(), kNumPages); |
268 for (int page_num = 0; page_num < kNumPages; ++page_num) { | |
269 const DistilledPageProto& page = article_proto_->pages(page_num); | |
270 EXPECT_EQ(content[page_num], page.html()); | |
271 EXPECT_EQ(page_urls[page_num], page.url()); | |
272 EXPECT_EQ(image_indices[page_num].size(), | |
273 static_cast<size_t>(page.image_size())); | |
274 for (size_t img_num = 0; img_num < image_indices[page_num].size(); | |
275 ++img_num) { | |
276 EXPECT_EQ(kImageData[image_indices[page_num][img_num]], | |
277 page.image(img_num).data()); | |
278 EXPECT_EQ(GetImageName(page_num + 1, img_num), | |
279 page.image(img_num).name()); | |
280 } | |
281 } | |
282 } | 377 } |
283 | 378 |
284 TEST_F(DistillerTest, DistillLinkLoop) { | 379 TEST_F(DistillerTest, DistillLinkLoop) { |
285 base::MessageLoopForUI loop; | 380 base::MessageLoopForUI loop; |
286 // Create a loop, the next page is same as the current page. This could | 381 // Create a loop, the next page is same as the current page. This could |
287 // happen if javascript misparses a next page link. | 382 // happen if javascript misparses a next page link. |
288 scoped_ptr<base::ListValue> list = | 383 scoped_ptr<base::ListValue> list = |
289 CreateDistilledValueReturnedFromJS(kTitle, kContent, vector<int>(), kURL); | 384 CreateDistilledValueReturnedFromJS(kTitle, kContent, vector<int>(), kURL); |
290 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 385 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) |
291 .WillOnce(CreateMockDistillerPage(list.get(), GURL(kURL))); | 386 .WillOnce(CreateMockDistillerPage(list.get(), GURL(kURL))); |
292 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 387 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
293 distiller_->Init(); | 388 distiller_->Init(); |
294 distiller_->DistillPage( | 389 DistillPage(kURL); |
295 GURL(kURL), | |
296 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
297 base::MessageLoop::current()->RunUntilIdle(); | 390 base::MessageLoop::current()->RunUntilIdle(); |
298 EXPECT_EQ(kTitle, article_proto_->title()); | 391 EXPECT_EQ(kTitle, article_proto_->title()); |
299 EXPECT_EQ(article_proto_->pages_size(), 1); | 392 EXPECT_EQ(article_proto_->pages_size(), 1); |
300 } | 393 } |
301 | 394 |
302 TEST_F(DistillerTest, CheckMaxPageLimit) { | 395 TEST_F(DistillerTest, CheckMaxPageLimitExtraPage) { |
303 base::MessageLoopForUI loop; | 396 base::MessageLoopForUI loop; |
304 const size_t kMaxPagesInArticle = 10; | 397 const size_t kMaxPagesInArticle = 10; |
305 string page_urls[kMaxPagesInArticle]; | 398 scoped_ptr<MultipageDistillerData> distiller_data = |
306 scoped_ptr<base::ListValue> list[kMaxPagesInArticle]; | 399 CreateMultipageDistillerDataWithoutImages(kMaxPagesInArticle); |
307 | 400 |
308 // Note: Next page url of the last page of article is set. So distiller will | 401 // Note: Next page url of the last page of article is set. So distiller will |
309 // try to do kMaxPagesInArticle + 1 calls if the max article limit does not | 402 // try to do kMaxPagesInArticle + 1 calls if the max article limit does not |
310 // work. | 403 // work. |
311 string url_prefix = "http://a.com/"; | 404 scoped_ptr<base::ListValue> last_page_data = |
312 for (size_t page_num = 0; page_num < kMaxPagesInArticle; ++page_num) { | 405 CreateDistilledValueReturnedFromJS( |
313 page_urls[page_num] = url_prefix + base::IntToString(page_num + 1); | 406 kTitle, |
314 string content = "Content for page:" + base::IntToString(page_num); | 407 distiller_data->content[kMaxPagesInArticle - 1], |
315 string next_page_url = url_prefix + base::IntToString(page_num + 2); | 408 vector<int>(), |
316 list[page_num] = CreateDistilledValueReturnedFromJS( | 409 "", |
317 kTitle, content, vector<int>(), next_page_url); | 410 distiller_data->page_urls[kMaxPagesInArticle - 2]); |
318 } | |
319 | 411 |
320 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 412 distiller_data->distilled_values.pop_back(); |
321 .WillOnce(CreateMockDistillerPages( | 413 distiller_data->distilled_values.push_back(last_page_data.release()); |
322 list, page_urls, static_cast<int>(kMaxPagesInArticle), 0)); | |
323 | 414 |
415 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)).WillOnce( | |
416 CreateMockDistillerPages(distiller_data.get(), kMaxPagesInArticle, 0)); | |
324 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 417 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
325 | 418 |
326 distiller_->SetMaxNumPagesInArticle(kMaxPagesInArticle); | 419 distiller_->SetMaxNumPagesInArticle(kMaxPagesInArticle); |
327 | 420 |
328 distiller_->Init(); | 421 distiller_->Init(); |
329 distiller_->DistillPage( | 422 DistillPage(distiller_data->page_urls[0]); |
330 GURL(page_urls[0]), | |
331 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
332 base::MessageLoop::current()->RunUntilIdle(); | 423 base::MessageLoop::current()->RunUntilIdle(); |
333 EXPECT_EQ(kTitle, article_proto_->title()); | 424 EXPECT_EQ(kTitle, article_proto_->title()); |
334 EXPECT_EQ(kMaxPagesInArticle, | 425 EXPECT_EQ(kMaxPagesInArticle, |
335 static_cast<size_t>(article_proto_->pages_size())); | 426 static_cast<size_t>(article_proto_->pages_size())); |
427 } | |
336 | 428 |
337 // Now check if distilling an article with exactly the page limit works by | 429 TEST_F(DistillerTest, CheckMaxPageLimitExactLimit) { |
338 // resetting the next page url of the last page of the article. | 430 base::MessageLoopForUI loop; |
339 list[kMaxPagesInArticle - 1] = | 431 const size_t kMaxPagesInArticle = 10; |
340 CreateDistilledValueReturnedFromJS(kTitle, "Content", vector<int>(), ""); | 432 scoped_ptr<MultipageDistillerData> distiller_data = |
341 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 433 CreateMultipageDistillerDataWithoutImages(kMaxPagesInArticle); |
342 .WillOnce(CreateMockDistillerPages( | |
343 list, page_urls, static_cast<int>(kMaxPagesInArticle), 0)); | |
344 | 434 |
435 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)).WillOnce( | |
436 CreateMockDistillerPages(distiller_data.get(), kMaxPagesInArticle, 0)); | |
345 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 437 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
438 | |
439 // Check if distilling an article with exactly the page limit works. | |
346 distiller_->SetMaxNumPagesInArticle(kMaxPagesInArticle); | 440 distiller_->SetMaxNumPagesInArticle(kMaxPagesInArticle); |
347 | 441 |
348 distiller_->Init(); | 442 distiller_->Init(); |
349 distiller_->DistillPage( | 443 |
350 GURL(page_urls[0]), | 444 DistillPage(distiller_data->page_urls[0]); |
351 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
352 base::MessageLoop::current()->RunUntilIdle(); | 445 base::MessageLoop::current()->RunUntilIdle(); |
353 EXPECT_EQ(kTitle, article_proto_->title()); | 446 EXPECT_EQ(kTitle, article_proto_->title()); |
354 EXPECT_EQ(kMaxPagesInArticle, | 447 EXPECT_EQ(kMaxPagesInArticle, |
355 static_cast<size_t>(article_proto_->pages_size())); | |
356 | |
357 // Now check if distilling an article with exactly the page limit works by | |
358 // resetting the next page url of the last page of the article. | |
359 list[kMaxPagesInArticle - 1] = | |
360 CreateDistilledValueReturnedFromJS(kTitle, "Content", vector<int>(), ""); | |
361 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | |
362 .WillOnce(CreateMockDistillerPages( | |
363 list, page_urls, static_cast<int>(kMaxPagesInArticle), 0)); | |
364 | |
365 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | |
366 distiller_->SetMaxNumPagesInArticle(kMaxPagesInArticle); | |
367 | |
368 distiller_->Init(); | |
369 distiller_->DistillPage( | |
370 GURL(page_urls[0]), | |
371 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
372 base::MessageLoop::current()->RunUntilIdle(); | |
373 EXPECT_EQ(kTitle, article_proto_->title()); | |
374 EXPECT_EQ(kMaxPagesInArticle, | |
375 static_cast<size_t>(article_proto_->pages_size())); | 448 static_cast<size_t>(article_proto_->pages_size())); |
376 } | 449 } |
377 | 450 |
378 TEST_F(DistillerTest, SinglePageDistillationFailure) { | 451 TEST_F(DistillerTest, SinglePageDistillationFailure) { |
379 base::MessageLoopForUI loop; | 452 base::MessageLoopForUI loop; |
380 // To simulate failure return a null value. | 453 // To simulate failure return a null value. |
381 scoped_ptr<base::Value> nullValue(base::Value::CreateNullValue()); | 454 scoped_ptr<base::Value> nullValue(base::Value::CreateNullValue()); |
382 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 455 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) |
383 .WillOnce(CreateMockDistillerPage(nullValue.get(), GURL(kURL))); | 456 .WillOnce(CreateMockDistillerPage(nullValue.get(), GURL(kURL))); |
384 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 457 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
385 distiller_->Init(); | 458 distiller_->Init(); |
386 distiller_->DistillPage( | 459 DistillPage(kURL); |
387 GURL(kURL), | |
388 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
389 base::MessageLoop::current()->RunUntilIdle(); | 460 base::MessageLoop::current()->RunUntilIdle(); |
390 EXPECT_EQ("", article_proto_->title()); | 461 EXPECT_EQ("", article_proto_->title()); |
391 EXPECT_EQ(0, article_proto_->pages_size()); | 462 EXPECT_EQ(0, article_proto_->pages_size()); |
392 } | 463 } |
393 | 464 |
394 TEST_F(DistillerTest, MultiplePagesDistillationFailure) { | 465 TEST_F(DistillerTest, MultiplePagesDistillationFailure) { |
395 base::MessageLoopForUI loop; | 466 base::MessageLoopForUI loop; |
396 const int kNumPages = 8; | 467 const size_t kNumPages = 8; |
397 string content[kNumPages]; | 468 scoped_ptr<MultipageDistillerData> distiller_data = |
398 string page_urls[kNumPages]; | 469 CreateMultipageDistillerDataWithoutImages(kNumPages); |
399 scoped_ptr<base::Value> distilled_values[kNumPages]; | 470 |
400 // The page number of the failed page. | 471 // The page number of the failed page. |
401 int failed_page_num = 3; | 472 size_t failed_page_num = 3; |
402 string url_prefix = "http://a.com/"; | 473 // reset distilled data of the failed page. |
403 for (int page_num = 0; page_num < kNumPages; ++page_num) { | 474 distiller_data->distilled_values.erase( |
404 page_urls[page_num] = url_prefix + base::IntToString(page_num); | 475 distiller_data->distilled_values.begin() + failed_page_num); |
405 content[page_num] = "Content for page:" + base::IntToString(page_num); | 476 distiller_data->distilled_values.insert( |
406 string next_page_url = url_prefix + base::IntToString(page_num + 1); | 477 distiller_data->distilled_values.begin() + failed_page_num, |
407 if (page_num != failed_page_num) { | 478 base::Value::CreateNullValue()); |
408 distilled_values[page_num] = CreateDistilledValueReturnedFromJS( | |
409 kTitle, content[page_num], vector<int>(), next_page_url); | |
410 } else { | |
411 distilled_values[page_num].reset(base::Value::CreateNullValue()); | |
412 } | |
413 } | |
414 | |
415 // Expect only calls till the failed page number. | 479 // Expect only calls till the failed page number. |
416 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 480 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)).WillOnce( |
417 .WillOnce(CreateMockDistillerPages( | 481 CreateMockDistillerPages(distiller_data.get(), failed_page_num + 1, 0)); |
418 distilled_values, page_urls, failed_page_num + 1, 0)); | |
419 | 482 |
420 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 483 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
421 distiller_->Init(); | 484 distiller_->Init(); |
422 distiller_->DistillPage( | 485 DistillPage(distiller_data->page_urls[0]); |
423 GURL(page_urls[0]), | |
424 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | |
425 base::MessageLoop::current()->RunUntilIdle(); | 486 base::MessageLoop::current()->RunUntilIdle(); |
426 EXPECT_EQ(kTitle, article_proto_->title()); | 487 EXPECT_EQ(kTitle, article_proto_->title()); |
427 EXPECT_EQ(article_proto_->pages_size(), failed_page_num); | 488 VerifyArticleProtoMatchesMultipageData( |
428 for (int page_num = 0; page_num < failed_page_num; ++page_num) { | 489 article_proto_.get(), distiller_data.get(), failed_page_num); |
429 const DistilledPageProto& page = article_proto_->pages(page_num); | |
430 EXPECT_EQ(content[page_num], page.html()); | |
431 EXPECT_EQ(page_urls[page_num], page.url()); | |
432 } | |
433 } | 490 } |
434 | 491 |
435 TEST_F(DistillerTest, DistillPreviousPage) { | 492 TEST_F(DistillerTest, DistillPreviousPage) { |
436 base::MessageLoopForUI loop; | 493 base::MessageLoopForUI loop; |
437 const int kNumPages = 8; | 494 const size_t kNumPages = 8; |
438 string content[kNumPages]; | |
439 string page_urls[kNumPages]; | |
440 scoped_ptr<base::Value> distilled_values[kNumPages]; | |
441 | 495 |
442 // The page number of the article on which distillation starts. | 496 // The page number of the article on which distillation starts. |
443 int start_page_number = 3; | 497 int start_page_num = 3; |
444 string url_prefix = "http://a.com/"; | 498 scoped_ptr<MultipageDistillerData> distiller_data = |
445 for (int page_no = 0; page_no < kNumPages; ++page_no) { | 499 CreateMultipageDistillerDataWithoutImages(kNumPages); |
446 page_urls[page_no] = url_prefix + base::IntToString(page_no); | |
447 content[page_no] = "Content for page:" + base::IntToString(page_no); | |
448 string next_page_url = (page_no + 1 < kNumPages) | |
449 ? url_prefix + base::IntToString(page_no + 1) | |
450 : ""; | |
451 string prev_page_url = (page_no > 0) ? page_urls[page_no - 1] : ""; | |
452 distilled_values[page_no] = CreateDistilledValueReturnedFromJS( | |
453 kTitle, content[page_no], vector<int>(), next_page_url, prev_page_url); | |
454 } | |
455 | 500 |
456 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | 501 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) |
457 .WillOnce(CreateMockDistillerPages( | 502 .WillOnce(CreateMockDistillerPages( |
458 distilled_values, page_urls, kNumPages, start_page_number)); | 503 distiller_data.get(), kNumPages, start_page_num)); |
459 | 504 |
460 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | 505 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); |
461 distiller_->Init(); | 506 distiller_->Init(); |
462 distiller_->DistillPage( | 507 DistillPage(distiller_data->page_urls[start_page_num]); |
463 GURL(page_urls[start_page_number]), | 508 base::MessageLoop::current()->RunUntilIdle(); |
464 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); | 509 VerifyArticleProtoMatchesMultipageData( |
510 article_proto_.get(), distiller_data.get(), kNumPages); | |
511 } | |
512 | |
513 TEST_F(DistillerTest, IncrementalUpdates) { | |
514 base::MessageLoopForUI loop; | |
515 const size_t kNumPages = 8; | |
516 | |
517 // The page number of the article on which distillation starts. | |
518 int start_page_num = 3; | |
519 scoped_ptr<MultipageDistillerData> distiller_data = | |
520 CreateMultipageDistillerDataWithoutImages(kNumPages); | |
521 | |
522 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | |
523 .WillOnce(CreateMockDistillerPages( | |
524 distiller_data.get(), kNumPages, start_page_num)); | |
525 | |
526 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | |
527 distiller_->Init(); | |
528 DistillPage(distiller_data->page_urls[start_page_num]); | |
465 base::MessageLoop::current()->RunUntilIdle(); | 529 base::MessageLoop::current()->RunUntilIdle(); |
466 EXPECT_EQ(kTitle, article_proto_->title()); | 530 EXPECT_EQ(kTitle, article_proto_->title()); |
467 EXPECT_EQ(kNumPages, article_proto_->pages_size()); | 531 EXPECT_EQ(kNumPages, static_cast<size_t>(article_proto_->pages_size())); |
468 for (int page_no = 0; page_no < kNumPages; ++page_no) { | 532 EXPECT_EQ(kNumPages, in_sequence_updates_.size()); |
469 const DistilledPageProto& page = article_proto_->pages(page_no); | 533 |
470 EXPECT_EQ(content[page_no], page.html()); | 534 VerifyIncrementalUpdatesMatch( |
471 EXPECT_EQ(page_urls[page_no], page.url()); | 535 distiller_data.get(), kNumPages, in_sequence_updates_, start_page_num); |
472 } | 536 } |
537 | |
538 TEST_F(DistillerTest, IncrementalUpdatesDoNotDeleteFinalArticle) { | |
539 base::MessageLoopForUI loop; | |
540 const size_t kNumPages = 8; | |
541 int start_page_num = 3; | |
542 scoped_ptr<MultipageDistillerData> distiller_data = | |
543 CreateMultipageDistillerDataWithoutImages(kNumPages); | |
544 | |
545 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | |
546 .WillOnce(CreateMockDistillerPages( | |
547 distiller_data.get(), kNumPages, start_page_num)); | |
548 | |
549 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | |
550 distiller_->Init(); | |
551 DistillPage(distiller_data->page_urls[start_page_num]); | |
552 base::MessageLoop::current()->RunUntilIdle(); | |
553 EXPECT_EQ(kNumPages, in_sequence_updates_.size()); | |
554 | |
555 in_sequence_updates_.clear(); | |
556 | |
557 // Should still be able to access article and pages. | |
558 VerifyArticleProtoMatchesMultipageData( | |
559 article_proto_.get(), distiller_data.get(), kNumPages); | |
560 } | |
561 | |
562 TEST_F(DistillerTest, DeletingArticleDoesNotInterfereWithUpdates) { | |
563 base::MessageLoopForUI loop; | |
564 const size_t kNumPages = 8; | |
565 scoped_ptr<MultipageDistillerData> distiller_data = | |
566 CreateMultipageDistillerDataWithoutImages(kNumPages); | |
567 // The page number of the article on which distillation starts. | |
568 int start_page_num = 3; | |
569 | |
570 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_)) | |
571 .WillOnce(CreateMockDistillerPages( | |
572 distiller_data.get(), kNumPages, start_page_num)); | |
573 | |
574 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); | |
575 distiller_->Init(); | |
576 DistillPage(distiller_data->page_urls[start_page_num]); | |
577 base::MessageLoop::current()->RunUntilIdle(); | |
578 EXPECT_EQ(kNumPages, in_sequence_updates_.size()); | |
579 EXPECT_EQ(kTitle, article_proto_->title()); | |
580 EXPECT_EQ(kNumPages, static_cast<size_t>(article_proto_->pages_size())); | |
581 | |
582 // Delete the article. | |
583 article_proto_.reset(); | |
584 VerifyIncrementalUpdatesMatch( | |
585 distiller_data.get(), kNumPages, in_sequence_updates_, start_page_num); | |
473 } | 586 } |
474 | 587 |
475 } // namespace dom_distiller | 588 } // namespace dom_distiller |
OLD | NEW |