1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/dom_distiller/core/task_tracker.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/run_loop.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/dom_distiller/core/article_distillation_update.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/dom_distiller/core/article_entry.h"
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/dom_distiller/core/distilled_content_store.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/dom_distiller/core/fake_distiller.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using testing::Return;
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using testing::_;
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace dom_distiller {
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace test {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class FakeViewRequestDelegate : public ViewRequestDelegate {
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~FakeViewRequestDelegate() {}
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD1(OnArticleReady,
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               void(const DistilledArticleProto* article_proto));
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MOCK_METHOD1(OnArticleUpdated,
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               void(ArticleDistillationUpdate article_update));
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass MockContentStore : public DistilledContentStore {
300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public:
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MOCK_METHOD2(LoadContent,
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)               void(const ArticleEntry& entry, LoadCallback callback));
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MOCK_METHOD3(SaveContent,
340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch               void(const ArticleEntry& entry,
350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    const DistilledArticleProto& proto,
360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                    SaveCallback callback));
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class TestCancelCallback {
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback() : cancelled_(false) {}
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TaskTracker::CancelCallback GetCallback() {
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return base::Bind(&TestCancelCallback::Cancel, base::Unretained(this));
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void Cancel(TaskTracker*) { cancelled_ = true; }
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool Cancelled() { return cancelled_; }
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool cancelled_;
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class MockSaveCallback {
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MOCK_METHOD3(Save,
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               void(const ArticleEntry&, const DistilledArticleProto*, bool));
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class DomDistillerTaskTrackerTest : public testing::Test {
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    message_loop_.reset(new base::MessageLoop());
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    entry_id_ = "id0";
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    page_0_url_ = GURL("http://www.example.com/1");
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    page_1_url_ = GURL("http://www.example.com/2");
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ArticleEntry GetDefaultEntry() {
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ArticleEntry entry;
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    entry.set_entry_id(entry_id_);
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ArticleEntryPage* page0 = entry.add_pages();
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ArticleEntryPage* page1 = entry.add_pages();
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    page0->set_url(page_0_url_.spec());
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    page1->set_url(page_1_url_.spec());
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return entry;
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<base::MessageLoop> message_loop_;
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string entry_id_;
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GURL page_0_url_;
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GURL page_1_url_;
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(DomDistillerTaskTrackerTest, TestHasEntryId) {
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockDistillerFactory distiller_factory;
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback cancel_callback;
870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(task_tracker.HasEntryId(entry_id_));
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(task_tracker.HasEntryId("other_id"));
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(DomDistillerTaskTrackerTest, TestHasUrl) {
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockDistillerFactory distiller_factory;
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback cancel_callback;
960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(task_tracker.HasUrl(page_0_url_));
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(task_tracker.HasUrl(page_1_url_));
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(task_tracker.HasUrl(GURL("http://other.url/")));
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(DomDistillerTaskTrackerTest, TestViewerCancelled) {
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockDistillerFactory distiller_factory;
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback cancel_callback;
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
1070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FakeViewRequestDelegate viewer_delegate;
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FakeViewRequestDelegate viewer_delegate2;
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ViewerHandle> handle2(task_tracker.AddViewer(&viewer_delegate2));
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(cancel_callback.Cancelled());
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  handle.reset();
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(cancel_callback.Cancelled());
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  handle2.reset();
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(cancel_callback.Cancelled());
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(DomDistillerTaskTrackerTest, TestViewerCancelledWithSaveRequest) {
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockDistillerFactory distiller_factory;
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback cancel_callback;
1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
1250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FakeViewRequestDelegate viewer_delegate;
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(cancel_callback.Cancelled());
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockSaveCallback save_callback;
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  task_tracker.AddSaveCallback(
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&MockSaveCallback::Save, base::Unretained(&save_callback)));
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  handle.reset();
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Since there is a pending save request, the task shouldn't be cancelled.
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(cancel_callback.Cancelled());
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(DomDistillerTaskTrackerTest, TestViewerNotifiedOnDistillationComplete) {
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockDistillerFactory distiller_factory;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FakeDistiller* distiller = new FakeDistiller(true);
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      .WillOnce(Return(distiller));
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback cancel_callback;
1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
1470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  FakeViewRequestDelegate viewer_delegate;
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(viewer_delegate, OnArticleReady(_));
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  task_tracker.StartDistiller(&distiller_factory,
1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                              scoped_ptr<DistillerPage>().Pass());
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(cancel_callback.Cancelled());
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(DomDistillerTaskTrackerTest, TestDistillerFails) {
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MockDistillerFactory distiller_factory;
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FakeDistiller* distiller = new FakeDistiller(false);
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      .WillOnce(Return(distiller));
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TestCancelCallback cancel_callback;
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  TaskTracker task_tracker(
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FakeViewRequestDelegate viewer_delegate;
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_CALL(viewer_delegate, OnArticleReady(_));
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  task_tracker.StartDistiller(&distiller_factory,
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              scoped_ptr<DistillerPage>().Pass());
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  distiller->RunDistillerCallback(
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      scoped_ptr<DistilledArticleProto>(new DistilledArticleProto));
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(cancel_callback.Cancelled());
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(DomDistillerTaskTrackerTest,
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       TestSaveCallbackCalledOnDistillationComplete) {
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockDistillerFactory distiller_factory;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FakeDistiller* distiller = new FakeDistiller(true);
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      .WillOnce(Return(distiller));
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TestCancelCallback cancel_callback;
1940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  MockSaveCallback save_callback;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  task_tracker.AddSaveCallback(
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::Bind(&MockSaveCallback::Save, base::Unretained(&save_callback)));
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_CALL(save_callback, Save(_, _, _));
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  task_tracker.StartDistiller(&distiller_factory,
2055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                              scoped_ptr<DistillerPage>().Pass());
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_TRUE(cancel_callback.Cancelled());
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2110529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochDistilledArticleProto CreateDistilledArticleForEntry(
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    const ArticleEntry& entry) {
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledArticleProto article;
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  for (int i = 0; i < entry.pages_size(); ++i) {
2150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DistilledPageProto* page = article.add_pages();
2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    page->set_url(entry.pages(i).url());
2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    page->set_html("<div>" + entry.pages(i).url() + "</div>");
2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return article;
2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2220529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(DomDistillerTaskTrackerTest, TestBlobFetcher) {
2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ArticleEntry entry_with_blob = GetDefaultEntry();
2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledArticleProto stored_distilled_article =
2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      CreateDistilledArticleForEntry(entry_with_blob);
22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  content_store.InjectContent(entry_with_blob, stored_distilled_article);
2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TestCancelCallback cancel_callback;
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      entry_with_blob, cancel_callback.GetCallback(), &content_store);
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeViewRequestDelegate viewer_delegate;
2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const DistilledArticleProto* distilled_article;
2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_))
2400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(testing::SaveArg<0>(&distilled_article));
2410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  task_tracker.StartBlobFetcher();
2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
2440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_EQ(stored_distilled_article.SerializeAsString(),
2460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            distilled_article->SerializeAsString());
2470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_FALSE(cancel_callback.Cancelled());
2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2510529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(DomDistillerTaskTrackerTest, TestBlobFetcherFinishesFirst) {
2520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MockDistillerFactory distiller_factory;
2530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeDistiller* distiller = new FakeDistiller(false);
2540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(Return(distiller));
2560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ArticleEntry entry_with_blob = GetDefaultEntry();
2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledArticleProto stored_distilled_article =
2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      CreateDistilledArticleForEntry(entry_with_blob);
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  content_store.InjectContent(entry_with_blob, stored_distilled_article);
2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TestCancelCallback cancel_callback;
2630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      entry_with_blob, cancel_callback.GetCallback(), &content_store);
2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeViewRequestDelegate viewer_delegate;
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledArticleProto distilled_article;
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_))
2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(testing::SaveArgPointee<0>(&distilled_article));
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  bool distiller_destroyed = false;
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(*distiller, Die())
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(testing::Assign(&distiller_destroyed, true));
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  task_tracker.StartDistiller(&distiller_factory,
2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                              scoped_ptr<DistillerPage>().Pass());
2800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  task_tracker.StartBlobFetcher();
2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  testing::Mock::VerifyAndClearExpectations(&viewer_delegate);
2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_EQ(stored_distilled_article.SerializeAsString(),
2850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            distilled_article.SerializeAsString());
2860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_TRUE(distiller_destroyed);
2880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_FALSE(cancel_callback.Cancelled());
2890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
2900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2920529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(DomDistillerTaskTrackerTest, TestBlobFetcherWithoutBlob) {
2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MockDistillerFactory distiller_factory;
2940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeDistiller* distiller = new FakeDistiller(false);
2950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
2960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(Return(distiller));
2970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ArticleEntry entry(GetDefaultEntry());
29946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
3000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<DistilledArticleProto> distilled_article(
3010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      new DistilledArticleProto(CreateDistilledArticleForEntry(entry)));
3020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TestCancelCallback cancel_callback;
3040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
3050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), &content_store);
3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeViewRequestDelegate viewer_delegate;
3080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  task_tracker.StartBlobFetcher();
3125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  task_tracker.StartDistiller(&distiller_factory,
3135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                              scoped_ptr<DistillerPage>().Pass());
3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // OnArticleReady shouldn't be called until distillation finishes (i.e. the
3160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // blob fetcher shouldn't return distilled content).
3170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
3180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
3190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_));
3210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  distiller->RunDistillerCallback(distilled_article.Pass());
3220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
3230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_FALSE(cancel_callback.Cancelled());
3250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3270529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(DomDistillerTaskTrackerTest, TestDistillerFailsFirst) {
3280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MockDistillerFactory distiller_factory;
3290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeDistiller* distiller = new FakeDistiller(false);
3300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
3310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(Return(distiller));
3320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ArticleEntry entry(GetDefaultEntry());
3340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MockContentStore content_store;
3350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TestCancelCallback cancel_callback;
3370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
3380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), &content_store);
3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeViewRequestDelegate viewer_delegate;
3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledContentStore::LoadCallback content_store_load_callback;
3445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_CALL(content_store, LoadContent(_, _))
3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      .WillOnce(testing::SaveArg<1>(&content_store_load_callback));
3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  task_tracker.StartDistiller(&distiller_factory,
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                              scoped_ptr<DistillerPage>().Pass());
3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  task_tracker.StartBlobFetcher();
3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  distiller->RunDistillerCallback(
3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      scoped_ptr<DistilledArticleProto>(new DistilledArticleProto));
3540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_));
3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  content_store_load_callback.Run(
3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      true,
3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      scoped_ptr<DistilledArticleProto>(
3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          new DistilledArticleProto(CreateDistilledArticleForEntry(entry))));
3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_FALSE(cancel_callback.Cancelled());
3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3660529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochTEST_F(DomDistillerTaskTrackerTest, ContentIsSaved) {
3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MockDistillerFactory distiller_factory;
3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeDistiller* distiller = new FakeDistiller(false);
3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(distiller_factory, CreateDistillerImpl())
3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(Return(distiller));
3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ArticleEntry entry(GetDefaultEntry());
3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledArticleProto distilled_article =
3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      CreateDistilledArticleForEntry(entry);
3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  MockContentStore content_store;
3770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TestCancelCallback cancel_callback;
3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  TaskTracker task_tracker(
3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      GetDefaultEntry(), cancel_callback.GetCallback(), &content_store);
3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  FakeViewRequestDelegate viewer_delegate;
3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledArticleProto stored_distilled_article;
3850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DistilledContentStore::LoadCallback content_store_load_callback;
3860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(content_store, SaveContent(_, _, _))
3870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      .WillOnce(testing::SaveArg<1>(&stored_distilled_article));
3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  task_tracker.StartDistiller(&distiller_factory,
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                              scoped_ptr<DistillerPage>().Pass());
3910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_CALL(viewer_delegate, OnArticleReady(_));
3930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  distiller->RunDistillerCallback(scoped_ptr<DistilledArticleProto>(
3940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      new DistilledArticleProto(distilled_article)));
3950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::RunLoop().RunUntilIdle();
3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ASSERT_EQ(stored_distilled_article.SerializeAsString(),
3980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            distilled_article.SerializeAsString());
3990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  EXPECT_FALSE(cancel_callback.Cancelled());
4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace test
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace dom_distiller
404