Add metrics to report the number of bytes downloaded per protocol.

This CL adds these two basic metrics:
1. The number of megabytes downloaded using each protocol (or source
in general, as we want to consider HTTP downloads from server and possibly
a peer in future as two different sources) for each successful update. The
totals across all protocols will equal the payload size exactly.
2. The total number of megabytes downloaded since the last update attempt.
If there are no errors, this should be same as above. Otherwise, this will
be larger and will help us to compute the update efficiency.

BUG=chromium:225953
TEST=Unit tests pass, new Unit tests added.
TEST=chrome://histograms shows metrics correctly.

Change-Id: Ic02e218f46568427df99a8a9df2011860aee84f3
Reviewed-on: https://gerrit.chromium.org/gerrit/48069
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Queue: Jay Srinivasan <jaysri@chromium.org>
Tested-by: Jay Srinivasan <jaysri@chromium.org>
diff --git a/payload_state_unittest.cc b/payload_state_unittest.cc
index 62de02b..ffd1b27 100644
--- a/payload_state_unittest.cc
+++ b/payload_state_unittest.cc
@@ -9,6 +9,7 @@
 #include "gtest/gtest.h"
 
 #include "update_engine/constants.h"
+#include "update_engine/mock_system_state.h"
 #include "update_engine/omaha_request_action.h"
 #include "update_engine/payload_state.h"
 #include "update_engine/prefs_mock.h"
@@ -26,6 +27,15 @@
 
 namespace chromeos_update_engine {
 
+const char* kCurrentBytesDownloadedFromHttps =
+  "current-bytes-downloaded-from-HttpsServer";
+const char* kTotalBytesDownloadedFromHttps =
+  "total-bytes-downloaded-from-HttpsServer";
+const char* kCurrentBytesDownloadedFromHttp =
+  "current-bytes-downloaded-from-HttpServer";
+const char* kTotalBytesDownloadedFromHttp =
+  "total-bytes-downloaded-from-HttpServer";
+
 static void SetupPayloadStateWith2Urls(string hash,
                                        PayloadState* payload_state,
                                        OmahaResponse* response) {
@@ -72,15 +82,25 @@
 
 TEST(PayloadStateTest, SetResponseWorksWithEmptyResponse) {
   OmahaResponse response;
-  NiceMock<PrefsMock> prefs;
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsBackoffExpiryTime, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateTimestampStart, _)).Times(AtLeast(1));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateDurationUptime, _)).Times(AtLeast(1));
+  MockSystemState mock_system_state;
+  NiceMock<PrefsMock>* prefs = mock_system_state.mock_prefs();
+  EXPECT_CALL(*prefs, SetInt64(_,_)).Times(AtLeast(0));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, 0)).Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateTimestampStart, _))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateDurationUptime, _))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
+    .Times(AtLeast(1));
   PayloadState payload_state;
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   payload_state.SetResponse(response);
   string stored_response_sign = payload_state.GetResponseSignature();
   string expected_response_sign = "NumURLs = 0\n"
@@ -103,15 +123,27 @@
   response.hash = "hash";
   response.metadata_size = 58123;
   response.metadata_signature = "msign";
-  NiceMock<PrefsMock> prefs;
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsBackoffExpiryTime, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateTimestampStart, _)).Times(AtLeast(1));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateDurationUptime, _)).Times(AtLeast(1));
+  MockSystemState mock_system_state;
+  NiceMock<PrefsMock>* prefs = mock_system_state.mock_prefs();
+  EXPECT_CALL(*prefs, SetInt64(_,_)).Times(AtLeast(0));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateTimestampStart, _))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateDurationUptime, _))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
+    .Times(AtLeast(1));
   PayloadState payload_state;
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   payload_state.SetResponse(response);
   string stored_response_sign = payload_state.GetResponseSignature();
   string expected_response_sign = "NumURLs = 1\n"
@@ -136,15 +168,23 @@
   response.hash = "rhash";
   response.metadata_size = 558123;
   response.metadata_signature = "metasign";
-  NiceMock<PrefsMock> prefs;
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsBackoffExpiryTime, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateTimestampStart, _)).Times(AtLeast(1));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateDurationUptime, _)).Times(AtLeast(1));
+  MockSystemState mock_system_state;
+  NiceMock<PrefsMock>* prefs = mock_system_state.mock_prefs();
+  EXPECT_CALL(*prefs, SetInt64(_,_)).Times(AtLeast(0));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
+    .Times(AtLeast(1));
   PayloadState payload_state;
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   payload_state.SetResponse(response);
   string stored_response_sign = payload_state.GetResponseSignature();
   string expected_response_sign = "NumURLs = 2\n"
@@ -164,27 +204,28 @@
 
 TEST(PayloadStateTest, CanAdvanceUrlIndexCorrectly) {
   OmahaResponse response;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
+  NiceMock<PrefsMock>* prefs = mock_system_state.mock_prefs();
   PayloadState payload_state;
 
+  EXPECT_CALL(*prefs, SetInt64(_,_)).Times(AtLeast(0));
   // Payload attempt should start with 0 and then advance to 1.
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0)).Times(1);
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 1)).Times(1);
-  EXPECT_CALL(prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(2);
-
-  // Durations will be set
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateTimestampStart, _)).Times(AtLeast(1));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateDurationUptime, _)).Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(AtLeast(2));
 
   // Url index should go from 0 to 1 twice.
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(2);
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(2);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(AtLeast(1));
 
   // Failure count should be called each times url index is set, so that's
   // 4 times for this test.
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0)).Times(4);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
+    .Times(AtLeast(4));
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
 
   // This does a SetResponse which causes all the states to be set to 0 for
   // the first time.
@@ -207,10 +248,10 @@
 
 TEST(PayloadStateTest, NewResponseResetsPayloadState) {
   OmahaResponse response;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
   PayloadState payload_state;
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
 
   // Set the first response.
   SetupPayloadStateWith2Urls("Hash5823", &payload_state, &response);
@@ -226,30 +267,58 @@
   // Make sure the url index was reset to 0 because of the new response.
   EXPECT_EQ(0, payload_state.GetUrlIndex());
   EXPECT_EQ(0, payload_state.GetUrlFailureCount());
+  EXPECT_EQ(0,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(0,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(0, payload_state.GetCurrentBytesDownloaded(
+                 kDownloadSourceHttpsServer));
+  EXPECT_EQ(0,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
 }
 
 TEST(PayloadStateTest, AllCountersGetUpdatedProperlyOnErrorCodesAndEvents) {
   OmahaResponse response;
   PayloadState payload_state;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
+  int progress_bytes = 100;
+  NiceMock<PrefsMock>* prefs = mock_system_state.mock_prefs();
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0)).Times(2);
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 1)).Times(1);
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 2)).Times(1);
+  EXPECT_CALL(*prefs, SetInt64(_,_)).Times(AtLeast(0));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
+    .Times(AtLeast(2));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 2))
+    .Times(AtLeast(1));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(4);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(AtLeast(4));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(4);
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(2);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(AtLeast(4));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 1)).Times(AtLeast(2));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0)).Times(7);
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 1)).Times(2);
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 2)).Times(1);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
+    .Times(AtLeast(7));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 1))
+    .Times(AtLeast(2));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 2))
+    .Times(AtLeast(1));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateTimestampStart, _)).Times(AtLeast(1));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateDurationUptime, _)).Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateTimestampStart, _))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsUpdateDurationUptime, _))
+    .Times(AtLeast(1));
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttps, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kCurrentBytesDownloadedFromHttp, progress_bytes))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kTotalBytesDownloadedFromHttp, progress_bytes))
+    .Times(AtLeast(1));
+
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
 
   SetupPayloadStateWith2Urls("Hash5873", &payload_state, &response);
 
@@ -306,7 +375,7 @@
 
   // And that failure count should be reset when we download some bytes
   // afterwards.
-  payload_state.DownloadProgress(100);
+  payload_state.DownloadProgress(progress_bytes);
   EXPECT_EQ(2, payload_state.GetPayloadAttemptNumber());
   EXPECT_EQ(0, payload_state.GetUrlIndex());
   EXPECT_EQ(0, payload_state.GetUrlFailureCount());
@@ -325,20 +394,24 @@
 TEST(PayloadStateTest, PayloadAttemptNumberIncreasesOnSuccessfulDownload) {
   OmahaResponse response;
   PayloadState payload_state;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
+  NiceMock<PrefsMock>* prefs = mock_system_state.mock_prefs();
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 0)).Times(1);
-  EXPECT_CALL(prefs, SetInt64(kPrefsPayloadAttemptNumber, 1)).Times(1);
+  EXPECT_CALL(*prefs, SetInt64(_,_)).Times(AtLeast(0));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsPayloadAttemptNumber, 1))
+    .Times(AtLeast(1));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsBackoffExpiryTime, _)).Times(2);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsBackoffExpiryTime, _))
+    .Times(AtLeast(2));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlIndex, 0)).Times(1);
-  EXPECT_CALL(prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0)).Times(1);
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlIndex, 0))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs, SetInt64(kPrefsCurrentUrlFailureCount, 0))
+    .Times(AtLeast(1));
 
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateTimestampStart, _)).Times(AtLeast(1));
-  EXPECT_CALL(prefs, SetInt64(kPrefsUpdateDurationUptime, _)).Times(AtLeast(1));
-
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
 
   SetupPayloadStateWith2Urls("Hash8593", &payload_state, &response);
 
@@ -353,9 +426,9 @@
 TEST(PayloadStateTest, SetResponseResetsInvalidUrlIndex) {
   OmahaResponse response;
   PayloadState payload_state;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   SetupPayloadStateWith2Urls("Hash4427", &payload_state, &response);
 
   // Generate enough events to advance URL index, failure count and
@@ -370,21 +443,22 @@
   // Now, simulate a corrupted url index on persisted store which gets
   // loaded when update_engine restarts. Using a different prefs object
   // so as to not bother accounting for the uninteresting calls above.
-  NiceMock<PrefsMock> prefs2;
-  EXPECT_CALL(prefs2, Exists(_)).WillRepeatedly(Return(true));
-  EXPECT_CALL(prefs2, GetInt64(kPrefsPayloadAttemptNumber, _));
-  EXPECT_CALL(prefs2, GetInt64(kPrefsBackoffExpiryTime, _));
-  EXPECT_CALL(prefs2, GetInt64(kPrefsCurrentUrlIndex, _))
-      .WillOnce(DoAll(SetArgumentPointee<1>(2), Return(true)));
-  EXPECT_CALL(prefs2, GetInt64(kPrefsCurrentUrlFailureCount, _));
-  EXPECT_CALL(prefs2, GetInt64(kPrefsUpdateTimestampStart, _));
-  EXPECT_CALL(prefs2, GetInt64(kPrefsUpdateDurationUptime, _));
+  MockSystemState mock_system_state2;
+  NiceMock<PrefsMock>* prefs2 = mock_system_state2.mock_prefs();
+  EXPECT_CALL(*prefs2, Exists(_)).WillRepeatedly(Return(true));
+  EXPECT_CALL(*prefs2, GetInt64(_,_)).Times(AtLeast(1));
+  EXPECT_CALL(*prefs2, GetInt64(kPrefsPayloadAttemptNumber, _))
+    .Times(AtLeast(1));
+  EXPECT_CALL(*prefs2, GetInt64(kPrefsCurrentUrlIndex, _))
+      .WillRepeatedly(DoAll(SetArgumentPointee<1>(2), Return(true)));
+  EXPECT_CALL(*prefs2, GetInt64(kPrefsCurrentUrlFailureCount, _))
+    .Times(AtLeast(1));
 
   // Note: This will be a different payload object, but the response should
   // have the same hash as before so as to not trivially reset because the
   // response was different. We want to specifically test that even if the
   // response is same, we should reset the state if we find it corrupted.
-  EXPECT_TRUE(payload_state.Initialize(&prefs2));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state2));
   SetupPayloadStateWith2Urls("Hash4427", &payload_state, &response);
 
   // Make sure all counters get reset to 0 because of the corrupted URL index
@@ -398,9 +472,9 @@
   OmahaResponse response;
   response.is_delta_payload = true;
   PayloadState payload_state;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   SetupPayloadStateWith2Urls("Hash6437", &payload_state, &response);
 
   // Simulate a successful download and see that we're ready to download
@@ -440,9 +514,9 @@
   OmahaResponse response;
   response.is_delta_payload = false;
   PayloadState payload_state;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   SetupPayloadStateWith2Urls("Hash8939", &payload_state, &response);
 
   CheckPayloadBackoffState(&payload_state, 1,  TimeDelta::FromDays(1));
@@ -461,9 +535,9 @@
   OmahaResponse response;
   response.disable_payload_backoff = true;
   PayloadState payload_state;
-  NiceMock<PrefsMock> prefs;
+  MockSystemState mock_system_state;
 
-  EXPECT_TRUE(payload_state.Initialize(&prefs));
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
   SetupPayloadStateWith2Urls("Hash8939", &payload_state, &response);
 
   // Simulate a successful download and see that we are ready to download
@@ -481,4 +555,122 @@
   EXPECT_FALSE(payload_state.ShouldBackoffDownload());
 }
 
+TEST(PayloadStateTest, BytesDownloadedMetricsGetAddedToCorrectSources) {
+  OmahaResponse response;
+  response.disable_payload_backoff = true;
+  PayloadState payload_state;
+  MockSystemState mock_system_state;
+  int https_total = 0;
+  int http_total = 0;
+
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
+  SetupPayloadStateWith2Urls("Hash3286", &payload_state, &response);
+
+  // Simulate a successful download and see that we are ready to download
+  // again without any backoff.
+  int first_chunk = 5000000;
+  http_total += first_chunk;
+  payload_state.DownloadProgress(first_chunk);
+  // Test that first all progress is made on HTTP and none on HTTPs.
+  EXPECT_EQ(first_chunk,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(http_total,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(0, payload_state.GetCurrentBytesDownloaded(
+                 kDownloadSourceHttpsServer));
+  EXPECT_EQ(https_total,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
+
+  // Simulate an error that'll cause the url index to point to https.
+  ActionExitCode error = kActionCodeDownloadMetadataSignatureMismatch;
+  payload_state.UpdateFailed(error);
+
+  // Test that no new progress is made on HTTP and new progress is on HTTPs.
+  int second_chunk = 23456789;
+  https_total += second_chunk;
+  payload_state.DownloadProgress(second_chunk);
+  EXPECT_EQ(first_chunk,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(http_total,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(second_chunk, payload_state.GetCurrentBytesDownloaded(
+              kDownloadSourceHttpsServer));
+  EXPECT_EQ(https_total,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
+
+  // Simulate error to go back to http.
+  payload_state.UpdateFailed(error);
+  int third_chunk = 32345678;
+  int http_chunk = first_chunk + third_chunk;
+  http_total += third_chunk;
+  int https_chunk = second_chunk;
+  payload_state.DownloadProgress(third_chunk);
+
+  // Test that third chunk is again back on HTTP. HTTPS remains on second chunk.
+  EXPECT_EQ(http_chunk,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(http_chunk,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(second_chunk, payload_state.GetCurrentBytesDownloaded(
+                 kDownloadSourceHttpsServer));
+  EXPECT_EQ(https_total,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
+
+  EXPECT_CALL(*mock_system_state.mock_metrics_lib(), SendToUMA(
+      "Installer.SuccessfulMBsDownloadedFromHttpServer",
+      http_chunk / kNumBytesInOneMiB, _, _, _));
+  EXPECT_CALL(*mock_system_state.mock_metrics_lib(), SendToUMA(
+      "Installer.TotalMBsDownloadedFromHttpServer",
+      http_total / kNumBytesInOneMiB, _, _, _));
+  EXPECT_CALL(*mock_system_state.mock_metrics_lib(), SendToUMA(
+      "Installer.SuccessfulMBsDownloadedFromHttpsServer",
+      https_chunk / kNumBytesInOneMiB, _, _, _));
+  EXPECT_CALL(*mock_system_state.mock_metrics_lib(), SendToUMA(
+      "Installer.TotalMBsDownloadedFromHttpsServer",
+      https_total / kNumBytesInOneMiB, _, _, _));
+
+  payload_state.UpdateSucceeded();
+
+  // Make sure the metrics are reset after a successful update.
+  EXPECT_EQ(0,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(0,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(0, payload_state.GetCurrentBytesDownloaded(
+                 kDownloadSourceHttpsServer));
+  EXPECT_EQ(0,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
+}
+
+TEST(PayloadStateTest, RestartingUpdateResetsMetrics) {
+  OmahaResponse response;
+  MockSystemState mock_system_state;
+  PayloadState payload_state;
+
+  EXPECT_TRUE(payload_state.Initialize(&mock_system_state));
+
+  // Set the first response.
+  SetupPayloadStateWith2Urls("Hash5823", &payload_state, &response);
+
+  int num_bytes = 10000;
+  payload_state.DownloadProgress(num_bytes);
+  EXPECT_EQ(num_bytes,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(num_bytes,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(0, payload_state.GetCurrentBytesDownloaded(
+                 kDownloadSourceHttpsServer));
+  EXPECT_EQ(0,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpsServer));
+
+  payload_state.UpdateRestarted();
+  // Make sure the current bytes downloaded is reset, but not the total bytes.
+  EXPECT_EQ(0,
+            payload_state.GetCurrentBytesDownloaded(kDownloadSourceHttpServer));
+  EXPECT_EQ(num_bytes,
+            payload_state.GetTotalBytesDownloaded(kDownloadSourceHttpServer));
+}
+
+
+
 }