1//
2// Copyright (C) 2012 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "update_engine/payload_state.h"
18
19#include <base/files/file_path.h>
20#include <base/files/file_util.h>
21#include <base/strings/stringprintf.h>
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
24
25#include "update_engine/common/constants.h"
26#include "update_engine/common/fake_clock.h"
27#include "update_engine/common/fake_hardware.h"
28#include "update_engine/common/fake_prefs.h"
29#include "update_engine/common/mock_prefs.h"
30#include "update_engine/common/prefs.h"
31#include "update_engine/common/test_utils.h"
32#include "update_engine/common/utils.h"
33#include "update_engine/fake_system_state.h"
34#include "update_engine/omaha_request_action.h"
35
36using base::Time;
37using base::TimeDelta;
38using std::string;
39using testing::AnyNumber;
40using testing::AtLeast;
41using testing::Mock;
42using testing::NiceMock;
43using testing::Return;
44using testing::SetArgumentPointee;
45using testing::_;
46
47namespace chromeos_update_engine {
48
49const char* kCurrentBytesDownloadedFromHttps =
50  "current-bytes-downloaded-from-HttpsServer";
51const char* kTotalBytesDownloadedFromHttps =
52  "total-bytes-downloaded-from-HttpsServer";
53const char* kCurrentBytesDownloadedFromHttp =
54  "current-bytes-downloaded-from-HttpServer";
55const char* kTotalBytesDownloadedFromHttp =
56  "total-bytes-downloaded-from-HttpServer";
57const char* kCurrentBytesDownloadedFromHttpPeer =
58  "current-bytes-downloaded-from-HttpPeer";
59const char* kTotalBytesDownloadedFromHttpPeer =
60  "total-bytes-downloaded-from-HttpPeer";
61
62static void SetupPayloadStateWith2Urls(string hash,
63                                       bool http_enabled,
64                                       PayloadState* payload_state,
65                                       OmahaResponse* response) {
66  response->payload_urls.clear();
67  response->payload_urls.push_back("http://test");
68  response->payload_urls.push_back("https://test");
69  response->size = 523456789;
70  response->hash = hash;
71  response->metadata_size = 558123;
72  response->metadata_signature = "metasign";
73  response->max_failure_count_per_url = 3;
74  payload_state->SetResponse(*response);
75  string stored_response_sign = payload_state->GetResponseSignature();
76
77  string expected_url_https_only =
78      "NumURLs = 1\n"
79      "Candidate Url0 = https://test\n";
80
81  string expected_urls_both =
82      "NumURLs = 2\n"
83      "Candidate Url0 = http://test\n"
84      "Candidate Url1 = https://test\n";
85
86  string expected_response_sign =
87      (http_enabled ? expected_urls_both : expected_url_https_only) +
88      base::StringPrintf("Payload Size = 523456789\n"
89                         "Payload Sha256 Hash = %s\n"
90                         "Metadata Size = 558123\n"
91                         "Metadata Signature = metasign\n"
92                         "Is Delta Payload = %d\n"
93                         "Max Failure Count Per Url = %d\n"
94                         "Disable Payload Backoff = %d\n",
95                         hash.c_str(),
96                         response->is_delta_payload,
97                         response->max_failure_count_per_url,
98                         response->disable_payload_backoff);
99  EXPECT_EQ(expected_response_sign, stored_response_sign);
100}
101
102class PayloadStateTest : public ::testing::Test { };
103
104TEST(PayloadStateTest, SetResponseWorksWithEmptyResponse) {
105  OmahaResponse response;
106  FakeSystemState fake_system_state;
107  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
108  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
109  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
110    .Times(AtLeast(1));
111  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
112    .Times(AtLeast(1));
113  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, 0)).Times(AtLeast(1));
114  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(AtLeast(1));
115  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
116    .Times(AtLeast(1));
117  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateTimestampStart, _))
118    .Times(AtLeast(1));
119  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateDurationUptime, _))
120    .Times(AtLeast(1));
121  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
122    .Times(AtLeast(1));
123  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
124    .Times(AtLeast(1));
125  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttpPeer, 0))
126    .Times(AtLeast(1));
127  EXPECT_CALL(*prefs, SetInt64(kPrefsNumReboots, 0)).Times(AtLeast(1));
128  PayloadState payload_state;
129  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
130  payload_state.SetResponse(response);
131  string stored_response_sign = payload_state.GetResponseSignature();
132  string expected_response_sign = "NumURLs = 0\n"
133                                  "Payload Size = 0\n"
134                                  "Payload Sha256 Hash = \n"
135                                  "Metadata Size = 0\n"
136                                  "Metadata Signature = \n"
137                                  "Is Delta Payload = 0\n"
138                                  "Max Failure Count Per Url = 0\n"
139                                  "Disable Payload Backoff = 0\n";
140  EXPECT_EQ(expected_response_sign, stored_response_sign);
141  EXPECT_EQ("", payload_state.GetCurrentUrl());
142  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
143  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
144  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
145}
146
147TEST(PayloadStateTest, SetResponseWorksWithSingleUrl) {
148  OmahaResponse response;
149  response.payload_urls.push_back("https://single.url.test");
150  response.size = 123456789;
151  response.hash = "hash";
152  response.metadata_size = 58123;
153  response.metadata_signature = "msign";
154  FakeSystemState fake_system_state;
155  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
156  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
157  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
158    .Times(AtLeast(1));
159  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
160    .Times(AtLeast(1));
161  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, 0))
162    .Times(AtLeast(1));
163  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
164    .Times(AtLeast(1));
165  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
166    .Times(AtLeast(1));
167  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateTimestampStart, _))
168    .Times(AtLeast(1));
169  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateDurationUptime, _))
170    .Times(AtLeast(1));
171  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
172    .Times(AtLeast(1));
173  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
174    .Times(AtLeast(1));
175  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttpPeer, 0))
176    .Times(AtLeast(1));
177  EXPECT_CALL(*prefs, SetInt64(kPrefsNumReboots, 0))
178      .Times(AtLeast(1));
179  PayloadState payload_state;
180  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
181  payload_state.SetResponse(response);
182  string stored_response_sign = payload_state.GetResponseSignature();
183  string expected_response_sign = "NumURLs = 1\n"
184                                  "Candidate Url0 = https://single.url.test\n"
185                                  "Payload Size = 123456789\n"
186                                  "Payload Sha256 Hash = hash\n"
187                                  "Metadata Size = 58123\n"
188                                  "Metadata Signature = msign\n"
189                                  "Is Delta Payload = 0\n"
190                                  "Max Failure Count Per Url = 0\n"
191                                  "Disable Payload Backoff = 0\n";
192  EXPECT_EQ(expected_response_sign, stored_response_sign);
193  EXPECT_EQ("https://single.url.test", payload_state.GetCurrentUrl());
194  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
195  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
196  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
197}
198
199TEST(PayloadStateTest, SetResponseWorksWithMultipleUrls) {
200  OmahaResponse response;
201  response.payload_urls.push_back("http://multiple.url.test");
202  response.payload_urls.push_back("https://multiple.url.test");
203  response.size = 523456789;
204  response.hash = "rhash";
205  response.metadata_size = 558123;
206  response.metadata_signature = "metasign";
207  FakeSystemState fake_system_state;
208  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
209  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
210  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
211    .Times(AtLeast(1));
212  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
213    .Times(AtLeast(1));
214  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, 0))
215    .Times(AtLeast(1));
216  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
217    .Times(AtLeast(1));
218  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
219    .Times(AtLeast(1));
220  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
221    .Times(AtLeast(1));
222  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
223    .Times(AtLeast(1));
224  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttpPeer, 0))
225    .Times(AtLeast(1));
226  EXPECT_CALL(*prefs, SetInt64(kPrefsNumReboots, 0))
227      .Times(AtLeast(1));
228
229  PayloadState payload_state;
230  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
231  payload_state.SetResponse(response);
232  string stored_response_sign = payload_state.GetResponseSignature();
233  string expected_response_sign = "NumURLs = 2\n"
234                                  "Candidate Url0 = http://multiple.url.test\n"
235                                  "Candidate Url1 = https://multiple.url.test\n"
236                                  "Payload Size = 523456789\n"
237                                  "Payload Sha256 Hash = rhash\n"
238                                  "Metadata Size = 558123\n"
239                                  "Metadata Signature = metasign\n"
240                                  "Is Delta Payload = 0\n"
241                                  "Max Failure Count Per Url = 0\n"
242                                  "Disable Payload Backoff = 0\n";
243  EXPECT_EQ(expected_response_sign, stored_response_sign);
244  EXPECT_EQ("http://multiple.url.test", payload_state.GetCurrentUrl());
245  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
246  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
247  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
248}
249
250TEST(PayloadStateTest, CanAdvanceUrlIndexCorrectly) {
251  OmahaResponse response;
252  FakeSystemState fake_system_state;
253  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
254  PayloadState payload_state;
255
256  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
257  // Payload attempt should start with 0 and then advance to 1.
258  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
259    .Times(AtLeast(1));
260  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
261    .Times(AtLeast(1));
262  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
263    .Times(AtLeast(1));
264  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 1))
265    .Times(AtLeast(1));
266  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(AtLeast(2));
267
268  // Reboots will be set
269  EXPECT_CALL(*prefs, SetInt64(kPrefsNumReboots, _)).Times(AtLeast(1));
270
271  // Url index should go from 0 to 1 twice.
272  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(AtLeast(1));
273  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(AtLeast(1));
274
275  // Failure count should be called each times url index is set, so that's
276  // 4 times for this test.
277  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
278    .Times(AtLeast(4));
279
280  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
281
282  // This does a SetResponse which causes all the states to be set to 0 for
283  // the first time.
284  SetupPayloadStateWith2Urls("Hash1235", true, &payload_state, &response);
285  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
286
287  // Verify that on the first error, the URL index advances to 1.
288  ErrorCode error = ErrorCode::kDownloadMetadataSignatureMismatch;
289  payload_state.UpdateFailed(error);
290  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
291
292  // Verify that on the next error, the URL index wraps around to 0.
293  payload_state.UpdateFailed(error);
294  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
295
296  // Verify that on the next error, it again advances to 1.
297  payload_state.UpdateFailed(error);
298  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
299
300  // Verify that we switched URLs three times
301  EXPECT_EQ(3U, payload_state.GetUrlSwitchCount());
302}
303
304TEST(PayloadStateTest, NewResponseResetsPayloadState) {
305  OmahaResponse response;
306  FakeSystemState fake_system_state;
307  PayloadState payload_state;
308
309  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
310
311  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(_, _, _, _, _))
312    .Times(AnyNumber());
313  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
314    .Times(AnyNumber());
315
316  // Set the first response.
317  SetupPayloadStateWith2Urls("Hash5823", true, &payload_state, &response);
318  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
319
320  // Advance the URL index to 1 by faking an error.
321  ErrorCode error = ErrorCode::kDownloadMetadataSignatureMismatch;
322  payload_state.UpdateFailed(error);
323  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
324  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
325
326  // Now, slightly change the response and set it again.
327  SetupPayloadStateWith2Urls("Hash8225", true, &payload_state, &response);
328  EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
329
330  // Fake an error again.
331  payload_state.UpdateFailed(error);
332  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
333  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
334
335  // Return a third different response.
336  SetupPayloadStateWith2Urls("Hash9999", true, &payload_state, &response);
337  EXPECT_EQ(3, payload_state.GetNumResponsesSeen());
338
339  // Make sure the url index was reset to 0 because of the new response.
340  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
341  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
342  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
343  EXPECT_EQ(0U,
344            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
345  EXPECT_EQ(0U,
346            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
347  EXPECT_EQ(
348      0U, payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpsServer));
349  EXPECT_EQ(0U,
350            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
351}
352
353TEST(PayloadStateTest, AllCountersGetUpdatedProperlyOnErrorCodesAndEvents) {
354  OmahaResponse response;
355  PayloadState payload_state;
356  FakeSystemState fake_system_state;
357  int progress_bytes = 100;
358  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
359
360  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
361  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
362    .Times(AtLeast(2));
363  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
364    .Times(AtLeast(1));
365  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 2))
366    .Times(AtLeast(1));
367
368  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
369    .Times(AtLeast(2));
370  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 1))
371    .Times(AtLeast(1));
372  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 2))
373    .Times(AtLeast(1));
374
375  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(AtLeast(4));
376
377  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(AtLeast(4));
378  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(AtLeast(2));
379
380  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
381    .Times(AtLeast(7));
382  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 1))
383    .Times(AtLeast(2));
384  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 2))
385    .Times(AtLeast(1));
386
387  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateTimestampStart, _))
388    .Times(AtLeast(1));
389  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateDurationUptime, _))
390    .Times(AtLeast(1));
391
392  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
393    .Times(AtLeast(1));
394  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
395    .Times(AtLeast(1));
396  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttpPeer, 0))
397    .Times(AtLeast(1));
398  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, progress_bytes))
399    .Times(AtLeast(1));
400  EXPECT_CALL(*prefs, SetInt64(kTotalBytesDownloadedFromHttp, progress_bytes))
401    .Times(AtLeast(1));
402  EXPECT_CALL(*prefs, SetInt64(kPrefsNumReboots, 0))
403      .Times(AtLeast(1));
404
405  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
406
407  SetupPayloadStateWith2Urls("Hash5873", true, &payload_state, &response);
408  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
409
410  // This should advance the URL index.
411  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
412  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
413  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
414  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
415  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
416  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
417
418  // This should advance the failure count only.
419  payload_state.UpdateFailed(ErrorCode::kDownloadTransferError);
420  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
421  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
422  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
423  EXPECT_EQ(1U, payload_state.GetUrlFailureCount());
424  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
425
426  // This should advance the failure count only.
427  payload_state.UpdateFailed(ErrorCode::kDownloadTransferError);
428  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
429  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
430  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
431  EXPECT_EQ(2U, payload_state.GetUrlFailureCount());
432  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
433
434  // This should advance the URL index as we've reached the
435  // max failure count and reset the failure count for the new URL index.
436  // This should also wrap around the URL index and thus cause the payload
437  // attempt number to be incremented.
438  payload_state.UpdateFailed(ErrorCode::kDownloadTransferError);
439  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
440  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
441  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
442  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
443  EXPECT_EQ(2U, payload_state.GetUrlSwitchCount());
444  EXPECT_TRUE(payload_state.ShouldBackoffDownload());
445
446  // This should advance the URL index.
447  payload_state.UpdateFailed(ErrorCode::kPayloadHashMismatchError);
448  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
449  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
450  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
451  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
452  EXPECT_EQ(3U, payload_state.GetUrlSwitchCount());
453  EXPECT_TRUE(payload_state.ShouldBackoffDownload());
454
455  // This should advance the URL index and payload attempt number due to
456  // wrap-around of URL index.
457  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMissingError);
458  EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
459  EXPECT_EQ(2, payload_state.GetFullPayloadAttemptNumber());
460  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
461  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
462  EXPECT_EQ(4U, payload_state.GetUrlSwitchCount());
463  EXPECT_TRUE(payload_state.ShouldBackoffDownload());
464
465  // This HTTP error code should only increase the failure count.
466  payload_state.UpdateFailed(static_cast<ErrorCode>(
467      static_cast<int>(ErrorCode::kOmahaRequestHTTPResponseBase) + 404));
468  EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
469  EXPECT_EQ(2, payload_state.GetFullPayloadAttemptNumber());
470  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
471  EXPECT_EQ(1U, payload_state.GetUrlFailureCount());
472  EXPECT_EQ(4U, payload_state.GetUrlSwitchCount());
473  EXPECT_TRUE(payload_state.ShouldBackoffDownload());
474
475  // And that failure count should be reset when we download some bytes
476  // afterwards.
477  payload_state.DownloadProgress(progress_bytes);
478  EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
479  EXPECT_EQ(2, payload_state.GetFullPayloadAttemptNumber());
480  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
481  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
482  EXPECT_EQ(4U, payload_state.GetUrlSwitchCount());
483  EXPECT_TRUE(payload_state.ShouldBackoffDownload());
484
485  // Now, slightly change the response and set it again.
486  SetupPayloadStateWith2Urls("Hash8532", true, &payload_state, &response);
487  EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
488
489  // Make sure the url index was reset to 0 because of the new response.
490  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
491  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
492  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
493  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
494  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
495  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
496}
497
498TEST(PayloadStateTest, PayloadAttemptNumberIncreasesOnSuccessfulFullDownload) {
499  OmahaResponse response;
500  response.is_delta_payload = false;
501  PayloadState payload_state;
502  FakeSystemState fake_system_state;
503  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
504
505  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
506  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
507    .Times(AtLeast(1));
508  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
509    .Times(AtLeast(1));
510
511  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
512    .Times(AtLeast(1));
513  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 1))
514    .Times(AtLeast(1));
515
516  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _))
517    .Times(AtLeast(2));
518
519  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
520    .Times(AtLeast(1));
521  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
522    .Times(AtLeast(1));
523
524  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
525
526  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
527
528  // This should just advance the payload attempt number;
529  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
530  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
531  payload_state.DownloadComplete();
532  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
533  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
534  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
535  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
536  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
537}
538
539TEST(PayloadStateTest, PayloadAttemptNumberIncreasesOnSuccessfulDeltaDownload) {
540  OmahaResponse response;
541  response.is_delta_payload = true;
542  PayloadState payload_state;
543  FakeSystemState fake_system_state;
544  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
545
546  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AnyNumber());
547  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
548    .Times(AtLeast(1));
549  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
550    .Times(AtLeast(1));
551
552  // kPrefsFullPayloadAttemptNumber is not incremented for delta payloads.
553  EXPECT_CALL(*prefs, SetInt64(kPrefsFullPayloadAttemptNumber, 0))
554    .Times(AtLeast(1));
555
556  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _))
557    .Times(1);
558
559  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
560    .Times(AtLeast(1));
561  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
562    .Times(AtLeast(1));
563
564  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
565
566  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
567
568  // This should just advance the payload attempt number;
569  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
570  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
571  payload_state.DownloadComplete();
572  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
573  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
574  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
575  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
576  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
577}
578
579TEST(PayloadStateTest, SetResponseResetsInvalidUrlIndex) {
580  OmahaResponse response;
581  PayloadState payload_state;
582  FakeSystemState fake_system_state;
583
584  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
585  SetupPayloadStateWith2Urls("Hash4427", true, &payload_state, &response);
586
587  // Generate enough events to advance URL index, failure count and
588  // payload attempt number all to 1.
589  payload_state.DownloadComplete();
590  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
591  payload_state.UpdateFailed(ErrorCode::kDownloadTransferError);
592  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
593  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
594  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
595  EXPECT_EQ(1U, payload_state.GetUrlFailureCount());
596  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
597
598  // Now, simulate a corrupted url index on persisted store which gets
599  // loaded when update_engine restarts. Using a different prefs object
600  // so as to not bother accounting for the uninteresting calls above.
601  FakeSystemState fake_system_state2;
602  NiceMock<MockPrefs>* prefs2 = fake_system_state2.mock_prefs();
603  EXPECT_CALL(*prefs2, Exists(_)).WillRepeatedly(Return(true));
604  EXPECT_CALL(*prefs2, GetInt64(_, _)).Times(AtLeast(1));
605  EXPECT_CALL(*prefs2, GetInt64(kPrefsPayloadAttemptNumber, _))
606    .Times(AtLeast(1));
607  EXPECT_CALL(*prefs2, GetInt64(kPrefsFullPayloadAttemptNumber, _))
608    .Times(AtLeast(1));
609  EXPECT_CALL(*prefs2, GetInt64(kPrefsCurrentUrlIndex, _))
610      .WillRepeatedly(DoAll(SetArgumentPointee<1>(2), Return(true)));
611  EXPECT_CALL(*prefs2, GetInt64(kPrefsCurrentUrlFailureCount, _))
612    .Times(AtLeast(1));
613  EXPECT_CALL(*prefs2, GetInt64(kPrefsUrlSwitchCount, _))
614    .Times(AtLeast(1));
615
616  // Note: This will be a different payload object, but the response should
617  // have the same hash as before so as to not trivially reset because the
618  // response was different. We want to specifically test that even if the
619  // response is same, we should reset the state if we find it corrupted.
620  EXPECT_TRUE(payload_state.Initialize(&fake_system_state2));
621  SetupPayloadStateWith2Urls("Hash4427", true, &payload_state, &response);
622
623  // Make sure all counters get reset to 0 because of the corrupted URL index
624  // we supplied above.
625  EXPECT_EQ(0, payload_state.GetPayloadAttemptNumber());
626  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
627  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
628  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
629  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
630}
631
632TEST(PayloadStateTest, NoBackoffInteractiveChecks) {
633  OmahaResponse response;
634  response.is_delta_payload = false;
635  PayloadState payload_state;
636  FakeSystemState fake_system_state;
637  OmahaRequestParams params(&fake_system_state);
638  params.Init("", "", true);  // is_interactive = True.
639  fake_system_state.set_request_params(&params);
640
641  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
642  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
643
644  // Simulate two failures (enough to cause payload backoff) and check
645  // again that we're ready to re-download without any backoff as this is
646  // an interactive check.
647  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
648  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
649  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
650  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
651  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
652  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
653}
654
655TEST(PayloadStateTest, NoBackoffForP2PUpdates) {
656  OmahaResponse response;
657  response.is_delta_payload = false;
658  PayloadState payload_state;
659  FakeSystemState fake_system_state;
660  OmahaRequestParams params(&fake_system_state);
661  params.Init("", "", false);  // is_interactive = False.
662  fake_system_state.set_request_params(&params);
663
664  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
665  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
666
667  // Simulate two failures (enough to cause payload backoff) and check
668  // again that we're ready to re-download without any backoff as this is
669  // an interactive check.
670  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
671  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
672  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
673  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
674  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
675  // Set p2p url.
676  payload_state.SetUsingP2PForDownloading(true);
677  payload_state.SetP2PUrl("http://mypeer:52909/path/to/file");
678  // Should not backoff for p2p updates.
679  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
680
681  payload_state.SetP2PUrl("");
682  // No actual p2p update if no url is provided.
683  EXPECT_TRUE(payload_state.ShouldBackoffDownload());
684}
685
686TEST(PayloadStateTest, NoBackoffForDeltaPayloads) {
687  OmahaResponse response;
688  response.is_delta_payload = true;
689  PayloadState payload_state;
690  FakeSystemState fake_system_state;
691
692  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
693  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
694
695  // Simulate a successful download and see that we're ready to download
696  // again without any backoff as this is a delta payload.
697  payload_state.DownloadComplete();
698  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
699  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
700  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
701
702  // Simulate two failures (enough to cause payload backoff) and check
703  // again that we're ready to re-download without any backoff as this is
704  // a delta payload.
705  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
706  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
707  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
708  EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
709  EXPECT_EQ(0, payload_state.GetFullPayloadAttemptNumber());
710  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
711}
712
713static void CheckPayloadBackoffState(PayloadState* payload_state,
714                                     int expected_attempt_number,
715                                     TimeDelta expected_days) {
716  payload_state->DownloadComplete();
717  EXPECT_EQ(expected_attempt_number,
718      payload_state->GetFullPayloadAttemptNumber());
719  EXPECT_TRUE(payload_state->ShouldBackoffDownload());
720  Time backoff_expiry_time = payload_state->GetBackoffExpiryTime();
721  // Add 1 hour extra to the 6 hour fuzz check to tolerate edge cases.
722  TimeDelta max_fuzz_delta = TimeDelta::FromHours(7);
723  Time expected_min_time = Time::Now() + expected_days - max_fuzz_delta;
724  Time expected_max_time = Time::Now() + expected_days + max_fuzz_delta;
725  EXPECT_LT(expected_min_time.ToInternalValue(),
726            backoff_expiry_time.ToInternalValue());
727  EXPECT_GT(expected_max_time.ToInternalValue(),
728            backoff_expiry_time.ToInternalValue());
729}
730
731TEST(PayloadStateTest, BackoffPeriodsAreInCorrectRange) {
732  OmahaResponse response;
733  response.is_delta_payload = false;
734  PayloadState payload_state;
735  FakeSystemState fake_system_state;
736
737  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
738  SetupPayloadStateWith2Urls("Hash8939", true, &payload_state, &response);
739
740  CheckPayloadBackoffState(&payload_state, 1,  TimeDelta::FromDays(1));
741  CheckPayloadBackoffState(&payload_state, 2,  TimeDelta::FromDays(2));
742  CheckPayloadBackoffState(&payload_state, 3,  TimeDelta::FromDays(4));
743  CheckPayloadBackoffState(&payload_state, 4,  TimeDelta::FromDays(8));
744  CheckPayloadBackoffState(&payload_state, 5,  TimeDelta::FromDays(16));
745  CheckPayloadBackoffState(&payload_state, 6,  TimeDelta::FromDays(16));
746  CheckPayloadBackoffState(&payload_state, 7,  TimeDelta::FromDays(16));
747  CheckPayloadBackoffState(&payload_state, 8,  TimeDelta::FromDays(16));
748  CheckPayloadBackoffState(&payload_state, 9,  TimeDelta::FromDays(16));
749  CheckPayloadBackoffState(&payload_state, 10,  TimeDelta::FromDays(16));
750}
751
752TEST(PayloadStateTest, BackoffLogicCanBeDisabled) {
753  OmahaResponse response;
754  response.disable_payload_backoff = true;
755  PayloadState payload_state;
756  FakeSystemState fake_system_state;
757
758  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
759  SetupPayloadStateWith2Urls("Hash8939", true, &payload_state, &response);
760
761  // Simulate a successful download and see that we are ready to download
762  // again without any backoff.
763  payload_state.DownloadComplete();
764  EXPECT_EQ(1, payload_state.GetPayloadAttemptNumber());
765  EXPECT_EQ(1, payload_state.GetFullPayloadAttemptNumber());
766  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
767
768  // Test again, this time by simulating two errors that would cause
769  // the payload attempt number to increment due to wrap around. And
770  // check that we are still ready to re-download without any backoff.
771  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
772  payload_state.UpdateFailed(ErrorCode::kDownloadMetadataSignatureMismatch);
773  EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
774  EXPECT_EQ(2, payload_state.GetFullPayloadAttemptNumber());
775  EXPECT_FALSE(payload_state.ShouldBackoffDownload());
776}
777
778TEST(PayloadStateTest, BytesDownloadedMetricsGetAddedToCorrectSources) {
779  OmahaResponse response;
780  response.disable_payload_backoff = true;
781  PayloadState payload_state;
782  FakeSystemState fake_system_state;
783  uint64_t https_total = 0;
784  uint64_t http_total = 0;
785
786  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
787  SetupPayloadStateWith2Urls("Hash3286", true, &payload_state, &response);
788  EXPECT_EQ(1, payload_state.GetNumResponsesSeen());
789
790  // Simulate a previous attempt with in order to set an initial non-zero value
791  // for the total bytes downloaded for HTTP.
792  uint64_t prev_chunk = 323456789;
793  http_total += prev_chunk;
794  payload_state.DownloadProgress(prev_chunk);
795
796  // Ensure that the initial values for HTTP reflect this attempt.
797  EXPECT_EQ(prev_chunk,
798            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
799  EXPECT_EQ(http_total,
800            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
801
802  // Change the response hash so as to simulate a new response which will
803  // reset the current bytes downloaded, but not the total bytes downloaded.
804  SetupPayloadStateWith2Urls("Hash9904", true, &payload_state, &response);
805  EXPECT_EQ(2, payload_state.GetNumResponsesSeen());
806
807  // First, simulate successful download of a few bytes over HTTP.
808  uint64_t first_chunk = 5000000;
809  http_total += first_chunk;
810  payload_state.DownloadProgress(first_chunk);
811  // Test that first all progress is made on HTTP and none on HTTPS.
812  EXPECT_EQ(first_chunk,
813            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
814  EXPECT_EQ(http_total,
815            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
816  EXPECT_EQ(0U, payload_state.GetCurrentBytesDownloaded(
817                 kDownloadSourceHttpsServer));
818  EXPECT_EQ(https_total,
819            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
820
821  // Simulate an error that'll cause the url index to point to https.
822  ErrorCode error = ErrorCode::kDownloadMetadataSignatureMismatch;
823  payload_state.UpdateFailed(error);
824
825  // Test that no new progress is made on HTTP and new progress is on HTTPS.
826  uint64_t second_chunk = 23456789;
827  https_total += second_chunk;
828  payload_state.DownloadProgress(second_chunk);
829  EXPECT_EQ(first_chunk,
830            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
831  EXPECT_EQ(http_total,
832            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
833  EXPECT_EQ(second_chunk, payload_state.GetCurrentBytesDownloaded(
834              kDownloadSourceHttpsServer));
835  EXPECT_EQ(https_total,
836            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
837
838  // Simulate error to go back to http.
839  payload_state.UpdateFailed(error);
840  uint64_t third_chunk = 32345678;
841  uint64_t http_chunk = first_chunk + third_chunk;
842  http_total += third_chunk;
843  payload_state.DownloadProgress(third_chunk);
844
845  // Test that third chunk is again back on HTTP. HTTPS remains on second chunk.
846  EXPECT_EQ(http_chunk,
847            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
848  EXPECT_EQ(http_total,
849            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
850  EXPECT_EQ(second_chunk, payload_state.GetCurrentBytesDownloaded(
851                 kDownloadSourceHttpsServer));
852  EXPECT_EQ(https_total,
853            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
854
855  // Simulate error (will cause URL switch), set p2p is to be used and
856  // then do 42MB worth of progress
857  payload_state.UpdateFailed(error);
858  payload_state.SetUsingP2PForDownloading(true);
859  uint64_t p2p_total = 42 * 1000 * 1000;
860  payload_state.DownloadProgress(p2p_total);
861
862  EXPECT_EQ(p2p_total,
863            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpPeer));
864
865  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(_, _, _, _, _))
866    .Times(AnyNumber());
867  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
868    .Times(AnyNumber());
869  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
870      metrics::kMetricSuccessfulUpdateUrlSwitchCount,
871      3, _, _, _));
872  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
873      metrics::kMetricSuccessfulUpdateTotalDurationMinutes,
874      _, _, _, _));
875  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
876      metrics::kMetricSuccessfulUpdateDownloadOverheadPercentage,
877      314, _, _, _));
878  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
879      metrics::kMetricAttemptPayloadType, kPayloadTypeFull, kNumPayloadTypes));
880  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
881      metrics::kMetricSuccessfulUpdatePayloadType, kPayloadTypeFull,
882      kNumPayloadTypes));
883  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
884      metrics::kMetricSuccessfulUpdateAttemptCount, 1, _, _, _));
885
886  payload_state.UpdateSucceeded();
887
888  // Make sure the metrics are reset after a successful update.
889  EXPECT_EQ(0U,
890            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
891  EXPECT_EQ(0U,
892            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
893  EXPECT_EQ(0U, payload_state.GetCurrentBytesDownloaded(
894                 kDownloadSourceHttpsServer));
895  EXPECT_EQ(0U,
896            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
897  EXPECT_EQ(0, payload_state.GetNumResponsesSeen());
898}
899
900TEST(PayloadStateTest, DownloadSourcesUsedIsCorrect) {
901  OmahaResponse response;
902  PayloadState payload_state;
903  FakeSystemState fake_system_state;
904
905  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
906  SetupPayloadStateWith2Urls("Hash3286", true, &payload_state, &response);
907
908  // Simulate progress in order to mark HTTP as one of the sources used.
909  uint64_t num_bytes = 42 * 1000 * 1000;
910  payload_state.DownloadProgress(num_bytes);
911
912  // Check that this was done via HTTP.
913  EXPECT_EQ(num_bytes,
914            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
915  EXPECT_EQ(num_bytes,
916            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
917
918  // Check that only HTTP is reported as a download source.
919  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(_, _, _, _, _))
920    .Times(AnyNumber());
921  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
922      metrics::kMetricSuccessfulUpdateDownloadSourcesUsed,
923      (1 << kDownloadSourceHttpServer),
924      _, _, _));
925
926  payload_state.UpdateSucceeded();
927}
928
929TEST(PayloadStateTest, RestartingUpdateResetsMetrics) {
930  OmahaResponse response;
931  FakeSystemState fake_system_state;
932  PayloadState payload_state;
933
934  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
935
936  // Set the first response.
937  SetupPayloadStateWith2Urls("Hash5823", true, &payload_state, &response);
938
939  uint64_t num_bytes = 10000;
940  payload_state.DownloadProgress(num_bytes);
941  EXPECT_EQ(num_bytes,
942            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
943  EXPECT_EQ(num_bytes,
944            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
945  EXPECT_EQ(0U, payload_state.GetCurrentBytesDownloaded(
946                 kDownloadSourceHttpsServer));
947  EXPECT_EQ(0U,
948            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
949
950  payload_state.UpdateRestarted();
951  // Make sure the current bytes downloaded is reset, but not the total bytes.
952  EXPECT_EQ(0U,
953            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
954  EXPECT_EQ(num_bytes,
955            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
956}
957
958TEST(PayloadStateTest, NumRebootsIncrementsCorrectly) {
959  FakeSystemState fake_system_state;
960  PayloadState payload_state;
961
962  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
963  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(AtLeast(0));
964  EXPECT_CALL(*prefs, SetInt64(kPrefsNumReboots, 1)).Times(AtLeast(1));
965
966  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
967
968  payload_state.UpdateRestarted();
969  EXPECT_EQ(0U, payload_state.GetNumReboots());
970
971  fake_system_state.set_system_rebooted(true);
972  payload_state.UpdateResumed();
973  // Num reboots should be incremented because system rebooted detected.
974  EXPECT_EQ(1U, payload_state.GetNumReboots());
975
976  fake_system_state.set_system_rebooted(false);
977  payload_state.UpdateResumed();
978  // Num reboots should now be 1 as reboot was not detected.
979  EXPECT_EQ(1U, payload_state.GetNumReboots());
980
981  // Restart the update again to verify we set the num of reboots back to 0.
982  payload_state.UpdateRestarted();
983  EXPECT_EQ(0U, payload_state.GetNumReboots());
984}
985
986TEST(PayloadStateTest, RollbackVersion) {
987  FakeSystemState fake_system_state;
988  PayloadState payload_state;
989
990  NiceMock<MockPrefs>* mock_powerwash_safe_prefs =
991      fake_system_state.mock_powerwash_safe_prefs();
992  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
993
994  // Verify pre-conditions are good.
995  EXPECT_TRUE(payload_state.GetRollbackVersion().empty());
996
997  // Mock out the os version and make sure it's blacklisted correctly.
998  string rollback_version = "2345.0.0";
999  OmahaRequestParams params(&fake_system_state);
1000  params.Init(rollback_version, "", false);
1001  fake_system_state.set_request_params(&params);
1002
1003  EXPECT_CALL(*mock_powerwash_safe_prefs, SetString(kPrefsRollbackVersion,
1004                                                    rollback_version));
1005  payload_state.Rollback();
1006
1007  EXPECT_EQ(rollback_version, payload_state.GetRollbackVersion());
1008
1009  // Change it up a little and verify we load it correctly.
1010  rollback_version = "2345.0.1";
1011  // Let's verify we can reload it correctly.
1012  EXPECT_CALL(*mock_powerwash_safe_prefs, GetString(
1013      kPrefsRollbackVersion, _)).WillOnce(DoAll(
1014          SetArgumentPointee<1>(rollback_version), Return(true)));
1015  EXPECT_CALL(*mock_powerwash_safe_prefs, SetString(kPrefsRollbackVersion,
1016                                                    rollback_version));
1017  payload_state.LoadRollbackVersion();
1018  EXPECT_EQ(rollback_version, payload_state.GetRollbackVersion());
1019
1020  // Check that we report only UpdateEngine.Rollback.* metrics in
1021  // UpdateSucceeded().
1022  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(_, _, _, _, _))
1023    .Times(0);
1024  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
1025    .Times(0);
1026  EXPECT_CALL(*fake_system_state.mock_metrics_lib(),
1027              SendEnumToUMA(
1028                  metrics::kMetricRollbackResult,
1029                  static_cast<int>(metrics::RollbackResult::kSuccess),
1030                  static_cast<int>(metrics::RollbackResult::kNumConstants)));
1031  payload_state.UpdateSucceeded();
1032}
1033
1034TEST(PayloadStateTest, DurationsAreCorrect) {
1035  OmahaResponse response;
1036  PayloadState payload_state;
1037  FakeSystemState fake_system_state;
1038  FakeClock fake_clock;
1039  FakePrefs fake_prefs;
1040
1041  // Set the clock to a well-known time - 1 second on the wall-clock
1042  // and 2 seconds on the monotonic clock
1043  fake_clock.SetWallclockTime(Time::FromInternalValue(1000000));
1044  fake_clock.SetMonotonicTime(Time::FromInternalValue(2000000));
1045
1046  fake_system_state.set_clock(&fake_clock);
1047  fake_system_state.set_prefs(&fake_prefs);
1048  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1049
1050  // Check that durations are correct for a successful update where
1051  // time has advanced 7 seconds on the wall clock and 4 seconds on
1052  // the monotonic clock.
1053  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1054  fake_clock.SetWallclockTime(Time::FromInternalValue(8000000));
1055  fake_clock.SetMonotonicTime(Time::FromInternalValue(6000000));
1056  payload_state.UpdateSucceeded();
1057  EXPECT_EQ(payload_state.GetUpdateDuration().InMicroseconds(), 7000000);
1058  EXPECT_EQ(payload_state.GetUpdateDurationUptime().InMicroseconds(), 4000000);
1059
1060  // Check that durations are reset when a new response comes in.
1061  SetupPayloadStateWith2Urls("Hash8594", true, &payload_state, &response);
1062  EXPECT_EQ(payload_state.GetUpdateDuration().InMicroseconds(), 0);
1063  EXPECT_EQ(payload_state.GetUpdateDurationUptime().InMicroseconds(), 0);
1064
1065  // Advance time a bit (10 secs), simulate download progress and
1066  // check that durations are updated.
1067  fake_clock.SetWallclockTime(Time::FromInternalValue(18000000));
1068  fake_clock.SetMonotonicTime(Time::FromInternalValue(16000000));
1069  payload_state.DownloadProgress(10);
1070  EXPECT_EQ(payload_state.GetUpdateDuration().InMicroseconds(), 10000000);
1071  EXPECT_EQ(payload_state.GetUpdateDurationUptime().InMicroseconds(), 10000000);
1072
1073  // Now simulate a reboot by resetting monotonic time (to 5000) and
1074  // creating a new PayloadState object and check that we load the
1075  // durations correctly (e.g. they are the same as before).
1076  fake_clock.SetMonotonicTime(Time::FromInternalValue(5000));
1077  PayloadState payload_state2;
1078  EXPECT_TRUE(payload_state2.Initialize(&fake_system_state));
1079  EXPECT_EQ(payload_state2.GetUpdateDuration().InMicroseconds(), 10000000);
1080  EXPECT_EQ(payload_state2.GetUpdateDurationUptime().InMicroseconds(),
1081            10000000);
1082
1083  // Advance wall-clock by 7 seconds and monotonic clock by 6 seconds
1084  // and check that the durations are increased accordingly.
1085  fake_clock.SetWallclockTime(Time::FromInternalValue(25000000));
1086  fake_clock.SetMonotonicTime(Time::FromInternalValue(6005000));
1087  payload_state2.UpdateSucceeded();
1088  EXPECT_EQ(payload_state2.GetUpdateDuration().InMicroseconds(), 17000000);
1089  EXPECT_EQ(payload_state2.GetUpdateDurationUptime().InMicroseconds(),
1090            16000000);
1091}
1092
1093TEST(PayloadStateTest, RebootAfterSuccessfulUpdateTest) {
1094  OmahaResponse response;
1095  PayloadState payload_state;
1096  FakeSystemState fake_system_state;
1097  FakeClock fake_clock;
1098  FakePrefs fake_prefs;
1099
1100  // Set the clock to a well-known time (t = 30 seconds).
1101  fake_clock.SetWallclockTime(Time::FromInternalValue(
1102      30 * Time::kMicrosecondsPerSecond));
1103
1104  fake_system_state.set_clock(&fake_clock);
1105  fake_system_state.set_prefs(&fake_prefs);
1106  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1107
1108  // Make the update succeed.
1109  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1110  payload_state.UpdateSucceeded();
1111
1112  // Check that the marker was written.
1113  EXPECT_TRUE(fake_prefs.Exists(kPrefsSystemUpdatedMarker));
1114
1115  // Now simulate a reboot and set the wallclock time to a later point
1116  // (t = 500 seconds). We do this by using a new PayloadState object
1117  // and checking that it emits the right UMA metric with the right
1118  // value.
1119  fake_clock.SetWallclockTime(Time::FromInternalValue(
1120      500 * Time::kMicrosecondsPerSecond));
1121  PayloadState payload_state2;
1122  EXPECT_TRUE(payload_state2.Initialize(&fake_system_state));
1123
1124  // Expect 500 - 30 seconds = 470 seconds ~= 7 min 50 sec
1125  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1126      metrics::kMetricTimeToRebootMinutes,
1127      7, _, _, _));
1128  fake_system_state.set_system_rebooted(true);
1129
1130  payload_state2.UpdateEngineStarted();
1131
1132  // Check that the marker was nuked.
1133  EXPECT_FALSE(fake_prefs.Exists(kPrefsSystemUpdatedMarker));
1134}
1135
1136TEST(PayloadStateTest, RestartAfterCrash) {
1137  PayloadState payload_state;
1138  FakeSystemState fake_system_state;
1139  NiceMock<MockPrefs>* prefs = fake_system_state.mock_prefs();
1140
1141  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1142
1143  // Only the |kPrefsAttemptInProgress| state variable should be read.
1144  EXPECT_CALL(*prefs, Exists(_)).Times(0);
1145  EXPECT_CALL(*prefs, SetString(_, _)).Times(0);
1146  EXPECT_CALL(*prefs, SetInt64(_, _)).Times(0);
1147  EXPECT_CALL(*prefs, SetBoolean(_, _)).Times(0);
1148  EXPECT_CALL(*prefs, GetString(_, _)).Times(0);
1149  EXPECT_CALL(*prefs, GetInt64(_, _)).Times(0);
1150  EXPECT_CALL(*prefs, GetBoolean(_, _)).Times(0);
1151  EXPECT_CALL(*prefs, GetBoolean(kPrefsAttemptInProgress, _));
1152
1153  // No metrics are reported after a crash.
1154  EXPECT_CALL(*fake_system_state.mock_metrics_lib(),
1155              SendToUMA(_, _, _, _, _)).Times(0);
1156
1157  // Simulate an update_engine restart without a reboot.
1158  fake_system_state.set_system_rebooted(false);
1159
1160  payload_state.UpdateEngineStarted();
1161}
1162
1163TEST(PayloadStateTest, AbnormalTerminationAttemptMetricsNoReporting) {
1164  PayloadState payload_state;
1165  FakeSystemState fake_system_state;
1166
1167  // If there's no marker at startup, ensure we don't report a metric.
1168  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1169  EXPECT_CALL(*fake_system_state.mock_metrics_lib(),
1170      SendEnumToUMA(
1171          metrics::kMetricAttemptResult,
1172          static_cast<int>(metrics::AttemptResult::kAbnormalTermination),
1173          _)).Times(0);
1174  payload_state.UpdateEngineStarted();
1175}
1176
1177TEST(PayloadStateTest, AbnormalTerminationAttemptMetricsReported) {
1178  PayloadState payload_state;
1179  FakeSystemState fake_system_state;
1180  FakePrefs fake_prefs;
1181
1182  // If we have a marker at startup, ensure it's reported and the
1183  // marker is then cleared.
1184  fake_system_state.set_prefs(&fake_prefs);
1185  fake_prefs.SetBoolean(kPrefsAttemptInProgress, true);
1186
1187  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1188
1189  EXPECT_CALL(*fake_system_state.mock_metrics_lib(),
1190      SendEnumToUMA(
1191          metrics::kMetricAttemptResult,
1192          static_cast<int>(metrics::AttemptResult::kAbnormalTermination),
1193          _)).Times(1);
1194  payload_state.UpdateEngineStarted();
1195
1196  EXPECT_FALSE(fake_prefs.Exists(kPrefsAttemptInProgress));
1197}
1198
1199TEST(PayloadStateTest, AbnormalTerminationAttemptMetricsClearedOnSucceess) {
1200  PayloadState payload_state;
1201  FakeSystemState fake_system_state;
1202  FakePrefs fake_prefs;
1203
1204  // Make sure the marker is written and cleared during an attempt and
1205  // also that we DO NOT emit the metric (since the attempt didn't end
1206  // abnormally).
1207  fake_system_state.set_prefs(&fake_prefs);
1208  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1209
1210  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(_, _, _, _, _))
1211    .Times(AnyNumber());
1212  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
1213    .Times(AnyNumber());
1214  EXPECT_CALL(*fake_system_state.mock_metrics_lib(),
1215      SendEnumToUMA(
1216          metrics::kMetricAttemptResult,
1217          static_cast<int>(metrics::AttemptResult::kAbnormalTermination),
1218          _)).Times(0);
1219
1220  // Attempt not in progress, should be clear.
1221  EXPECT_FALSE(fake_prefs.Exists(kPrefsAttemptInProgress));
1222
1223  payload_state.UpdateRestarted();
1224
1225  // Attempt not in progress, should be set.
1226  EXPECT_TRUE(fake_prefs.Exists(kPrefsAttemptInProgress));
1227
1228  payload_state.UpdateSucceeded();
1229
1230  // Attempt not in progress, should be clear.
1231  EXPECT_FALSE(fake_prefs.Exists(kPrefsAttemptInProgress));
1232}
1233
1234TEST(PayloadStateTest, CandidateUrlsComputedCorrectly) {
1235  OmahaResponse response;
1236  FakeSystemState fake_system_state;
1237  PayloadState payload_state;
1238
1239  policy::MockDevicePolicy disable_http_policy;
1240  fake_system_state.set_device_policy(&disable_http_policy);
1241  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1242
1243  // Test with no device policy. Should default to allowing http.
1244  EXPECT_CALL(disable_http_policy, GetHttpDownloadsEnabled(_))
1245      .WillRepeatedly(Return(false));
1246
1247  // Set the first response.
1248  SetupPayloadStateWith2Urls("Hash8433", true, &payload_state, &response);
1249
1250  // Check that we use the HTTP URL since there is no value set for allowing
1251  // http.
1252  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
1253
1254  // Test with device policy not allowing http updates.
1255  EXPECT_CALL(disable_http_policy, GetHttpDownloadsEnabled(_))
1256      .WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(true)));
1257
1258  // Reset state and set again.
1259  SetupPayloadStateWith2Urls("Hash8433", false, &payload_state, &response);
1260
1261  // Check that we skip the HTTP URL and use only the HTTPS url.
1262  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
1263
1264  // Advance the URL index to 1 by faking an error.
1265  ErrorCode error = ErrorCode::kDownloadMetadataSignatureMismatch;
1266  payload_state.UpdateFailed(error);
1267
1268  // Check that we still skip the HTTP URL and use only the HTTPS url.
1269  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
1270  EXPECT_EQ(0U, payload_state.GetUrlSwitchCount());
1271
1272  // Now, slightly change the response and set it again.
1273  SetupPayloadStateWith2Urls("Hash2399", false, &payload_state, &response);
1274
1275  // Check that we still skip the HTTP URL and use only the HTTPS url.
1276  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
1277
1278  // Now, pretend that the HTTP policy is turned on. We want to make sure
1279  // the new policy is honored.
1280  policy::MockDevicePolicy enable_http_policy;
1281  fake_system_state.set_device_policy(&enable_http_policy);
1282  EXPECT_CALL(enable_http_policy, GetHttpDownloadsEnabled(_))
1283      .WillRepeatedly(DoAll(SetArgumentPointee<0>(true), Return(true)));
1284
1285  // Now, set the same response using the same hash
1286  // so that we can test that the state is reset not because of the
1287  // hash but because of the policy change which results in candidate url
1288  // list change.
1289  SetupPayloadStateWith2Urls("Hash2399", true, &payload_state, &response);
1290
1291  // Check that we use the HTTP URL now and the failure count is reset.
1292  EXPECT_EQ("http://test", payload_state.GetCurrentUrl());
1293  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
1294
1295  // Fake a failure and see if we're moving over to the HTTPS url and update
1296  // the URL switch count properly.
1297  payload_state.UpdateFailed(error);
1298  EXPECT_EQ("https://test", payload_state.GetCurrentUrl());
1299  EXPECT_EQ(1U, payload_state.GetUrlSwitchCount());
1300  EXPECT_EQ(0U, payload_state.GetUrlFailureCount());
1301}
1302
1303TEST(PayloadStateTest, PayloadTypeMetricWhenTypeIsDelta) {
1304  OmahaResponse response;
1305  response.is_delta_payload = true;
1306  PayloadState payload_state;
1307  FakeSystemState fake_system_state;
1308
1309  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1310  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
1311
1312  // Simulate a successful download and update.
1313  payload_state.DownloadComplete();
1314
1315  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
1316    .Times(AnyNumber());
1317  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1318      metrics::kMetricAttemptPayloadType, kPayloadTypeDelta, kNumPayloadTypes));
1319  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1320      metrics::kMetricSuccessfulUpdatePayloadType, kPayloadTypeDelta,
1321      kNumPayloadTypes));
1322  payload_state.UpdateSucceeded();
1323
1324  // Mock the request to a request where the delta was disabled but Omaha sends
1325  // a delta anyway and test again.
1326  OmahaRequestParams params(&fake_system_state);
1327  params.set_delta_okay(false);
1328  fake_system_state.set_request_params(&params);
1329
1330  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1331  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
1332
1333  payload_state.DownloadComplete();
1334
1335  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1336      metrics::kMetricAttemptPayloadType, kPayloadTypeDelta,
1337      kNumPayloadTypes));
1338  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1339      metrics::kMetricSuccessfulUpdatePayloadType, kPayloadTypeDelta,
1340      kNumPayloadTypes));
1341  payload_state.UpdateSucceeded();
1342}
1343
1344TEST(PayloadStateTest, PayloadTypeMetricWhenTypeIsForcedFull) {
1345  OmahaResponse response;
1346  response.is_delta_payload = false;
1347  PayloadState payload_state;
1348  FakeSystemState fake_system_state;
1349
1350  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1351  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
1352
1353  // Mock the request to a request where the delta was disabled.
1354  OmahaRequestParams params(&fake_system_state);
1355  params.set_delta_okay(false);
1356  fake_system_state.set_request_params(&params);
1357
1358  // Simulate a successful download and update.
1359  payload_state.DownloadComplete();
1360
1361  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
1362    .Times(AnyNumber());
1363  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1364      metrics::kMetricAttemptPayloadType, kPayloadTypeForcedFull,
1365      kNumPayloadTypes));
1366  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1367      metrics::kMetricSuccessfulUpdatePayloadType, kPayloadTypeForcedFull,
1368      kNumPayloadTypes));
1369  payload_state.UpdateSucceeded();
1370}
1371
1372TEST(PayloadStateTest, PayloadTypeMetricWhenTypeIsFull) {
1373  OmahaResponse response;
1374  response.is_delta_payload = false;
1375  PayloadState payload_state;
1376  FakeSystemState fake_system_state;
1377
1378  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1379  SetupPayloadStateWith2Urls("Hash6437", true, &payload_state, &response);
1380
1381  // Mock the request to a request where the delta is enabled, although the
1382  // result is full.
1383  OmahaRequestParams params(&fake_system_state);
1384  params.set_delta_okay(true);
1385  fake_system_state.set_request_params(&params);
1386
1387  // Simulate a successful download and update.
1388  payload_state.DownloadComplete();
1389
1390  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(_, _, _))
1391    .Times(AnyNumber());
1392  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1393      metrics::kMetricAttemptPayloadType, kPayloadTypeFull,
1394      kNumPayloadTypes));
1395  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendEnumToUMA(
1396      metrics::kMetricSuccessfulUpdatePayloadType, kPayloadTypeFull,
1397      kNumPayloadTypes));
1398  payload_state.UpdateSucceeded();
1399}
1400
1401TEST(PayloadStateTest, RebootAfterUpdateFailedMetric) {
1402  FakeSystemState fake_system_state;
1403  OmahaResponse response;
1404  PayloadState payload_state;
1405  FakePrefs fake_prefs;
1406  fake_system_state.set_prefs(&fake_prefs);
1407
1408  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1409  SetupPayloadStateWith2Urls("Hash3141", true, &payload_state, &response);
1410
1411  // Simulate a successful download and update.
1412  payload_state.DownloadComplete();
1413  payload_state.UpdateSucceeded();
1414  payload_state.ExpectRebootInNewVersion("Version:12345678");
1415
1416  // Reboot into the same environment to get an UMA metric with a value of 1.
1417  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1418      metrics::kMetricFailedUpdateCount, 1, _, _, _));
1419  payload_state.ReportFailedBootIfNeeded();
1420  Mock::VerifyAndClearExpectations(fake_system_state.mock_metrics_lib());
1421
1422  // Simulate a second update and reboot into the same environment, this should
1423  // send a value of 2.
1424  payload_state.ExpectRebootInNewVersion("Version:12345678");
1425
1426  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1427      metrics::kMetricFailedUpdateCount, 2, _, _, _));
1428  payload_state.ReportFailedBootIfNeeded();
1429  Mock::VerifyAndClearExpectations(fake_system_state.mock_metrics_lib());
1430
1431  // Simulate a third failed reboot to new version, but this time for a
1432  // different payload. This should send a value of 1 this time.
1433  payload_state.ExpectRebootInNewVersion("Version:3141592");
1434  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1435      metrics::kMetricFailedUpdateCount, 1, _, _, _));
1436  payload_state.ReportFailedBootIfNeeded();
1437  Mock::VerifyAndClearExpectations(fake_system_state.mock_metrics_lib());
1438}
1439
1440TEST(PayloadStateTest, RebootAfterUpdateSucceed) {
1441  FakeSystemState fake_system_state;
1442  OmahaResponse response;
1443  PayloadState payload_state;
1444  FakePrefs fake_prefs;
1445  fake_system_state.set_prefs(&fake_prefs);
1446
1447  FakeBootControl* fake_boot_control = fake_system_state.fake_boot_control();
1448  fake_boot_control->SetCurrentSlot(0);
1449
1450  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1451  SetupPayloadStateWith2Urls("Hash3141", true, &payload_state, &response);
1452
1453  // Simulate a successful download and update.
1454  payload_state.DownloadComplete();
1455  payload_state.UpdateSucceeded();
1456  payload_state.ExpectRebootInNewVersion("Version:12345678");
1457
1458  // Change the BootDevice to a different one, no metric should be sent.
1459  fake_boot_control->SetCurrentSlot(1);
1460
1461  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1462      metrics::kMetricFailedUpdateCount, _, _, _, _))
1463      .Times(0);
1464  payload_state.ReportFailedBootIfNeeded();
1465
1466  // A second reboot in either partition should not send a metric.
1467  payload_state.ReportFailedBootIfNeeded();
1468  fake_boot_control->SetCurrentSlot(0);
1469  payload_state.ReportFailedBootIfNeeded();
1470}
1471
1472TEST(PayloadStateTest, RebootAfterCanceledUpdate) {
1473  FakeSystemState fake_system_state;
1474  OmahaResponse response;
1475  PayloadState payload_state;
1476  FakePrefs fake_prefs;
1477
1478  fake_system_state.set_prefs(&fake_prefs);
1479  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1480  SetupPayloadStateWith2Urls("Hash3141", true, &payload_state, &response);
1481
1482  // Simulate a successful download and update.
1483  payload_state.DownloadComplete();
1484  payload_state.UpdateSucceeded();
1485  payload_state.ExpectRebootInNewVersion("Version:12345678");
1486
1487  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1488      metrics::kMetricFailedUpdateCount, _, _, _, _))
1489      .Times(0);
1490
1491  // Cancel the applied update.
1492  payload_state.ResetUpdateStatus();
1493
1494  // Simulate a reboot.
1495  payload_state.ReportFailedBootIfNeeded();
1496}
1497
1498TEST(PayloadStateTest, UpdateSuccessWithWipedPrefs) {
1499  FakeSystemState fake_system_state;
1500  PayloadState payload_state;
1501  FakePrefs fake_prefs;
1502
1503  fake_system_state.set_prefs(&fake_prefs);
1504  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1505
1506  EXPECT_CALL(*fake_system_state.mock_metrics_lib(), SendToUMA(
1507      metrics::kMetricFailedUpdateCount, _, _, _, _))
1508      .Times(0);
1509
1510  // Simulate a reboot in this environment.
1511  payload_state.ReportFailedBootIfNeeded();
1512}
1513
1514TEST(PayloadStateTest, DisallowP2PAfterTooManyAttempts) {
1515  OmahaResponse response;
1516  PayloadState payload_state;
1517  FakeSystemState fake_system_state;
1518  FakePrefs fake_prefs;
1519  fake_system_state.set_prefs(&fake_prefs);
1520
1521  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1522  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1523
1524  // Should allow exactly kMaxP2PAttempts...
1525  for (int n = 0; n < kMaxP2PAttempts; n++) {
1526    payload_state.P2PNewAttempt();
1527    EXPECT_TRUE(payload_state.P2PAttemptAllowed());
1528  }
1529  // ... but not more than that.
1530  payload_state.P2PNewAttempt();
1531  EXPECT_FALSE(payload_state.P2PAttemptAllowed());
1532}
1533
1534TEST(PayloadStateTest, DisallowP2PAfterDeadline) {
1535  OmahaResponse response;
1536  PayloadState payload_state;
1537  FakeSystemState fake_system_state;
1538  FakeClock fake_clock;
1539  FakePrefs fake_prefs;
1540
1541  fake_system_state.set_clock(&fake_clock);
1542  fake_system_state.set_prefs(&fake_prefs);
1543  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1544  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1545
1546  // Set the clock to 1 second.
1547  Time epoch = Time::FromInternalValue(1000000);
1548  fake_clock.SetWallclockTime(epoch);
1549
1550  // Do an attempt - this will set the timestamp.
1551  payload_state.P2PNewAttempt();
1552
1553  // Check that the timestamp equals what we just set.
1554  EXPECT_EQ(epoch, payload_state.GetP2PFirstAttemptTimestamp());
1555
1556  // Time hasn't advanced - this should work.
1557  EXPECT_TRUE(payload_state.P2PAttemptAllowed());
1558
1559  // Set clock to half the deadline - this should work.
1560  fake_clock.SetWallclockTime(epoch +
1561      TimeDelta::FromSeconds(kMaxP2PAttemptTimeSeconds) / 2);
1562  EXPECT_TRUE(payload_state.P2PAttemptAllowed());
1563
1564  // Check that the first attempt timestamp hasn't changed just
1565  // because the wall-clock time changed.
1566  EXPECT_EQ(epoch, payload_state.GetP2PFirstAttemptTimestamp());
1567
1568  // Set clock to _just_ before the deadline - this should work.
1569  fake_clock.SetWallclockTime(epoch +
1570      TimeDelta::FromSeconds(kMaxP2PAttemptTimeSeconds - 1));
1571  EXPECT_TRUE(payload_state.P2PAttemptAllowed());
1572
1573  // Set clock to _just_ after the deadline - this should not work.
1574  fake_clock.SetWallclockTime(epoch +
1575      TimeDelta::FromSeconds(kMaxP2PAttemptTimeSeconds + 1));
1576  EXPECT_FALSE(payload_state.P2PAttemptAllowed());
1577}
1578
1579TEST(PayloadStateTest, P2PStateVarsInitialValue) {
1580  OmahaResponse response;
1581  PayloadState payload_state;
1582  FakeSystemState fake_system_state;
1583  FakePrefs fake_prefs;
1584
1585  fake_system_state.set_prefs(&fake_prefs);
1586  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1587  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1588
1589  Time null_time = Time();
1590  EXPECT_EQ(null_time, payload_state.GetP2PFirstAttemptTimestamp());
1591  EXPECT_EQ(0, payload_state.GetP2PNumAttempts());
1592}
1593
1594TEST(PayloadStateTest, P2PStateVarsArePersisted) {
1595  OmahaResponse response;
1596  PayloadState payload_state;
1597  FakeSystemState fake_system_state;
1598  FakeClock fake_clock;
1599  FakePrefs fake_prefs;
1600  fake_system_state.set_clock(&fake_clock);
1601  fake_system_state.set_prefs(&fake_prefs);
1602  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1603  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1604
1605  // Set the clock to something known.
1606  Time time = Time::FromInternalValue(12345);
1607  fake_clock.SetWallclockTime(time);
1608
1609  // New p2p attempt - as a side-effect this will update the p2p state vars.
1610  payload_state.P2PNewAttempt();
1611  EXPECT_EQ(1, payload_state.GetP2PNumAttempts());
1612  EXPECT_EQ(time, payload_state.GetP2PFirstAttemptTimestamp());
1613
1614  // Now create a new PayloadState and check that it loads the state
1615  // vars correctly.
1616  PayloadState payload_state2;
1617  EXPECT_TRUE(payload_state2.Initialize(&fake_system_state));
1618  EXPECT_EQ(1, payload_state2.GetP2PNumAttempts());
1619  EXPECT_EQ(time, payload_state2.GetP2PFirstAttemptTimestamp());
1620}
1621
1622TEST(PayloadStateTest, P2PStateVarsAreClearedOnNewResponse) {
1623  OmahaResponse response;
1624  PayloadState payload_state;
1625  FakeSystemState fake_system_state;
1626  FakeClock fake_clock;
1627  FakePrefs fake_prefs;
1628  fake_system_state.set_clock(&fake_clock);
1629  fake_system_state.set_prefs(&fake_prefs);
1630
1631  EXPECT_TRUE(payload_state.Initialize(&fake_system_state));
1632  SetupPayloadStateWith2Urls("Hash8593", true, &payload_state, &response);
1633
1634  // Set the clock to something known.
1635  Time time = Time::FromInternalValue(12345);
1636  fake_clock.SetWallclockTime(time);
1637
1638  // New p2p attempt - as a side-effect this will update the p2p state vars.
1639  payload_state.P2PNewAttempt();
1640  EXPECT_EQ(1, payload_state.GetP2PNumAttempts());
1641  EXPECT_EQ(time, payload_state.GetP2PFirstAttemptTimestamp());
1642
1643  // Set a new response...
1644  SetupPayloadStateWith2Urls("Hash9904", true, &payload_state, &response);
1645
1646  // ... and check that it clears the P2P state vars.
1647  Time null_time = Time();
1648  EXPECT_EQ(0, payload_state.GetP2PNumAttempts());
1649  EXPECT_EQ(null_time, payload_state.GetP2PFirstAttemptTimestamp());
1650}
1651
1652}  // namespace chromeos_update_engine
1653