Bug 1500360 - P2. Use reason in download protection testcases. r=francois
authordlee <dlee@mozilla.com>
Wed, 28 Nov 2018 14:07:43 +0000
changeset 504960 dc40390fd43656344b774aa2ba05caa2ebfa14ab
parent 504959 db270ae8003b5eaac4658768af0b5f63369a942a
child 504961 66e1668bb44c322c83e89bfebae59e0a4d2a2f07
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfrancois
bugs1500360
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1500360 - P2. Use reason in download protection testcases. r=francois Add "Reason" checks in the testcase because it provides more fine-grained check. In this patch, I also refactor the testcase by move telemetry stuff into head_download_manager.js so it could easily used by different testcases. Differential Revision: https://phabricator.services.mozilla.com/D10953
toolkit/components/reputationservice/test/unit/head_download_manager.js
toolkit/components/reputationservice/test/unit/test_app_rep.js
toolkit/components/reputationservice/test/unit/test_app_rep_maclinux.js
toolkit/components/reputationservice/test/unit/test_app_rep_windows.js
--- a/toolkit/components/reputationservice/test/unit/head_download_manager.js
+++ b/toolkit/components/reputationservice/test/unit/head_download_manager.js
@@ -5,12 +5,91 @@
 // This file tests the download manager backend
 
 do_get_profile();
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://testing-common/httpd.js");
 
+// List types, this should sync with |enum LIST_TYPES| defined in PendingLookup.
+var ALLOW_LIST = 0;
+var BLOCK_LIST = 1;
+var NO_LIST = 2;
+
+// Allow or block reason, this should sync with |enum Reason| in ApplicationReputation.cpp
+var NotSet = 0;
+var LocalWhitelist = 1;
+var LocalBlocklist = 2;
+var NonBinaryFile = 3;
+var VerdictSafe = 4;
+var VerdictUnknown = 5;
+var VerdictDangerous = 6;
+var VerdictDangerousHost = 7;
+var VerdictUnwanted = 8;
+var VerdictUncommon = 9;
+var VerdictUnrecognized = 10;
+var DangerousPrefOff = 11;
+var DangerousHostPrefOff = 12;
+var UnwantedPrefOff = 13;
+var UncommonPrefOff = 14;
+var NetworkError = 15;
+var RemoteLookupDisabled = 16;
+var InternalError = 17;
+var DPDisabled = 18;
+var MAX_REASON = 19;
+
 function createURI(aObj) {
   return (aObj instanceof Ci.nsIFile) ? Services.io.newFileURI(aObj) :
                                         Services.io.newURI(aObj);
 }
+
+function add_telemetry_count(telemetry, index, count) {
+  let val = telemetry[index] || 0;
+  telemetry[index] = val + count;
+}
+
+function check_telemetry(aExpectedTelemetry) {
+  // SHOULD_BLOCK = true
+  let shouldBlock = Services.telemetry
+                            .getHistogramById("APPLICATION_REPUTATION_SHOULD_BLOCK")
+                            .snapshot();
+  let expectedShouldBlock = aExpectedTelemetry.shouldBlock;
+  Assert.equal(shouldBlock.values[1] || 0, expectedShouldBlock);
+
+  let local = Services.telemetry
+                      .getHistogramById("APPLICATION_REPUTATION_LOCAL")
+                      .snapshot();
+
+  let expectedLocal = aExpectedTelemetry.local;
+  Assert.equal(local.values[ALLOW_LIST] || 0, expectedLocal[ALLOW_LIST] || 0,
+               "Allow list.values don't match");
+  Assert.equal(local.values[BLOCK_LIST] || 0, expectedLocal[BLOCK_LIST] || 0,
+               "Block list.values don't match");
+  Assert.equal(local.values[NO_LIST] || 0, expectedLocal[NO_LIST] || 0,
+               "No list.values don't match");
+
+  let reason = Services.telemetry
+                       .getHistogramById("APPLICATION_REPUTATION_REASON")
+                       .snapshot();
+  let expectedReason = aExpectedTelemetry.reason;
+
+  for (let i = 0; i < MAX_REASON; i++) {
+    if ((reason.values[i] || 0) != (expectedReason[i] || 0)) {
+      Assert.ok(false, "Allow or Block reason(" + i + ") doesn't match");
+    }
+  }
+}
+
+function get_telemetry_snapshot() {
+  let local = Services.telemetry
+                      .getHistogramById("APPLICATION_REPUTATION_LOCAL")
+                      .snapshot();
+  let shouldBlock = Services.telemetry
+                            .getHistogramById("APPLICATION_REPUTATION_SHOULD_BLOCK")
+                            .snapshot();
+  let reason = Services.telemetry
+                       .getHistogramById("APPLICATION_REPUTATION_REASON")
+                       .snapshot();
+  return { shouldBlock: shouldBlock.values[1] || 0,
+           local: local.values,
+           reason: reason.values };
+}
--- a/toolkit/components/reputationservice/test/unit/test_app_rep.js
+++ b/toolkit/components/reputationservice/test/unit/test_app_rep.js
@@ -9,20 +9,16 @@ ChromeUtils.import("resource://gre/modul
 
 const gAppRep = Cc["@mozilla.org/reputationservice/application-reputation-service;1"].
                   getService(Ci.nsIApplicationReputationService);
 var gHttpServ = null;
 var gTables = {};
 var gExpectedRemote = false;
 var gExpectedRemoteRequestBody = "";
 
-var ALLOW_LIST = 0;
-var BLOCK_LIST = 1;
-var NO_LIST = 2;
-
 var whitelistedURI = createURI("http://foo:bar@whitelisted.com/index.htm#junk");
 var exampleURI = createURI("http://user:password@example.com/i.html?foo=bar");
 var exampleReferrerURI = createURI("http://user:password@example.referrer.com/i.html?foo=bar");
 var exampleRedirectURI = createURI("http://user:password@example.redirect.com/i.html?foo=bar");
 var blocklistedURI = createURI("http://baz:qux@blocklisted.com?xyzzy");
 
 var binaryFile = "binaryFile.exe";
 var nonBinaryFile = "nonBinaryFile.txt";
@@ -107,72 +103,45 @@ add_task(async function test_setup() {
     return (async function() {
       await new Promise(resolve => {
         gHttpServ.stop(resolve);
       });
     })();
   });
 });
 
-function check_telemetry(aShouldBlockCount,
-                         aListCounts) {
-  let local = Services.telemetry
-                      .getHistogramById("APPLICATION_REPUTATION_LOCAL")
-                      .snapshot();
-  Assert.equal(local.values[ALLOW_LIST] || 0, aListCounts[ALLOW_LIST] || 0,
-               "Allow list counts don't match");
-  Assert.equal(local.values[BLOCK_LIST] || 0, aListCounts[BLOCK_LIST] || 0,
-               "Block list counts don't match");
-  Assert.equal(local.values[NO_LIST] || 0, aListCounts[NO_LIST] || 0,
-               "No list counts don't match");
+add_test(function test_nullSourceURI() {
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.reason, InternalError, 1);
 
-  let shouldBlock = Services.telemetry
-                            .getHistogramById("APPLICATION_REPUTATION_SHOULD_BLOCK")
-                            .snapshot();
-  // SHOULD_BLOCK = true
-  Assert.equal(shouldBlock.values[1], aShouldBlockCount);
-}
-
-function get_telemetry_counts() {
-  let local = Services.telemetry
-                      .getHistogramById("APPLICATION_REPUTATION_LOCAL")
-                      .snapshot();
-  let shouldBlock = Services.telemetry
-                            .getHistogramById("APPLICATION_REPUTATION_SHOULD_BLOCK")
-                            .snapshot();
-  return { shouldBlock: shouldBlock.values[1] || 0,
-           listCounts: local.values };
-}
-
-add_test(function test_nullSourceURI() {
-  let counts = get_telemetry_counts();
   gAppRep.queryReputation({
     // No source URI
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_ERROR_UNEXPECTED, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, counts.listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_nullCallback() {
-  let counts = get_telemetry_counts();
+  let expected = get_telemetry_snapshot();
+
   try {
     gAppRep.queryReputation({
       sourceURI: createURI("http://example.com"),
       fileSize: 12,
     }, null);
     do_throw("Callback cannot be null");
   } catch (ex) {
     if (ex.result != Cr.NS_ERROR_INVALID_POINTER)
       throw ex;
     // We don't even increment the count here, because there's no callback.
-    check_telemetry(counts.shouldBlock, counts.listCounts);
+    check_telemetry(expected);
     run_next_test();
   }
 });
 
 // Set up the local whitelist.
 add_test(function test_local_list() {
   // Construct a response with redirect urls.
   function processUpdateRequest() {
@@ -221,114 +190,125 @@ add_test(function test_local_list() {
     true, // isPostRequest.
     "http://localhost:4444/downloads",
     updateSuccess, handleError, handleError);
 });
 
 add_test(function test_unlisted() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  let val = listCounts[NO_LIST] || 0;
-  listCounts[NO_LIST] = val + 1;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
+
   gAppRep.queryReputation({
     sourceURI: exampleURI,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_non_uri() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
+
   // No listcount is incremented, since the sourceURI is not an nsIURL
   let source = NetUtil.newURI("data:application/octet-stream,ABC");
   Assert.equal(false, source instanceof Ci.nsIURL);
   gAppRep.queryReputation({
     sourceURI: source,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_local_blacklist() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[BLOCK_LIST]++;
+  let expected = get_telemetry_snapshot();
+  expected.shouldBlock++;
+  add_telemetry_count(expected.local, BLOCK_LIST, 1);
+  add_telemetry_count(expected.reason, LocalBlocklist, 1);
+
   gAppRep.queryReputation({
     sourceURI: blocklistedURI,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(aShouldBlock);
-    check_telemetry(counts.shouldBlock + 1, listCounts);
+    check_telemetry(expected);
+
     run_next_test();
   });
 });
 
 add_test(function test_referer_blacklist() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[BLOCK_LIST]++;
-  listCounts[NO_LIST]++;
+  let expected = get_telemetry_snapshot();
+  expected.shouldBlock++;
+  add_telemetry_count(expected.local, BLOCK_LIST, 1);
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, LocalBlocklist, 1);
+
   gAppRep.queryReputation({
     sourceURI: exampleURI,
     referrerURI: blocklistedURI,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(aShouldBlock);
-    check_telemetry(counts.shouldBlock + 1, listCounts);
+    check_telemetry(expected);
+
     run_next_test();
   });
 });
 
 add_test(function test_blocklist_trumps_allowlist() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[BLOCK_LIST]++;
-  listCounts[ALLOW_LIST]++;
+  let expected = get_telemetry_snapshot();
+  expected.shouldBlock++;
+  add_telemetry_count(expected.local, BLOCK_LIST, 1);
+  add_telemetry_count(expected.local, ALLOW_LIST, 1);
+  add_telemetry_count(expected.reason, LocalBlocklist, 1);
+
   gAppRep.queryReputation({
     sourceURI: whitelistedURI,
     referrerURI: blocklistedURI,
     suggestedFileName: binaryFile,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(aShouldBlock);
-    check_telemetry(counts.shouldBlock + 1, listCounts);
+    check_telemetry(expected);
+
     run_next_test();
   });
 });
 
 add_test(function test_redirect_on_blocklist() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[BLOCK_LIST]++;
-  listCounts[ALLOW_LIST]++;
-  listCounts[NO_LIST]++;
+  let expected = get_telemetry_snapshot();
+  expected.shouldBlock++;
+  add_telemetry_count(expected.local, BLOCK_LIST, 1);
+  add_telemetry_count(expected.local, ALLOW_LIST, 1);
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, LocalBlocklist, 1);
   let secman = Services.scriptSecurityManager;
   let badRedirects = Cc["@mozilla.org/array;1"]
                        .createInstance(Ci.nsIMutableArray);
 
   let redirect1 = {
     QueryInterface: ChromeUtils.generateQI([Ci.nsIRedirectHistoryEntry]),
     principal: secman.createCodebasePrincipal(exampleURI, {}),
   };
@@ -352,81 +332,81 @@ add_test(function test_redirect_on_block
     sourceURI: whitelistedURI,
     referrerURI: exampleURI,
     redirects: badRedirects,
     suggestedFileName: binaryFile,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(aShouldBlock);
-    check_telemetry(counts.shouldBlock + 1, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_whitelisted_source() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[ALLOW_LIST]++;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, ALLOW_LIST, 1);
+  add_telemetry_count(expected.reason, LocalWhitelist, 1);
   gAppRep.queryReputation({
     sourceURI: whitelistedURI,
     suggestedFileName: binaryFile,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_whitelisted_non_binary_source() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[NO_LIST]++;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
   gAppRep.queryReputation({
     sourceURI: whitelistedURI,
     suggestedFileName: nonBinaryFile,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_whitelisted_referrer() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[NO_LIST] += 2;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 2);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
   gAppRep.queryReputation({
     sourceURI: exampleURI,
     referrerURI: whitelistedURI,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_whitelisted_redirect() {
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[NO_LIST] += 3;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 3);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
   let secman = Services.scriptSecurityManager;
   let okayRedirects = Cc["@mozilla.org/array;1"]
                        .createInstance(Ci.nsIMutableArray);
 
   let redirect1 = {
     QueryInterface: ChromeUtils.generateQI([Ci.nsIRedirectHistoryEntry]),
     principal: secman.createCodebasePrincipal(exampleURI, {}),
   };
@@ -442,34 +422,34 @@ add_test(function test_whitelisted_redir
 
   gAppRep.queryReputation({
     sourceURI: exampleURI,
     redirects: okayRedirects,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
     run_next_test();
   });
 });
 
 add_test(function test_remote_lookup_protocolbuf() {
   // This long hard-coded string is the contents of the request generated by
   // the Application Reputation component, converted to the binary protobuf format.
   // If this test is changed, or we add anything to the remote lookup requests
   // in ApplicationReputation.cpp, then we'll need to update this hard-coded string.
   gExpectedRemote = true;
   gExpectedRemoteRequestBody = "\x0A\x19\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x12\x22\x0A\x20\x61\x62\x63\x00\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x64\x65\x18\x0C\x22\x41\x0A\x19\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x10\x00\x22\x22\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x72\x65\x66\x65\x72\x72\x65\x72\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x22\x26\x0A\x22\x68\x74\x74\x70\x3A\x2F\x2F\x65\x78\x61\x6D\x70\x6C\x65\x2E\x72\x65\x64\x69\x72\x65\x63\x74\x2E\x63\x6F\x6D\x2F\x69\x2E\x68\x74\x6D\x6C\x10\x01\x30\x01\x4A\x0E\x62\x69\x6E\x61\x72\x79\x46\x69\x6C\x65\x2E\x65\x78\x65\x50\x00\x5A\x05\x65\x6E\x2D\x55\x53";
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
   let secman = Services.scriptSecurityManager;
-  let counts = get_telemetry_counts();
-  let listCounts = counts.listCounts;
-  listCounts[NO_LIST] += 3;
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 3);
+  add_telemetry_count(expected.reason, VerdictSafe, 1);
 
   // Redirects
   let redirects = Cc["@mozilla.org/array;1"]
                      .createInstance(Ci.nsIMutableArray);
   let redirect1 = {
     QueryInterface: ChromeUtils.generateQI([Ci.nsIRedirectHistoryEntry]),
     principal: secman.createCodebasePrincipal(exampleRedirectURI, {}),
   };
@@ -483,14 +463,14 @@ add_test(function test_remote_lookup_pro
     referrerURI: exampleReferrerURI,
     suggestedFileName: binaryFile,
     sha256Hash,
     redirects,
     fileSize: 12,
   }, function onComplete(aShouldBlock, aStatus) {
     Assert.equal(Cr.NS_OK, aStatus);
     Assert.ok(!aShouldBlock);
-    check_telemetry(counts.shouldBlock, listCounts);
+    check_telemetry(expected);
 
     gExpectedRemote = false;
     run_next_test();
   });
 });
--- a/toolkit/components/reputationservice/test/unit/test_app_rep_maclinux.js
+++ b/toolkit/components/reputationservice/test/unit/test_app_rep_maclinux.js
@@ -187,21 +187,21 @@ function waitForUpdates() {
       "goog-downloadwhite-digest256",
       "goog-downloadwhite-digest256;\n",
       true,
       "http://localhost:4444/downloads",
       updateSuccess, handleError, handleError);
   });
 }
 
-function promiseQueryReputation(query, expectedShouldBlock) {
+function promiseQueryReputation(query, expected) {
   return new Promise(resolve => {
     function onComplete(aShouldBlock, aStatus) {
       Assert.equal(Cr.NS_OK, aStatus);
-      Assert.equal(aShouldBlock, expectedShouldBlock);
+      check_telemetry(expected);
       resolve(true);
     }
     gAppRep.queryReputation(query, onComplete);
   });
 }
 
 add_task(async function() {
   // Wait for Safebrowsing local list updates to complete.
@@ -209,81 +209,108 @@ add_task(async function() {
 });
 
 add_task(async function test_blocked_binary() {
   // We should reach the remote server for a verdict.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
+  let expected = get_telemetry_snapshot();
+  expected.shouldBlock++;
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, VerdictDangerous, 1);
+
   // evil.com should return a malware verdict from the remote server.
   await promiseQueryReputation({sourceURI: createURI("http://evil.com"),
                                 suggestedFileName: "noop.bat",
-                                fileSize: 12}, true);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_non_binary() {
   // We should not reach the remote server for a verdict for non-binary files.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/throw");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
+
   await promiseQueryReputation({sourceURI: createURI("http://evil.com"),
                                 suggestedFileName: "noop.txt",
-                                fileSize: 12}, false);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_good_binary() {
   // We should reach the remote server for a verdict.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, VerdictSafe, 1);
+
   // mozilla.com should return a not-guilty verdict from the remote server.
   await promiseQueryReputation({sourceURI: createURI("http://mozilla.com"),
                                 suggestedFileName: "noop.bat",
-                                fileSize: 12}, false);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_disabled() {
   // Explicitly disable remote checks
   Services.prefs.setBoolPref(remoteEnabledPref,
                              false);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/throw");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, RemoteLookupDisabled, 1);
+
   let query = {sourceURI: createURI("http://example.com"),
                suggestedFileName: "noop.bat",
                fileSize: 12};
   await new Promise(resolve => {
     gAppRep.queryReputation(query,
       function onComplete(aShouldBlock, aStatus) {
         // We should be getting NS_ERROR_NOT_AVAILABLE if the service is disabled
         Assert.equal(Cr.NS_ERROR_NOT_AVAILABLE, aStatus);
         Assert.ok(!aShouldBlock);
+        check_telemetry(expected);
         resolve(true);
       }
     );
   });
 });
 
 add_task(async function test_disabled_through_lists() {
   Services.prefs.setBoolPref(remoteEnabledPref,
                              false);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
   Services.prefs.setCharPref("urlclassifier.downloadBlockTable", "");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, RemoteLookupDisabled, 1);
+
   let query = {sourceURI: createURI("http://example.com"),
                suggestedFileName: "noop.bat",
                fileSize: 12};
   await new Promise(resolve => {
     gAppRep.queryReputation(query,
       function onComplete(aShouldBlock, aStatus) {
         // We should be getting NS_ERROR_NOT_AVAILABLE if the service is disabled
         Assert.equal(Cr.NS_ERROR_NOT_AVAILABLE, aStatus);
         Assert.ok(!aShouldBlock);
+        check_telemetry(expected);
         resolve(true);
       }
     );
   });
 });
 add_task(async function test_teardown() {
   gStillRunning = false;
 });
--- a/toolkit/components/reputationservice/test/unit/test_app_rep_windows.js
+++ b/toolkit/components/reputationservice/test/unit/test_app_rep_windows.js
@@ -277,21 +277,21 @@ function waitForUpdates() {
       "goog-downloadwhite-digest256",
       "goog-downloadwhite-digest256;\n",
       true,
       "http://localhost:4444/downloads",
       updateSuccess, handleError, handleError);
   });
 }
 
-function promiseQueryReputation(query, expectedShouldBlock) {
+function promiseQueryReputation(query, expected) {
   return new Promise(resolve => {
     function onComplete(aShouldBlock, aStatus) {
       Assert.equal(Cr.NS_OK, aStatus);
-      Assert.equal(aShouldBlock, expectedShouldBlock);
+      check_telemetry(expected);
       resolve(true);
     }
     gAppRep.queryReputation(query, onComplete);
   });
 }
 
 add_task(async function() {
   // Wait for Safebrowsing local list updates to complete.
@@ -300,16 +300,20 @@ add_task(async function() {
 
 add_task(async function test_signature_whitelists() {
   // We should never get to the remote server.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/throw");
 
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
+
   // Use BackgroundFileSaver to extract the signature on Windows.
   let destFile = FileTestUtils.getTempFile(TEST_FILE_NAME_1);
 
   let data = readFileToString("data/signed_win.exe");
   let saver = new BackgroundFileSaverOutputStream();
   let completionPromise = promiseSaverComplete(saver);
   saver.enableSignatureInfo();
   saver.setTarget(destFile, false);
@@ -320,90 +324,118 @@ add_task(async function test_signature_w
 
   // Clean up.
   destFile.remove(false);
 
   // evil.com is not on the allowlist, but this binary is signed by an entity
   // whose certificate information is on the allowlist.
   await promiseQueryReputation({sourceURI: createURI("http://evil.com"),
                                 signatureInfo: saver.signatureInfo,
-                                fileSize: 12}, false);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_blocked_binary() {
   // We should reach the remote server for a verdict.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
+
+  let expected = get_telemetry_snapshot();
+  expected.shouldBlock++;
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, VerdictDangerous, 1);
+
   // evil.com should return a malware verdict from the remote server.
   await promiseQueryReputation({sourceURI: createURI("http://evil.com"),
                                 suggestedFileName: "noop.bat",
-                                fileSize: 12}, true);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_non_binary() {
   // We should not reach the remote server for a verdict for non-binary files.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/throw");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, NonBinaryFile, 1);
+
   await promiseQueryReputation({sourceURI: createURI("http://evil.com"),
                                 suggestedFileName: "noop.txt",
-                                fileSize: 12}, false);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_good_binary() {
   // We should reach the remote server for a verdict.
   Services.prefs.setBoolPref(remoteEnabledPref,
                              true);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, VerdictSafe, 1);
+
   // mozilla.com should return a not-guilty verdict from the remote server.
   await promiseQueryReputation({sourceURI: createURI("http://mozilla.com"),
                                 suggestedFileName: "noop.bat",
-                                fileSize: 12}, false);
+                                fileSize: 12}, expected);
 });
 
 add_task(async function test_disabled() {
   // Explicitly disable remote checks
   Services.prefs.setBoolPref(remoteEnabledPref,
                              false);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/throw");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, RemoteLookupDisabled, 1);
+
   let query = {sourceURI: createURI("http://example.com"),
                suggestedFileName: "noop.bat",
                fileSize: 12};
   await new Promise(resolve => {
     gAppRep.queryReputation(query,
       function onComplete(aShouldBlock, aStatus) {
         // We should be getting NS_ERROR_NOT_AVAILABLE if the service is disabled
         Assert.equal(Cr.NS_ERROR_NOT_AVAILABLE, aStatus);
         Assert.ok(!aShouldBlock);
+        check_telemetry(expected);
         resolve(true);
       }
     );
   });
 });
 
 add_task(async function test_disabled_through_lists() {
   Services.prefs.setBoolPref(remoteEnabledPref,
                              false);
   Services.prefs.setCharPref(appRepURLPref,
                              "http://localhost:4444/download");
   Services.prefs.setCharPref("urlclassifier.downloadBlockTable", "");
+
+  let expected = get_telemetry_snapshot();
+  add_telemetry_count(expected.local, NO_LIST, 1);
+  add_telemetry_count(expected.reason, RemoteLookupDisabled, 1);
+
   let query = {sourceURI: createURI("http://example.com"),
                suggestedFileName: "noop.bat",
                fileSize: 12};
   await new Promise(resolve => {
     gAppRep.queryReputation(query,
       function onComplete(aShouldBlock, aStatus) {
         // We should be getting NS_ERROR_NOT_AVAILABLE if the service is disabled
         Assert.equal(Cr.NS_ERROR_NOT_AVAILABLE, aStatus);
         Assert.ok(!aShouldBlock);
+        check_telemetry(expected);
         resolve(true);
       }
     );
   });
 });
 add_task(async function test_teardown() {
   gStillRunning = false;
 });