mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			607 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			607 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * DummyCompleter() lets tests easily specify the results of a partial
 | 
						|
 * hash completion request.
 | 
						|
 */
 | 
						|
function DummyCompleter() {
 | 
						|
  this.fragments = {};
 | 
						|
  this.queries = [];
 | 
						|
  this.tableName = "test-phish-simple";
 | 
						|
}
 | 
						|
 | 
						|
DummyCompleter.prototype = {
 | 
						|
  QueryInterface: ChromeUtils.generateQI(["nsIUrlClassifierHashCompleter"]),
 | 
						|
 | 
						|
  complete(partialHash, gethashUrl, tableName, cb) {
 | 
						|
    this.queries.push(partialHash);
 | 
						|
    var fragments = this.fragments;
 | 
						|
    var self = this;
 | 
						|
    var doCallback = function () {
 | 
						|
      if (self.alwaysFail) {
 | 
						|
        cb.completionFinished(Cr.NS_ERROR_FAILURE);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      if (fragments[partialHash]) {
 | 
						|
        for (var i = 0; i < fragments[partialHash].length; i++) {
 | 
						|
          var chunkId = fragments[partialHash][i][0];
 | 
						|
          var hash = fragments[partialHash][i][1];
 | 
						|
          cb.completionV2(hash, self.tableName, chunkId);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      cb.completionFinished(0);
 | 
						|
    };
 | 
						|
    executeSoon(doCallback);
 | 
						|
  },
 | 
						|
 | 
						|
  getHash(fragment) {
 | 
						|
    var data = new TextEncoder().encode(fragment);
 | 
						|
    var ch = Cc["@mozilla.org/security/hash;1"].createInstance(
 | 
						|
      Ci.nsICryptoHash
 | 
						|
    );
 | 
						|
    ch.init(ch.SHA256);
 | 
						|
    ch.update(data, data.length);
 | 
						|
    var hash = ch.finish(false);
 | 
						|
    return hash.slice(0, 32);
 | 
						|
  },
 | 
						|
 | 
						|
  addFragment(chunkId, fragment) {
 | 
						|
    this.addHash(chunkId, this.getHash(fragment));
 | 
						|
  },
 | 
						|
 | 
						|
  // This method allows the caller to generate complete hashes that match the
 | 
						|
  // prefix of a real fragment, but have different complete hashes.
 | 
						|
  addConflict(chunkId, fragment) {
 | 
						|
    var realHash = this.getHash(fragment);
 | 
						|
    var invalidHash = this.getHash("blah blah blah blah blah");
 | 
						|
    this.addHash(chunkId, realHash.slice(0, 4) + invalidHash.slice(4, 32));
 | 
						|
  },
 | 
						|
 | 
						|
  addHash(chunkId, hash) {
 | 
						|
    var partial = hash.slice(0, 4);
 | 
						|
    if (this.fragments[partial]) {
 | 
						|
      this.fragments[partial].push([chunkId, hash]);
 | 
						|
    } else {
 | 
						|
      this.fragments[partial] = [[chunkId, hash]];
 | 
						|
    }
 | 
						|
  },
 | 
						|
 | 
						|
  compareQueries(fragments) {
 | 
						|
    var expectedQueries = [];
 | 
						|
    for (let i = 0; i < fragments.length; i++) {
 | 
						|
      expectedQueries.push(this.getHash(fragments[i]).slice(0, 4));
 | 
						|
    }
 | 
						|
    Assert.equal(this.queries.length, expectedQueries.length);
 | 
						|
    expectedQueries.sort();
 | 
						|
    this.queries.sort();
 | 
						|
    for (let i = 0; i < this.queries.length; i++) {
 | 
						|
      Assert.equal(this.queries[i], expectedQueries[i]);
 | 
						|
    }
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
function setupCompleter(table, hits, conflicts) {
 | 
						|
  var completer = new DummyCompleter();
 | 
						|
  completer.tableName = table;
 | 
						|
  for (let i = 0; i < hits.length; i++) {
 | 
						|
    let chunkId = hits[i][0];
 | 
						|
    let fragments = hits[i][1];
 | 
						|
    for (let j = 0; j < fragments.length; j++) {
 | 
						|
      completer.addFragment(chunkId, fragments[j]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  for (let i = 0; i < conflicts.length; i++) {
 | 
						|
    let chunkId = conflicts[i][0];
 | 
						|
    let fragments = conflicts[i][1];
 | 
						|
    for (let j = 0; j < fragments.length; j++) {
 | 
						|
      completer.addConflict(chunkId, fragments[j]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  dbservice.setHashCompleter(table, completer);
 | 
						|
 | 
						|
  return completer;
 | 
						|
}
 | 
						|
 | 
						|
function installCompleter(table, fragments, conflictFragments) {
 | 
						|
  return setupCompleter(table, fragments, conflictFragments);
 | 
						|
}
 | 
						|
 | 
						|
function installFailingCompleter(table) {
 | 
						|
  var completer = setupCompleter(table, [], []);
 | 
						|
  completer.alwaysFail = true;
 | 
						|
  return completer;
 | 
						|
}
 | 
						|
 | 
						|
// Helper assertion for checking dummy completer queries
 | 
						|
gAssertions.completerQueried = function (data, cb) {
 | 
						|
  var completer = data[0];
 | 
						|
  completer.compareQueries(data[1]);
 | 
						|
  cb();
 | 
						|
};
 | 
						|
 | 
						|
function doTest(updates, assertions) {
 | 
						|
  doUpdateTest(updates, assertions, runNextTest, updateError);
 | 
						|
}
 | 
						|
 | 
						|
// Test an add of two partial urls to a fresh database
 | 
						|
function testPartialAdds() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsExist: addUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testPartialAddsWithConflicts() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  // Each result will have both a real match and a conflict
 | 
						|
  var completer = installCompleter(
 | 
						|
    "test-phish-simple",
 | 
						|
    [[1, addUrls]],
 | 
						|
    [[1, addUrls]]
 | 
						|
  );
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsExist: addUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
// Test whether the fragmenting code does not cause duplicated completions
 | 
						|
function testFragments() {
 | 
						|
  var addUrls = ["foo.com/a/b/c", "foo.net/", "foo.com/c/"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsExist: addUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
// Test http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec
 | 
						|
// section 6.2 example 1
 | 
						|
function testSpecFragments() {
 | 
						|
  var probeUrls = ["a.b.c/1/2.html?param=1"];
 | 
						|
 | 
						|
  var addUrls = [
 | 
						|
    "a.b.c/1/2.html",
 | 
						|
    "a.b.c/",
 | 
						|
    "a.b.c/1/",
 | 
						|
    "b.c/1/2.html?param=1",
 | 
						|
    "b.c/1/2.html",
 | 
						|
    "b.c/",
 | 
						|
    "b.c/1/",
 | 
						|
    "a.b.c/1/2.html?param=1",
 | 
						|
  ];
 | 
						|
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsExist: probeUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
// Test http://code.google.com/p/google-safe-browsing/wiki/Protocolv2Spec
 | 
						|
// section 6.2 example 2
 | 
						|
function testMoreSpecFragments() {
 | 
						|
  var probeUrls = ["a.b.c.d.e.f.g/1.html"];
 | 
						|
 | 
						|
  var addUrls = [
 | 
						|
    "a.b.c.d.e.f.g/1.html",
 | 
						|
    "a.b.c.d.e.f.g/",
 | 
						|
    "c.d.e.f.g/1.html",
 | 
						|
    "c.d.e.f.g/",
 | 
						|
    "d.e.f.g/1.html",
 | 
						|
    "d.e.f.g/",
 | 
						|
    "e.f.g/1.html",
 | 
						|
    "e.f.g/",
 | 
						|
    "f.g/1.html",
 | 
						|
    "f.g/",
 | 
						|
  ];
 | 
						|
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsExist: probeUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testFalsePositives() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  // Each result will have no matching complete hashes and a non-matching
 | 
						|
  // conflict
 | 
						|
  var completer = installCompleter("test-phish-simple", [], [[1, addUrls]]);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsDontExist: addUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testEmptyCompleter() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  // Completer will never return full hashes
 | 
						|
  var completer = installCompleter("test-phish-simple", [], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsDontExist: addUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testCompleterFailure() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  // Completer will never return full hashes
 | 
						|
  var completer = installFailingCompleter("test-phish-simple");
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsDontExist: addUrls,
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testMixedSizesSameDomain() {
 | 
						|
  var add1Urls = ["foo.com/a"];
 | 
						|
  var add2Urls = ["foo.com/b"];
 | 
						|
 | 
						|
  var update1 = buildPhishingUpdate([{ chunkNum: 1, urls: add1Urls }], 4);
 | 
						|
  var update2 = buildPhishingUpdate([{ chunkNum: 2, urls: add2Urls }], 32);
 | 
						|
 | 
						|
  // We should only need to complete the partial hashes
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, add1Urls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1-2",
 | 
						|
    // both urls should match...
 | 
						|
    urlsExist: add1Urls.concat(add2Urls),
 | 
						|
    // ... but the completer should only be queried for the partial entry
 | 
						|
    completerQueried: [completer, add1Urls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update1, update2], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testMixedSizesDifferentDomains() {
 | 
						|
  var add1Urls = ["foo.com/a"];
 | 
						|
  var add2Urls = ["bar.com/b"];
 | 
						|
 | 
						|
  var update1 = buildPhishingUpdate([{ chunkNum: 1, urls: add1Urls }], 4);
 | 
						|
  var update2 = buildPhishingUpdate([{ chunkNum: 2, urls: add2Urls }], 32);
 | 
						|
 | 
						|
  // We should only need to complete the partial hashes
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, add1Urls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1-2",
 | 
						|
    // both urls should match...
 | 
						|
    urlsExist: add1Urls.concat(add2Urls),
 | 
						|
    // ... but the completer should only be queried for the partial entry
 | 
						|
    completerQueried: [completer, add1Urls],
 | 
						|
  };
 | 
						|
 | 
						|
  doTest([update1, update2], assertions);
 | 
						|
}
 | 
						|
 | 
						|
function testInvalidHashSize() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 12); // only 4 and 32 are legal hash sizes
 | 
						|
 | 
						|
  var addUrls2 = ["zaz.com/a", "xyz.com/b"];
 | 
						|
  var update2 = buildPhishingUpdate([{ chunkNum: 2, urls: addUrls2 }], 4);
 | 
						|
 | 
						|
  installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:2",
 | 
						|
    urlsDontExist: addUrls,
 | 
						|
  };
 | 
						|
 | 
						|
  // A successful update will trigger an error
 | 
						|
  doUpdateTest([update2, update], assertions, updateError, runNextTest);
 | 
						|
}
 | 
						|
 | 
						|
function testWrongTable() {
 | 
						|
  var addUrls = ["foo.com/a"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
  var completer = installCompleter(
 | 
						|
    "test-malware-simple", // wrong table
 | 
						|
    [[1, addUrls]],
 | 
						|
    []
 | 
						|
  );
 | 
						|
 | 
						|
  // The above installCompleter installs the completer for test-malware-simple,
 | 
						|
  // we want it to be used for test-phish-simple too.
 | 
						|
  dbservice.setHashCompleter("test-phish-simple", completer);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    // The urls were added as phishing urls, but the completer is claiming
 | 
						|
    // that they are malware urls, and we trust the completer in this case.
 | 
						|
    // The result will be discarded, so we can only check for non-existence.
 | 
						|
    urlsDontExist: addUrls,
 | 
						|
    // Make sure the completer was actually queried.
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doUpdateTest(
 | 
						|
    [update],
 | 
						|
    assertions,
 | 
						|
    function () {
 | 
						|
      // Give the dbservice a chance to (not) cache the result.
 | 
						|
      do_timeout(3000, function () {
 | 
						|
        // The miss earlier will have caused a miss to be cached.
 | 
						|
        // Resetting the completer does not count as an update,
 | 
						|
        // so we will not be probed again.
 | 
						|
        var newCompleter = installCompleter(
 | 
						|
          "test-malware-simple",
 | 
						|
          [[1, addUrls]],
 | 
						|
          []
 | 
						|
        );
 | 
						|
        dbservice.setHashCompleter("test-phish-simple", newCompleter);
 | 
						|
 | 
						|
        var assertions1 = {
 | 
						|
          urlsDontExist: addUrls,
 | 
						|
        };
 | 
						|
        checkAssertions(assertions1, runNextTest);
 | 
						|
      });
 | 
						|
    },
 | 
						|
    updateError
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
function setupCachedResults(addUrls, part2) {
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    // Request the add url.  This should cause the completion to be cached.
 | 
						|
    urlsExist: addUrls,
 | 
						|
    // Make sure the completer was actually queried.
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  doUpdateTest(
 | 
						|
    [update],
 | 
						|
    assertions,
 | 
						|
    function () {
 | 
						|
      // Give the dbservice a chance to cache the result.
 | 
						|
      do_timeout(3000, part2);
 | 
						|
    },
 | 
						|
    updateError
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
function testCachedResults() {
 | 
						|
  setupCachedResults(["foo.com/a"], function () {
 | 
						|
    // This is called after setupCachedResults().  Verify that
 | 
						|
    // checking the url again does not cause a completer request.
 | 
						|
 | 
						|
    // install a new completer, this one should never be queried.
 | 
						|
    var newCompleter = installCompleter("test-phish-simple", [[1, []]], []);
 | 
						|
 | 
						|
    var assertions = {
 | 
						|
      urlsExist: ["foo.com/a"],
 | 
						|
      completerQueried: [newCompleter, []],
 | 
						|
    };
 | 
						|
    checkAssertions(assertions, runNextTest);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function testCachedResultsWithSub() {
 | 
						|
  setupCachedResults(["foo.com/a"], function () {
 | 
						|
    // install a new completer, this one should never be queried.
 | 
						|
    var newCompleter = installCompleter("test-phish-simple", [[1, []]], []);
 | 
						|
 | 
						|
    var removeUpdate = buildPhishingUpdate(
 | 
						|
      [{ chunkNum: 2, chunkType: "s", urls: ["1:foo.com/a"] }],
 | 
						|
      4
 | 
						|
    );
 | 
						|
 | 
						|
    var assertions = {
 | 
						|
      urlsDontExist: ["foo.com/a"],
 | 
						|
      completerQueried: [newCompleter, []],
 | 
						|
    };
 | 
						|
 | 
						|
    doTest([removeUpdate], assertions);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function testCachedResultsWithExpire() {
 | 
						|
  setupCachedResults(["foo.com/a"], function () {
 | 
						|
    // install a new completer, this one should never be queried.
 | 
						|
    var newCompleter = installCompleter("test-phish-simple", [[1, []]], []);
 | 
						|
 | 
						|
    var expireUpdate = "n:1000\ni:test-phish-simple\nad:1\n";
 | 
						|
 | 
						|
    var assertions = {
 | 
						|
      urlsDontExist: ["foo.com/a"],
 | 
						|
      completerQueried: [newCompleter, []],
 | 
						|
    };
 | 
						|
    doTest([expireUpdate], assertions);
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function testCachedResultsFailure() {
 | 
						|
  var existUrls = ["foo.com/a"];
 | 
						|
  setupCachedResults(existUrls, function () {
 | 
						|
    // This is called after setupCachedResults().  Verify that
 | 
						|
    // checking the url again does not cause a completer request.
 | 
						|
 | 
						|
    // install a new completer, this one should never be queried.
 | 
						|
    var newCompleter = installCompleter("test-phish-simple", [[1, []]], []);
 | 
						|
 | 
						|
    var assertions = {
 | 
						|
      urlsExist: existUrls,
 | 
						|
      completerQueried: [newCompleter, []],
 | 
						|
    };
 | 
						|
 | 
						|
    checkAssertions(assertions, function () {
 | 
						|
      // Apply the update. The cached completes should be gone.
 | 
						|
      doErrorUpdate(
 | 
						|
        "test-phish-simple,test-malware-simple",
 | 
						|
        function () {
 | 
						|
          // Now the completer gets queried again.
 | 
						|
          var newCompleter2 = installCompleter(
 | 
						|
            "test-phish-simple",
 | 
						|
            [[1, existUrls]],
 | 
						|
            []
 | 
						|
          );
 | 
						|
          var assertions2 = {
 | 
						|
            tableData: "test-phish-simple;a:1",
 | 
						|
            urlsExist: existUrls,
 | 
						|
            completerQueried: [newCompleter2, existUrls],
 | 
						|
          };
 | 
						|
          checkAssertions(assertions2, runNextTest);
 | 
						|
        },
 | 
						|
        updateError
 | 
						|
      );
 | 
						|
    });
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function testErrorList() {
 | 
						|
  var addUrls = ["foo.com/a", "foo.com/b", "bar.com/c"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: addUrls }], 4);
 | 
						|
  // The update failure should will kill the completes, so the above
 | 
						|
  // must be a prefix to get any hit at all past the update failure.
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, addUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-phish-simple;a:1",
 | 
						|
    urlsExist: addUrls,
 | 
						|
    // These are complete urls, and will only be completed if the
 | 
						|
    // list is stale.
 | 
						|
    completerQueried: [completer, addUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  // Apply the update.
 | 
						|
  doStreamUpdate(
 | 
						|
    update,
 | 
						|
    function () {
 | 
						|
      // Now the test-phish-simple and test-malware-simple tables are marked
 | 
						|
      // as fresh.  Fake an update failure to mark them stale.
 | 
						|
      doErrorUpdate(
 | 
						|
        "test-phish-simple,test-malware-simple",
 | 
						|
        function () {
 | 
						|
          // Now the lists should be marked stale.  Check assertions.
 | 
						|
          checkAssertions(assertions, runNextTest);
 | 
						|
        },
 | 
						|
        updateError
 | 
						|
      );
 | 
						|
    },
 | 
						|
    updateError
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
// Verify that different lists (test-phish-simple,
 | 
						|
// test-malware-simple) maintain their freshness separately.
 | 
						|
function testErrorListIndependent() {
 | 
						|
  var phishUrls = ["phish.com/a"];
 | 
						|
  var malwareUrls = ["attack.com/a"];
 | 
						|
  var update = buildPhishingUpdate([{ chunkNum: 1, urls: phishUrls }], 4);
 | 
						|
  // These have to persist past the update failure, so they must be prefixes,
 | 
						|
  // not completes.
 | 
						|
 | 
						|
  update += buildMalwareUpdate([{ chunkNum: 2, urls: malwareUrls }], 32);
 | 
						|
 | 
						|
  var completer = installCompleter("test-phish-simple", [[1, phishUrls]], []);
 | 
						|
 | 
						|
  var assertions = {
 | 
						|
    tableData: "test-malware-simple;a:2\ntest-phish-simple;a:1",
 | 
						|
    urlsExist: phishUrls,
 | 
						|
    malwareUrlsExist: malwareUrls,
 | 
						|
    // Only this phishing urls should be completed, because only the phishing
 | 
						|
    // urls will be stale.
 | 
						|
    completerQueried: [completer, phishUrls],
 | 
						|
  };
 | 
						|
 | 
						|
  // Apply the update.
 | 
						|
  doStreamUpdate(
 | 
						|
    update,
 | 
						|
    function () {
 | 
						|
      // Now the test-phish-simple and test-malware-simple tables are
 | 
						|
      // marked as fresh.  Fake an update failure to mark *just*
 | 
						|
      // phishing data as stale.
 | 
						|
      doErrorUpdate(
 | 
						|
        "test-phish-simple",
 | 
						|
        function () {
 | 
						|
          // Now the lists should be marked stale.  Check assertions.
 | 
						|
          checkAssertions(assertions, runNextTest);
 | 
						|
        },
 | 
						|
        updateError
 | 
						|
      );
 | 
						|
    },
 | 
						|
    updateError
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
function run_test() {
 | 
						|
  runTests([
 | 
						|
    testPartialAdds,
 | 
						|
    testPartialAddsWithConflicts,
 | 
						|
    testFragments,
 | 
						|
    testSpecFragments,
 | 
						|
    testMoreSpecFragments,
 | 
						|
    testFalsePositives,
 | 
						|
    testEmptyCompleter,
 | 
						|
    testCompleterFailure,
 | 
						|
    testMixedSizesSameDomain,
 | 
						|
    testMixedSizesDifferentDomains,
 | 
						|
    testInvalidHashSize,
 | 
						|
    testWrongTable,
 | 
						|
    testCachedResults,
 | 
						|
    testCachedResultsWithSub,
 | 
						|
    testCachedResultsWithExpire,
 | 
						|
    testCachedResultsFailure,
 | 
						|
    testErrorList,
 | 
						|
    testErrorListIndependent,
 | 
						|
  ]);
 | 
						|
}
 | 
						|
 | 
						|
do_test_pending();
 |