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 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: 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 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 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 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 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 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 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 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 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 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 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(¶ms); 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 653 TEST_F(PayloadStateTest, NoBackoffForP2PUpdates) { 654 OmahaResponse response; 655 PayloadState payload_state; 656 OmahaRequestParams params; 657 params.Init("", "", {}); 658 FakeSystemState::Get()->set_request_params(¶ms); 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 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 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 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 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 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 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 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 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 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 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(¶ms); 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 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 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 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 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 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 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 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 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(¶ms); 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 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(¶ms); 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 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(¶ms); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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