Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: components/dom_distiller/core/distiller_unittest.cc

Issue 146843010: Add support for multipage distillation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Chris' comments. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <map> 5 #include <map>
6 #include <string>
7 #include <vector>
6 8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
9 #include "base/location.h" 11 #include "base/location.h"
10 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string_number_conversions.h"
12 #include "base/values.h" 15 #include "base/values.h"
13 #include "components/dom_distiller/core/distiller.h" 16 #include "components/dom_distiller/core/distiller.h"
14 #include "components/dom_distiller/core/distiller_page.h" 17 #include "components/dom_distiller/core/distiller_page.h"
18 #include "components/dom_distiller/core/proto/distilled_article.pb.h"
15 #include "components/dom_distiller/core/proto/distilled_page.pb.h" 19 #include "components/dom_distiller/core/proto/distilled_page.pb.h"
16 #include "net/url_request/url_request_context_getter.h" 20 #include "net/url_request/url_request_context_getter.h"
17 #include "testing/gmock/include/gmock/gmock.h" 21 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h" 22 #include "testing/gtest/include/gtest/gtest.h"
19 23
24 using std::vector;
25 using std::string;
20 using::testing::Invoke; 26 using::testing::Invoke;
21 using::testing::Return; 27 using::testing::Return;
22 using::testing::_; 28 using::testing::_;
23 29
24 namespace { 30 namespace {
25 const char kTitle[] = "Title"; 31 const char kTitle[] = "Title";
26 const char kContent[] = "Content"; 32 const char kContent[] = "Content";
27 const char kURL[] = "http://a.com/"; 33 const char kURL[] = "http://a.com/";
28 const char kId0[] = "0"; 34 const size_t kTotalImages = 2;
29 const char kId1[] = "1"; 35 const char* kImageURLs[kTotalImages] = {"http://a.com/img1.jpg",
30 const char kImageURL0[] = "http://a.com/img1.jpg"; 36 "http://a.com/img2.jpg"};
31 const char kImageURL1[] = "http://a.com/img2.jpg"; 37 const char* kImageData[kTotalImages] = {"abcde", "12345"};
32 const char kImageData0[] = { 'a', 'b', 'c', 'd', 'e', 0 }; 38
33 const char kImageData1[] = { '1', '2', '3', '4', '5', 0 }; 39 const string GetImageName(int page_num, int image_num) {
40 return base::IntToString(page_num) + "_" + base::IntToString(image_num);
41 }
42
43 scoped_ptr<base::ListValue> CreateDistilledValueReturnedFromJS(
44 const string& title,
45 const string& content,
46 const vector<int>& image_indices,
47 const string& next_page_url) {
48 scoped_ptr<base::ListValue> list(new base::ListValue());
49
50 list->AppendString(title);
51 list->AppendString(content);
52 list->AppendString(next_page_url);
53 for (size_t i = 0; i < image_indices.size(); ++i) {
54 list->AppendString(kImageURLs[image_indices[i]]);
55 }
56 return list.Pass();
57 }
58
34 } // namespace 59 } // namespace
35 60
36 namespace dom_distiller { 61 namespace dom_distiller {
37 62
38 class TestDistillerURLFetcher : public DistillerURLFetcher { 63 class TestDistillerURLFetcher : public DistillerURLFetcher {
39 public: 64 public:
40 TestDistillerURLFetcher() : DistillerURLFetcher(NULL) { 65 TestDistillerURLFetcher() : DistillerURLFetcher(NULL) {
41 responses_[kImageURL0] = std::string(kImageData0); 66 responses_[kImageURLs[0]] = string(kImageData[0]);
42 responses_[kImageURL1] = std::string(kImageData1); 67 responses_[kImageURLs[1]] = string(kImageData[1]);
43 } 68 }
44 69
45 void CallCallback(std::string url, const URLFetcherCallback& callback) { 70 void CallCallback(string url, const URLFetcherCallback& callback) {
46 callback.Run(responses_[url]); 71 callback.Run(responses_[url]);
47 } 72 }
48 73
49 virtual void FetchURL(const std::string& url, 74 virtual void FetchURL(const string& url,
50 const URLFetcherCallback& callback) OVERRIDE { 75 const URLFetcherCallback& callback) OVERRIDE {
51 ASSERT_TRUE(base::MessageLoop::current()); 76 ASSERT_TRUE(base::MessageLoop::current());
52 base::MessageLoop::current()->PostTask( 77 base::MessageLoop::current()->PostTask(
53 FROM_HERE, 78 FROM_HERE,
54 base::Bind(&TestDistillerURLFetcher::CallCallback, 79 base::Bind(&TestDistillerURLFetcher::CallCallback,
55 base::Unretained(this), url, callback)); 80 base::Unretained(this), url, callback));
56 } 81 }
57 82
58 std::map<std::string, std::string> responses_; 83 std::map<string, string> responses_;
59 }; 84 };
60 85
61 86
62 class TestDistillerURLFetcherFactory : public DistillerURLFetcherFactory { 87 class TestDistillerURLFetcherFactory : public DistillerURLFetcherFactory {
63 public: 88 public:
64 TestDistillerURLFetcherFactory() : DistillerURLFetcherFactory(NULL) {} 89 TestDistillerURLFetcherFactory() : DistillerURLFetcherFactory(NULL) {}
65 virtual ~TestDistillerURLFetcherFactory() {} 90 virtual ~TestDistillerURLFetcherFactory() {}
66 virtual DistillerURLFetcher* CreateDistillerURLFetcher() const OVERRIDE { 91 virtual DistillerURLFetcher* CreateDistillerURLFetcher() const OVERRIDE {
67 return new TestDistillerURLFetcher(); 92 return new TestDistillerURLFetcher();
68 } 93 }
69 }; 94 };
70 95
71 96
72 class MockDistillerPage : public DistillerPage { 97 class MockDistillerPage : public DistillerPage {
73 public: 98 public:
74 MOCK_METHOD0(InitImpl, void()); 99 MOCK_METHOD0(InitImpl, void());
75 MOCK_METHOD1(LoadURLImpl, void(const GURL& gurl)); 100 MOCK_METHOD1(LoadURLImpl, void(const GURL& gurl));
76 MOCK_METHOD1(ExecuteJavaScriptImpl, void(const std::string& script)); 101 MOCK_METHOD1(ExecuteJavaScriptImpl, void(const string& script));
77 102
78 explicit MockDistillerPage(DistillerPage::Delegate* delegate) 103 explicit MockDistillerPage(DistillerPage::Delegate* delegate)
79 : DistillerPage(delegate) {} 104 : DistillerPage(delegate) {}
80 }; 105 };
81 106
82 107
83 class MockDistillerPageFactory : public DistillerPageFactory { 108 class MockDistillerPageFactory : public DistillerPageFactory {
84 public: 109 public:
85 MOCK_CONST_METHOD1( 110 MOCK_CONST_METHOD1(
86 CreateDistillerPageMock, 111 CreateDistillerPageMock,
87 DistillerPage*(DistillerPage::Delegate* delegate)); 112 DistillerPage*(DistillerPage::Delegate* delegate));
88 113
89 virtual scoped_ptr<DistillerPage> CreateDistillerPage( 114 virtual scoped_ptr<DistillerPage> CreateDistillerPage(
90 DistillerPage::Delegate* delegate) const OVERRIDE { 115 DistillerPage::Delegate* delegate) const OVERRIDE {
91 return scoped_ptr<DistillerPage>(CreateDistillerPageMock(delegate)); 116 return scoped_ptr<DistillerPage>(CreateDistillerPageMock(delegate));
92 } 117 }
93 }; 118 };
94 119
95 120
96 class DistillerTest : public testing::Test { 121 class DistillerTest : public testing::Test {
97 public: 122 public:
98 virtual ~DistillerTest() {} 123 virtual ~DistillerTest() {}
99 void OnDistillPageDone(scoped_ptr<DistilledPageProto> proto) { 124 void OnDistillPageDone(scoped_ptr<DistilledArticleProto> proto) {
100 proto_ = proto.Pass(); 125 article_proto_ = proto.Pass();
101 } 126 }
102 127
103 protected: 128 protected:
104 scoped_ptr<DistillerImpl> distiller_; 129 scoped_ptr<DistillerImpl> distiller_;
105 scoped_ptr<DistilledPageProto> proto_; 130 scoped_ptr<DistilledArticleProto> article_proto_;
106 MockDistillerPageFactory page_factory_; 131 MockDistillerPageFactory page_factory_;
107 TestDistillerURLFetcherFactory url_fetcher_factory_; 132 TestDistillerURLFetcherFactory url_fetcher_factory_;
108 }; 133 };
109 134
110 ACTION_P2(DistillerPageOnExecuteJavaScriptDone, distiller_page, list) { 135 ACTION_P3(DistillerPageOnExecuteJavaScriptDone, distiller_page, url, list) {
111 distiller_page->OnExecuteJavaScriptDone(list); 136 distiller_page->OnExecuteJavaScriptDone(url, list);
112 } 137 }
113 138
114 ACTION_P2(CreateMockDistillerPage, list, kurl) { 139 ACTION_P2(CreateMockDistillerPage, list, kurl) {
115 DistillerPage::Delegate* delegate = arg0; 140 DistillerPage::Delegate* delegate = arg0;
116 MockDistillerPage* distiller_page = new MockDistillerPage(delegate); 141 MockDistillerPage* distiller_page = new MockDistillerPage(delegate);
117 EXPECT_CALL(*distiller_page, InitImpl()); 142 EXPECT_CALL(*distiller_page, InitImpl());
118 EXPECT_CALL(*distiller_page, LoadURLImpl(kurl)) 143 EXPECT_CALL(*distiller_page, LoadURLImpl(kurl))
119 .WillOnce(testing::InvokeWithoutArgs(distiller_page, 144 .WillOnce(testing::InvokeWithoutArgs(distiller_page,
120 &DistillerPage::OnLoadURLDone)); 145 &DistillerPage::OnLoadURLDone));
121 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_)) 146 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_)).WillOnce(
122 .WillOnce(DistillerPageOnExecuteJavaScriptDone(distiller_page, list)); 147 DistillerPageOnExecuteJavaScriptDone(distiller_page, kurl, list));
148 return distiller_page;
149 }
150
151 ACTION_P3(CreateMockDistillerPages, lists, kurls, num_pages) {
152 DistillerPage::Delegate* delegate = arg0;
153 MockDistillerPage* distiller_page = new MockDistillerPage(delegate);
154 EXPECT_CALL(*distiller_page, InitImpl());
155 {
156 testing::InSequence s;
157
158 for (int page = 0; page < num_pages; ++page) {
159 GURL url = GURL(kurls[page]);
160 EXPECT_CALL(*distiller_page, LoadURLImpl(url))
161 .WillOnce(testing::InvokeWithoutArgs(distiller_page,
162 &DistillerPage::OnLoadURLDone));
163 EXPECT_CALL(*distiller_page, ExecuteJavaScriptImpl(_))
164 .WillOnce(DistillerPageOnExecuteJavaScriptDone(
165 distiller_page, url, lists[page].get()));
166 }
167 }
123 return distiller_page; 168 return distiller_page;
124 } 169 }
125 170
126 TEST_F(DistillerTest, DistillPage) { 171 TEST_F(DistillerTest, DistillPage) {
127 base::MessageLoopForUI loop; 172 base::MessageLoopForUI loop;
128 scoped_ptr<base::ListValue> list(new base::ListValue()); 173 vector<int> image_indices;
cjhopman 2014/02/03 21:47:22 Could we have a test for distilling a page with no
shashi 2014/02/03 23:19:29 Done.
129 list->AppendString(kTitle); 174 image_indices.push_back(0);
130 list->AppendString(kContent); 175 image_indices.push_back(1);
131 list->AppendString(kImageURL0); 176 scoped_ptr<base::ListValue> list =
132 list->AppendString(kImageURL1); 177 CreateDistilledValueReturnedFromJS(kTitle, kContent, image_indices, "");
133 EXPECT_CALL(page_factory_, 178 EXPECT_CALL(page_factory_,
134 CreateDistillerPageMock(_)).WillOnce( 179 CreateDistillerPageMock(_)).WillOnce(
135 CreateMockDistillerPage(list.get(), GURL(kURL))); 180 CreateMockDistillerPage(list.get(), GURL(kURL)));
136 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_)); 181 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_));
137 distiller_->Init(); 182 distiller_->Init();
138 distiller_->DistillPage( 183 distiller_->DistillPage(
139 GURL(kURL), 184 GURL(kURL),
140 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this))); 185 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this)));
141 base::MessageLoop::current()->RunUntilIdle(); 186 base::MessageLoop::current()->RunUntilIdle();
142 EXPECT_EQ(kTitle, proto_->title()); 187 EXPECT_EQ(kTitle, article_proto_->title());
143 EXPECT_EQ(kContent, proto_->html()); 188 EXPECT_EQ(article_proto_->pages_size(), 1);
144 EXPECT_EQ(kURL, proto_->url()); 189 const DistilledPageProto& first_page = article_proto_->pages(0);
145 EXPECT_EQ(2, proto_->image_size()); 190 EXPECT_EQ(kContent, first_page.html());
146 EXPECT_EQ(kImageData0, proto_->image(0).data()); 191 EXPECT_EQ(kURL, first_page.url());
147 EXPECT_EQ(kId0, proto_->image(0).name()); 192 EXPECT_EQ(2, first_page.image_size());
148 EXPECT_EQ(kImageData1, proto_->image(1).data()); 193 EXPECT_EQ(kImageData[0], first_page.image(0).data());
149 EXPECT_EQ(kId1, proto_->image(1).name()); 194 EXPECT_EQ(GetImageName(1, 0), first_page.image(0).name());
195 EXPECT_EQ(kImageData[1], first_page.image(1).data());
196 EXPECT_EQ(GetImageName(1, 1), first_page.image(1).name());
197 }
198
199 TEST_F(DistillerTest, DistillMultiplePages) {
200 base::MessageLoopForUI loop;
201 const int kNumPages = 8;
202 vector<int> image_indices[kNumPages];
203 string content[kNumPages];
204 string page_urls[kNumPages];
205 scoped_ptr<base::ListValue> list[kNumPages];
206
207 int next_image_number = 0;
208
209 for (int page_num = 0; page_num < kNumPages; ++page_num) {
210 // Each page has different number of images.
211 int tot_images = (page_num + kTotalImages) % (kTotalImages + 1);
212 for (int img_num = 0; img_num < tot_images; img_num++) {
213 image_indices[page_num].push_back(next_image_number);
214 next_image_number = (next_image_number + 1) % kTotalImages;
215 }
216
217 page_urls[page_num] = "http://a.com/" + base::IntToString(page_num);
218 content[page_num] = "Content for page:" + base::IntToString(page_num);
219 }
220 for (int i = 0; i < kNumPages; ++i) {
221 string next_page_url = "";
222 if (i + 1 < kNumPages)
223 next_page_url = page_urls[i + 1];
224
225 list[i] = CreateDistilledValueReturnedFromJS(
226 kTitle, content[i], image_indices[i], next_page_url);
227 }
228
229 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_))
230 .WillOnce(CreateMockDistillerPages(list, page_urls, kNumPages));
231
232 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_));
233 distiller_->Init();
234 distiller_->DistillPage(
235 GURL(page_urls[0]),
236 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this)));
237 base::MessageLoop::current()->RunUntilIdle();
238 EXPECT_EQ(kTitle, article_proto_->title());
239 EXPECT_EQ(article_proto_->pages_size(), kNumPages);
240 for (int page_num = 0; page_num < kNumPages; ++page_num) {
241 const DistilledPageProto& page = article_proto_->pages(page_num);
242 EXPECT_EQ(content[page_num], page.html());
243 EXPECT_EQ(page_urls[page_num], page.url());
244 EXPECT_EQ(image_indices[page_num].size(),
245 static_cast<size_t>(page.image_size()));
246 for (size_t img_num = 0; img_num < image_indices[page_num].size();
247 ++img_num) {
248 EXPECT_EQ(kImageData[image_indices[page_num][img_num]],
249 page.image(img_num).data());
250 EXPECT_EQ(GetImageName(page_num + 1, img_num),
251 page.image(img_num).name());
252 }
253 }
254 }
255
256 TEST_F(DistillerTest, DistillLinkLoop) {
257 base::MessageLoopForUI loop;
258 vector<int> image_indices;
cjhopman 2014/02/03 21:47:22 Don't have images here if they aren't needed for t
shashi 2014/02/03 23:19:29 Done.
259 image_indices.push_back(0);
260 image_indices.push_back(1);
261 // Create a loop, the next page is same as the current page. This could
262 // happen if javascript misparses a next page link.
263 scoped_ptr<base::ListValue> list =
264 CreateDistilledValueReturnedFromJS(kTitle, kContent, image_indices, kURL);
265 EXPECT_CALL(page_factory_, CreateDistillerPageMock(_))
266 .WillOnce(CreateMockDistillerPage(list.get(), GURL(kURL)));
267 distiller_.reset(new DistillerImpl(page_factory_, url_fetcher_factory_));
268 distiller_->Init();
269 distiller_->DistillPage(
270 GURL(kURL),
271 base::Bind(&DistillerTest::OnDistillPageDone, base::Unretained(this)));
272 base::MessageLoop::current()->RunUntilIdle();
273 EXPECT_EQ(kTitle, article_proto_->title());
274 EXPECT_EQ(article_proto_->pages_size(), 1);
150 } 275 }
151 276
152 } // namespace dom_distiller 277 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698