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