Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_ProfileCounter.js   Sprache: JAVA

 
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

"use strict";

const { BrowserUsageTelemetry } = ChromeUtils.importESModule(
  "resource:///modules/BrowserUsageTelemetry.sys.mjs"
);
const { TelemetryTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/TelemetryTestUtils.sys.mjs"
);

const PROFILE_COUNT_SCALAR = "browser.engagement.profile_count";
// Largest possible uint32_t value represents an error.
const SCALAR_ERROR_VALUE = 0;

const FILE_OPEN_OPERATION = "open";
const ERROR_FILE_NOT_FOUND = "NotFoundError";
const ERROR_ACCESS_DENIED = "NotAllowedError";

// We will redirect I/O to/from the profile counter file to read/write this
// variable instead. That makes it easier for us to:
//   - avoid interference from any pre-existing file
//   - read and change the values in the file.
//   - clean up changes made to the file
// We will translate a null value stored here to a File Not Found error.
var gFakeProfileCounterFile = null;
// We will use this to check that the profile counter code doesn't try to write
// to multiple files (since this test will malfunction in that case due to
// gFakeProfileCounterFile only being setup to accommodate a single file).
var gProfileCounterFilePath = null;

// Storing a value here lets us test the behavior when we encounter an error
// reading or writing to the file. A null value means that no error will
// be simulated (other than possibly a NotFoundError).
var gNextReadExceptionReason = null;
var gNextWriteExceptionReason = null;

// Nothing will actually be stored in this directory, so it's not important that
// it be valid, but the leafname should be unique to this test in order to be
// sure of preventing name conflicts with the pref:
// `browser.engagement.profileCounted.${hash}`
function getDummyUpdateDirectory() {
  const testName = "test_ProfileCounter";
  let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
  dir.initWithPath(`C:\\foo\\bar\\${testName}`);
  return dir;
}

// We aren't going to bother generating anything looking like a real client ID
// for this. The only real requirements for client ids is that they not repeat
// and that they be strings. So we'll just return an integer as a string and
// increment it when we want a new client id.
var gDummyTelemetryClientId = 0;
function getDummyTelemetryClientId() {
  return gDummyTelemetryClientId.toString();
}
function setNewDummyTelemetryClientId() {
  ++gDummyTelemetryClientId;
}

// Returns null if the (fake) profile count file hasn't been created yet.
function getProfileCount() {
  // Strict equality to ensure distinguish properly between a non-existent
  // file and an empty one.
  if (gFakeProfileCounterFile === null) {
    return null;
  }
  let saveData = JSON.parse(gFakeProfileCounterFile);
  return saveData.profileTelemetryIds.length;
}

// Resets the state to the original state, before the profile count file has
// even been written.
// If resetFile is specified as false, this will reset everything except for the
// file itself. This allows us to sort of pretend that another installation
// wrote the file.
function reset(resetFile = true) {
  if (resetFile) {
    gFakeProfileCounterFile = null;
  }
  gNextReadExceptionReason = null;
  gNextWriteExceptionReason = null;
  setNewDummyTelemetryClientId();
}

function setup() {
  reset();
  // FOG needs a profile directory to put its data in.
  do_get_profile();
  // Initialize FOG so we can test the FOG version of profile count
  Services.fog.initializeFOG();
  Services.fog.testResetFOG();

  BrowserUsageTelemetry.Policy.readProfileCountFile = async path => {
    if (!gProfileCounterFilePath) {
      gProfileCounterFilePath = path;
    } else {
      // We've only got one mock-file variable. Make sure we are always
      // accessing the same file or this will cause problems.
      Assert.equal(
        gProfileCounterFilePath,
        path,
        "Only one file should be accessed"
      );
    }
    // Strict equality to ensure distinguish properly between null and 0.
    if (gNextReadExceptionReason !== null) {
      let ex = new DOMException(FILE_OPEN_OPERATION, gNextReadExceptionReason);
      gNextReadExceptionReason = null;
      throw ex;
    }
    // Strict equality to ensure distinguish properly between a non-existent
    // file and an empty one.
    if (gFakeProfileCounterFile === null) {
      throw new DOMException(FILE_OPEN_OPERATION, ERROR_FILE_NOT_FOUND);
    }
    return gFakeProfileCounterFile;
  };
  BrowserUsageTelemetry.Policy.writeProfileCountFile = async (path, data) => {
    if (!gProfileCounterFilePath) {
      gProfileCounterFilePath = path;
    } else {
      // We've only got one mock-file variable. Make sure we are always
      // accessing the same file or this will cause problems.
      Assert.equal(
        gProfileCounterFilePath,
        path,
        "Only one file should be accessed"
      );
    }
    // Strict equality to ensure distinguish properly between null and 0.
    if (gNextWriteExceptionReason !== null) {
      let ex = new DOMException(FILE_OPEN_OPERATION, gNextWriteExceptionReason);
      gNextWriteExceptionReason = null;
      throw ex;
    }
    gFakeProfileCounterFile = data;
  };
  BrowserUsageTelemetry.Policy.getUpdateDirectory = getDummyUpdateDirectory;
  BrowserUsageTelemetry.Policy.getTelemetryClientId = getDummyTelemetryClientId;
}

// Checks that the number of profiles reported is the number expected. Because
// of bucketing, the raw count may be different than the reported count.
function checkSuccess(profilesReported, rawCount = profilesReported) {
  Assert.equal(rawCount, getProfileCount());
  const scalars = TelemetryTestUtils.getProcessScalars("parent");
  TelemetryTestUtils.assertScalar(
    scalars,
    PROFILE_COUNT_SCALAR,
    profilesReported,
    "The value reported to telemetry should be the expected profile count"
  );
  Assert.equal(
    profilesReported,
    Glean.browserEngagement.profileCount.testGetValue()
  );
}

function checkError() {
  const scalars = TelemetryTestUtils.getProcessScalars("parent");
  TelemetryTestUtils.assertScalar(
    scalars,
    PROFILE_COUNT_SCALAR,
    SCALAR_ERROR_VALUE,
    "The value reported to telemetry should be the error value"
  );
}

add_task(async function testProfileCounter() {
  setup();

  info("Testing basic functionality, single install");
  await BrowserUsageTelemetry.reportProfileCount();
  checkSuccess(1);
  await BrowserUsageTelemetry.reportProfileCount();
  checkSuccess(1);

  // Fake another installation by resetting everything except for the profile
  // count file.
  reset(false);

  info("Testing basic functionality, faking a second install");
  await BrowserUsageTelemetry.reportProfileCount();
  checkSuccess(2);

  // Check if we properly handle the case where we cannot read from the file
  // and we have already set its contents. This should report an error.
  info("Testing read error after successful write");
  gNextReadExceptionReason = ERROR_ACCESS_DENIED;
  await BrowserUsageTelemetry.reportProfileCount();
  checkError();

  reset();

  // A read error should cause an error to be reported, but should also write
  // to the file in an attempt to fix it. So the next (successful) read should
  // result in the correct telemetry.
  info("Testing read error self-correction");
  gNextReadExceptionReason = ERROR_ACCESS_DENIED;
  await BrowserUsageTelemetry.reportProfileCount();
  checkError();

  await BrowserUsageTelemetry.reportProfileCount();
  checkSuccess(1);

  reset();

  // If the file is malformed. We should report an error and fix it, then report
  // the correct profile count next time.
  info("Testing with malformed profile count file");
  gFakeProfileCounterFile = "";
  await BrowserUsageTelemetry.reportProfileCount();
  checkError();

  await BrowserUsageTelemetry.reportProfileCount();
  checkSuccess(1);

  reset();

  // If we haven't yet written to the file, a write error should cause an error
  // to be reported.
  info("Testing write error before the first write");
  gNextWriteExceptionReason = ERROR_ACCESS_DENIED;
  await BrowserUsageTelemetry.reportProfileCount();
  checkError();

  reset();

  info("Testing bucketing");
  // Fake 15 installations to drive the raw profile count up to 15.
  for (let i = 0; i < 15; i++) {
    reset(false);
    await BrowserUsageTelemetry.reportProfileCount();
  }
  // With bucketing, values from 10-99 should all be reported as 10.
  checkSuccess(10, 15);
});

Messung V0.5
C=93 H=93 G=92

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge