1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/network/upload_progress_tracker.h"
6 
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/macros.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/test/test_mock_time_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "net/base/upload_progress.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace network {
18 namespace {
19 
20 class TestingUploadProgressTracker : public UploadProgressTracker {
21  public:
TestingUploadProgressTracker(const base::Location & location,UploadProgressReportCallback report_callback,scoped_refptr<base::SingleThreadTaskRunner> task_runner)22   TestingUploadProgressTracker(
23       const base::Location& location,
24       UploadProgressReportCallback report_callback,
25       scoped_refptr<base::SingleThreadTaskRunner> task_runner)
26       : UploadProgressTracker(location,
27                               std::move(report_callback),
28                               nullptr,
29                               std::move(task_runner)),
30         current_time_(base::TimeTicks::Now()) {}
31 
set_upload_progress(const net::UploadProgress & upload_progress)32   void set_upload_progress(const net::UploadProgress& upload_progress) {
33     upload_progress_ = upload_progress;
34   }
35 
set_current_time(const base::TimeTicks & current_time)36   void set_current_time(const base::TimeTicks& current_time) {
37     current_time_ = current_time;
38   }
39 
40  private:
41   // UploadProgressTracker overrides.
GetCurrentTime() const42   base::TimeTicks GetCurrentTime() const override { return current_time_; }
GetUploadProgress() const43   net::UploadProgress GetUploadProgress() const override {
44     return upload_progress_;
45   }
46 
47   base::TimeTicks current_time_;
48   net::UploadProgress upload_progress_;
49 
50   DISALLOW_COPY_AND_ASSIGN(TestingUploadProgressTracker);
51 };
52 
53 }  // namespace
54 
55 class UploadProgressTrackerTest : public ::testing::Test {
56  public:
UploadProgressTrackerTest()57   UploadProgressTrackerTest()
58       : task_runner_handle_(mock_task_runner_),
59         upload_progress_tracker_(
60             FROM_HERE,
61             base::BindRepeating(
62                 &UploadProgressTrackerTest::OnUploadProgressReported,
63                 base::Unretained(this)),
64             mock_task_runner_) {}
65 
66  private:
OnUploadProgressReported(const net::UploadProgress & progress)67   void OnUploadProgressReported(const net::UploadProgress& progress) {
68     ++report_count_;
69     reported_position_ = progress.position();
70     reported_total_size_ = progress.size();
71   }
72 
73  protected:
74   int report_count_ = 0;
75   int64_t reported_position_ = 0;
76   int64_t reported_total_size_ = 0;
77 
78   // Mocks the current thread's task runner which will also be used as the
79   // UploadProgressTracker's task runner.
80   scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_ =
81       new base::TestMockTimeTaskRunner;
82   base::ThreadTaskRunnerHandle task_runner_handle_;
83 
84   TestingUploadProgressTracker upload_progress_tracker_;
85 
86   DISALLOW_COPY_AND_ASSIGN(UploadProgressTrackerTest);
87 };
88 
TEST_F(UploadProgressTrackerTest,NoACK)89 TEST_F(UploadProgressTrackerTest, NoACK) {
90   upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000));
91 
92   // The first timer task calls ReportUploadProgress.
93   EXPECT_EQ(0, report_count_);
94   mock_task_runner_->FastForwardBy(
95       UploadProgressTracker::GetUploadProgressIntervalForTesting());
96   EXPECT_EQ(1, report_count_);
97   EXPECT_EQ(500, reported_position_);
98   EXPECT_EQ(1000, reported_total_size_);
99 
100   upload_progress_tracker_.set_upload_progress(net::UploadProgress(750, 1000));
101 
102   // The second timer task does nothing, since the first report didn't send the
103   // ACK.
104   mock_task_runner_->FastForwardBy(
105       UploadProgressTracker::GetUploadProgressIntervalForTesting());
106   EXPECT_EQ(1, report_count_);
107 }
108 
TEST_F(UploadProgressTrackerTest,NoUpload)109 TEST_F(UploadProgressTrackerTest, NoUpload) {
110   upload_progress_tracker_.set_upload_progress(net::UploadProgress(0, 0));
111 
112   // UploadProgressTracker does nothing on the empty upload content.
113   EXPECT_EQ(0, report_count_);
114   mock_task_runner_->FastForwardBy(
115       UploadProgressTracker::GetUploadProgressIntervalForTesting());
116   EXPECT_EQ(0, report_count_);
117 }
118 
TEST_F(UploadProgressTrackerTest,NoProgress)119 TEST_F(UploadProgressTrackerTest, NoProgress) {
120   upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000));
121 
122   // The first timer task calls ReportUploadProgress.
123   EXPECT_EQ(0, report_count_);
124   mock_task_runner_->FastForwardBy(
125       UploadProgressTracker::GetUploadProgressIntervalForTesting());
126   EXPECT_EQ(1, report_count_);
127   EXPECT_EQ(500, reported_position_);
128   EXPECT_EQ(1000, reported_total_size_);
129 
130   upload_progress_tracker_.OnAckReceived();
131 
132   // The second time doesn't call ReportUploadProgress since there's no
133   // progress.
134   EXPECT_EQ(1, report_count_);
135   mock_task_runner_->FastForwardBy(
136       UploadProgressTracker::GetUploadProgressIntervalForTesting());
137   EXPECT_EQ(1, report_count_);
138 }
139 
TEST_F(UploadProgressTrackerTest,Finished)140 TEST_F(UploadProgressTrackerTest, Finished) {
141   upload_progress_tracker_.set_upload_progress(net::UploadProgress(999, 1000));
142 
143   // The first timer task calls ReportUploadProgress.
144   EXPECT_EQ(0, report_count_);
145   mock_task_runner_->FastForwardBy(
146       UploadProgressTracker::GetUploadProgressIntervalForTesting());
147   EXPECT_EQ(1, report_count_);
148   EXPECT_EQ(999, reported_position_);
149   EXPECT_EQ(1000, reported_total_size_);
150 
151   upload_progress_tracker_.OnAckReceived();
152   upload_progress_tracker_.set_upload_progress(net::UploadProgress(1000, 1000));
153 
154   // The second timer task calls ReportUploadProgress for reporting the
155   // completion.
156   EXPECT_EQ(1, report_count_);
157   mock_task_runner_->FastForwardBy(
158       UploadProgressTracker::GetUploadProgressIntervalForTesting());
159   EXPECT_EQ(2, report_count_);
160   EXPECT_EQ(1000, reported_position_);
161   EXPECT_EQ(1000, reported_total_size_);
162 }
163 
TEST_F(UploadProgressTrackerTest,Progress)164 TEST_F(UploadProgressTrackerTest, Progress) {
165   upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000));
166 
167   // The first timer task calls ReportUploadProgress.
168   EXPECT_EQ(0, report_count_);
169   mock_task_runner_->FastForwardBy(
170       UploadProgressTracker::GetUploadProgressIntervalForTesting());
171   EXPECT_EQ(1, report_count_);
172   EXPECT_EQ(500, reported_position_);
173   EXPECT_EQ(1000, reported_total_size_);
174 
175   upload_progress_tracker_.OnAckReceived();
176   upload_progress_tracker_.set_upload_progress(net::UploadProgress(750, 1000));
177 
178   // The second timer task calls ReportUploadProgress since the progress is
179   // big enough to report.
180   EXPECT_EQ(1, report_count_);
181   mock_task_runner_->FastForwardBy(
182       UploadProgressTracker::GetUploadProgressIntervalForTesting());
183   EXPECT_EQ(2, report_count_);
184   EXPECT_EQ(750, reported_position_);
185   EXPECT_EQ(1000, reported_total_size_);
186 }
187 
TEST_F(UploadProgressTrackerTest,TimePassed)188 TEST_F(UploadProgressTrackerTest, TimePassed) {
189   upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000));
190 
191   // The first timer task calls ReportUploadProgress.
192   EXPECT_EQ(0, report_count_);
193   mock_task_runner_->FastForwardBy(
194       UploadProgressTracker::GetUploadProgressIntervalForTesting());
195   EXPECT_EQ(1, report_count_);
196   EXPECT_EQ(500, reported_position_);
197   EXPECT_EQ(1000, reported_total_size_);
198 
199   upload_progress_tracker_.OnAckReceived();
200   upload_progress_tracker_.set_upload_progress(net::UploadProgress(501, 1000));
201 
202   // The second timer task doesn't call ReportUploadProgress since the progress
203   // is too small to report it.
204   EXPECT_EQ(1, report_count_);
205   mock_task_runner_->FastForwardBy(
206       UploadProgressTracker::GetUploadProgressIntervalForTesting());
207   EXPECT_EQ(1, report_count_);
208 
209   upload_progress_tracker_.set_current_time(base::TimeTicks::Now() +
210                                             base::TimeDelta::FromSeconds(5));
211 
212   // The third timer task calls ReportUploadProgress since it's been long time
213   // from the last report.
214   EXPECT_EQ(1, report_count_);
215   mock_task_runner_->FastForwardBy(
216       UploadProgressTracker::GetUploadProgressIntervalForTesting());
217   EXPECT_EQ(2, report_count_);
218   EXPECT_EQ(501, reported_position_);
219   EXPECT_EQ(1000, reported_total_size_);
220 }
221 
TEST_F(UploadProgressTrackerTest,Rewound)222 TEST_F(UploadProgressTrackerTest, Rewound) {
223   upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000));
224 
225   // The first timer task calls ReportUploadProgress.
226   EXPECT_EQ(0, report_count_);
227   mock_task_runner_->FastForwardBy(
228       UploadProgressTracker::GetUploadProgressIntervalForTesting());
229   EXPECT_EQ(1, report_count_);
230   EXPECT_EQ(500, reported_position_);
231   EXPECT_EQ(1000, reported_total_size_);
232 
233   upload_progress_tracker_.OnAckReceived();
234   upload_progress_tracker_.set_upload_progress(net::UploadProgress(250, 1000));
235 
236   // The second timer task doesn't call ReportUploadProgress since the progress
237   // was rewound.
238   EXPECT_EQ(1, report_count_);
239   mock_task_runner_->FastForwardBy(
240       UploadProgressTracker::GetUploadProgressIntervalForTesting());
241   EXPECT_EQ(1, report_count_);
242 
243   upload_progress_tracker_.set_current_time(base::TimeTicks::Now() +
244                                             base::TimeDelta::FromSeconds(5));
245 
246   // Even after a good amount of time passed, the rewound progress should not be
247   // reported.
248   EXPECT_EQ(1, report_count_);
249   mock_task_runner_->FastForwardBy(
250       UploadProgressTracker::GetUploadProgressIntervalForTesting());
251   EXPECT_EQ(1, report_count_);
252 }
253 
TEST_F(UploadProgressTrackerTest,Completed)254 TEST_F(UploadProgressTrackerTest, Completed) {
255   upload_progress_tracker_.set_upload_progress(net::UploadProgress(500, 1000));
256 
257   // The first timer task calls ReportUploadProgress.
258   EXPECT_EQ(0, report_count_);
259   mock_task_runner_->FastForwardBy(
260       UploadProgressTracker::GetUploadProgressIntervalForTesting());
261   EXPECT_EQ(1, report_count_);
262   EXPECT_EQ(500, reported_position_);
263   EXPECT_EQ(1000, reported_total_size_);
264 
265   upload_progress_tracker_.set_upload_progress(net::UploadProgress(1000, 1000));
266 
267   // OnUploadCompleted runs ReportUploadProgress even without Ack nor timer.
268   upload_progress_tracker_.OnUploadCompleted();
269   EXPECT_EQ(2, report_count_);
270   EXPECT_EQ(1000, reported_position_);
271   EXPECT_EQ(1000, reported_total_size_);
272 
273   mock_task_runner_->FastForwardBy(
274       UploadProgressTracker::GetUploadProgressIntervalForTesting());
275   EXPECT_EQ(2, report_count_);
276   EXPECT_FALSE(mock_task_runner_->HasPendingTask());
277 }
278 
279 }  // namespace network
280