Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/testing/mochitest/tests/SimpleTest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 34 kB image not shown  

Quelle  TestRunner.js   Sprache: JAVA

 
/* -*- js-indent-level: 4; indent-tabs-mode: nil -*- */
/*
 * e10s event dispatcher from content->chrome
 *
 * type = eventName (QuitApplication)
 * data = json object {"filename":filename} <- for LoggerInit
 */


// This file expects the following files to be loaded.
/* import-globals-from LogController.js */
/* import-globals-from MemoryStats.js */
/* import-globals-from MozillaLogger.js */

/* eslint-disable no-unsanitized/property */

"use strict";

const { StructuredLogger, StructuredFormatter } =
  SpecialPowers.ChromeUtils.importESModule(
    "resource://testing-common/StructuredLog.sys.mjs"
  );

function getElement(id) {
  return typeof id == "string" ? document.getElementById(id) : id;
}

this.$ = this.getElement;

function contentDispatchEvent(type, data, sync) {
  if (typeof data == "undefined") {
    data = {};
  }

  var event = new CustomEvent("contentEvent", {
    bubbles: true,
    detail: {
      sync,
      type,
      data: JSON.stringify(data),
    },
  });
  document.dispatchEvent(event);
}

function contentAsyncEvent(type, data) {
  contentDispatchEvent(type, data, 0);
}

/* Helper Function */
function extend(obj, /* optional */ skip) {
  // Extend an array with an array-like object starting
  // from the skip index
  if (!skip) {
    skip = 0;
  }
  if (obj) {
    var l = obj.length;
    var ret = [];
    for (var i = skip; i < l; i++) {
      ret.push(obj[i]);
    }
  }
  return ret;
}

function flattenArguments(/* ...*/) {
  var res = [];
  var args = extend(arguments);
  while (args.length) {
    var o = args.shift();
    if (o && typeof o == "object" && typeof o.length == "number") {
      for (var i = o.length - 1; i >= 0; i--) {
        args.unshift(o[i]);
      }
    } else {
      res.push(o);
    }
  }
  return res;
}

function testInXOriginFrame() {
  // Check if the test running in an iframe is a cross origin test.
  try {
    $("testframe").contentWindow.origin;
    return false;
  } catch (e) {
    return true;
  }
}

function testInDifferentProcess() {
  // Check if the test running in an iframe that is loaded in a different process.
  return SpecialPowers.Cu.isRemoteProxy($("testframe").contentWindow);
}

/**
 * TestRunner: A test runner for SimpleTest
 * TODO:
 *
 *  * Avoid moving iframes: That causes reloads on mozilla and opera.
 *
 *
 **/

var TestRunner = {};
TestRunner.logEnabled = false;
TestRunner._currentTest = 0;
TestRunner._lastTestFinished = -1;
TestRunner._loopIsRestarting = false;
TestRunner.currentTestURL = "";
TestRunner.originalTestURL = "";
TestRunner._urls = [];
TestRunner._lastAssertionCount = 0;
TestRunner._expectedMinAsserts = 0;
TestRunner._expectedMaxAsserts = 0;

TestRunner.timeout = 300 * 1000; // 5 minutes.
TestRunner.maxTimeouts = 4; // halt testing after too many timeouts
TestRunner.runSlower = false;
TestRunner.dumpOutputDirectory = "";
TestRunner.dumpAboutMemoryAfterTest = false;
TestRunner.dumpDMDAfterTest = false;
TestRunner.slowestTestTime = 0;
TestRunner.slowestTestURL = "";
TestRunner.interactiveDebugger = false;
TestRunner.cleanupCrashes = false;
TestRunner.timeoutAsPass = false;
TestRunner.conditionedProfile = false;
TestRunner.comparePrefs = false;

TestRunner._expectingProcessCrash = false;
TestRunner._structuredFormatter = new StructuredFormatter();

/**
 * Make sure the tests don't hang indefinitely.
 **/

TestRunner._numTimeouts = 0;
TestRunner._currentTestStartTime = new Date().valueOf();
TestRunner._timeoutFactor = 1;

/**
 * Used to collect code coverage with the js debugger.
 */

TestRunner.jscovDirPrefix = "";
var coverageCollector = {};

function record(succeeded, expectedFail, msg) {
  let successInfo;
  let failureInfo;
  if (expectedFail) {
    successInfo = {
      status: "PASS",
      expected: "FAIL",
      message: "TEST-UNEXPECTED-PASS",
    };
    failureInfo = {
      status: "FAIL",
      expected: "FAIL",
      message: "TEST-KNOWN-FAIL",
    };
  } else {
    successInfo = {
      status: "PASS",
      expected: "PASS",
      message: "TEST-PASS",
    };
    failureInfo = {
      status: "FAIL",
      expected: "PASS",
      message: "TEST-UNEXPECTED-FAIL",
    };
  }

  let result = succeeded ? successInfo : failureInfo;

  TestRunner.structuredLogger.testStatus(
    TestRunner.currentTestURL,
    msg,
    result.status,
    result.expected,
    "",
    ""
  );
}

TestRunner._checkForHangs = function () {
  function reportError(win, msg) {
    if (testInXOriginFrame() || "SimpleTest" in win) {
      record(false, TestRunner.timeoutAsPass, msg);
    } else if ("W3CTest" in win) {
      win.W3CTest.logFailure(msg);
    }
  }

  async function killTest(win) {
    if (testInXOriginFrame()) {
      win.postMessage("SimpleTest:timeout""*");
    } else if ("SimpleTest" in win) {
      await win.SimpleTest.timeout();
      win.SimpleTest.finish();
    } else if ("W3CTest" in win) {
      await win.W3CTest.timeout();
    }
  }

  if (TestRunner._currentTest < TestRunner._urls.length) {
    var runtime = new Date().valueOf() - TestRunner._currentTestStartTime;
    if (
      !TestRunner.interactiveDebugger &&
      runtime >= TestRunner.timeout * TestRunner._timeoutFactor
    ) {
      let testIframe = $("testframe");
      var frameWindow =
        (!testInXOriginFrame() && testIframe.contentWindow.wrappedJSObject) ||
        testIframe.contentWindow;
      reportError(frameWindow, "Test timed out.");
      TestRunner.updateUI([{ result: false }]);

      // If we have too many timeouts, give up. We don't want to wait hours
      // for results if some bug causes lots of tests to time out.
      if (
        ++TestRunner._numTimeouts >= TestRunner.maxTimeouts ||
        TestRunner.runUntilFailure
      ) {
        TestRunner._haltTests = true;

        TestRunner.currentTestURL = "(SimpleTest/TestRunner.js)";
        reportError(
          frameWindow,
          TestRunner.maxTimeouts + " test timeouts, giving up."
        );
        var skippedTests = TestRunner._urls.length - TestRunner._currentTest;
        reportError(
          frameWindow,
          "Skipping " + skippedTests + " remaining tests."
        );
      }

      // Add a little (1 second) delay to ensure automation.py has time to notice
      // "Test timed out" log and process it (= take a screenshot).
      setTimeout(async function delayedKillTest() {
        try {
          await killTest(frameWindow);
        } catch (e) {
          reportError(frameWindow, "Test error: " + e);
          TestRunner.updateUI([{ result: false }]);
        }
      }, 1000);

      if (TestRunner._haltTests) {
        return;
      }
    }

    setTimeout(TestRunner._checkForHangs, 30000);
  }
};

TestRunner.requestLongerTimeout = function (factor) {
  TestRunner._timeoutFactor = factor;
};

/**
 * This is used to loop tests
 **/

TestRunner.repeat = 0;
TestRunner._currentLoop = 1;

TestRunner.expectAssertions = function (min, max) {
  if (typeof max == "undefined") {
    max = min;
  }
  if (
    typeof min != "number" ||
    typeof max != "number" ||
    min < 0 ||
    max < min
  ) {
    throw new Error("bad parameter to expectAssertions");
  }
  TestRunner._expectedMinAsserts = min;
  TestRunner._expectedMaxAsserts = max;
};

/**
 * This function is called after generating the summary.
 **/

TestRunner.onComplete = null;

/**
 * Adds a failed test case to a list so we can rerun only the failed tests
 **/

TestRunner._failedTests = {};
TestRunner._failureFile = "";

TestRunner.addFailedTest = function (testName) {
  if (TestRunner._failedTests[testName] == undefined) {
    TestRunner._failedTests[testName] = "";
  }
};

TestRunner.setFailureFile = function (fileName) {
  TestRunner._failureFile = fileName;
};

TestRunner.generateFailureList = function () {
  if (TestRunner._failureFile) {
    var failures = new MozillaFileLogger(TestRunner._failureFile);
    failures.log(JSON.stringify(TestRunner._failedTests));
    failures.close();
  }
};

/**
 * If logEnabled is true, this is the logger that will be used.
 **/


// This delimiter is used to avoid interleaving Mochitest/Gecko logs.
var LOG_DELIMITER = "\ue175\uee31\u2c32\uacbf";

// A log callback for StructuredLog.sys.mjs
TestRunner._dumpMessage = function (message) {
  var str;

  // This is a directive to python to format these messages
  // for compatibility with mozharness. This can be removed
  // with the MochitestFormatter (see bug 1045525).
  message.js_source = "TestRunner.js";
  if (
    TestRunner.interactiveDebugger &&
    message.action in TestRunner._structuredFormatter
  ) {
    str = TestRunner._structuredFormatter[message.action](message);
  } else {
    str = LOG_DELIMITER + JSON.stringify(message) + LOG_DELIMITER;
  }
  // BUGFIX: browser-chrome tests don't use LogController
  if (Object.keys(LogController.listeners).length !== 0) {
    LogController.log(str);
  } else {
    dump("\n" + str + "\n");
  }
  // Checking for error messages
  if (message.expected || message.level === "ERROR") {
    TestRunner.failureHandler();
  }
};

// From https://searchfox.org/mozilla-central/source/testing/modules/StructuredLog.sys.mjs
TestRunner.structuredLogger = new StructuredLogger(
  "mochitest",
  TestRunner._dumpMessage,
  [],
  TestRunner
);
TestRunner.structuredLogger.deactivateBuffering = function () {
  TestRunner.structuredLogger.logData("buffering_off");
};
TestRunner.structuredLogger.activateBuffering = function () {
  TestRunner.structuredLogger.logData("buffering_on");
};

TestRunner.log = function (msg) {
  if (TestRunner.logEnabled) {
    TestRunner.structuredLogger.info(msg);
  } else {
    dump(msg + "\n");
  }
};

TestRunner.error = function (msg) {
  if (TestRunner.logEnabled) {
    TestRunner.structuredLogger.error(msg);
  } else {
    dump(msg + "\n");
    TestRunner.failureHandler();
  }
};

TestRunner.failureHandler = function () {
  if (TestRunner.runUntilFailure) {
    TestRunner._haltTests = true;
  }

  if (TestRunner.debugOnFailure) {
    // You've hit this line because you requested to break into the
    // debugger upon a testcase failure on your test run.
    // eslint-disable-next-line no-debugger
    debugger;
  }
};

/**
 * Toggle element visibility
 **/

TestRunner._toggle = function (el) {
  if (el.className == "noshow") {
    el.className = "";
    el.style.cssText = "";
  } else {
    el.className = "noshow";
    el.style.cssText = "width:0px; height:0px; border:0px;";
  }
};

/**
 * Creates the iframe that contains a test
 **/

TestRunner._makeIframe = function (url, retry) {
  var iframe = $("testframe");
  if (
    url != "about:blank" &&
    (("hasFocus" in document && !document.hasFocus()) ||
      ("activeElement" in document && document.activeElement != iframe))
  ) {
    contentAsyncEvent("Focus");
    window.focus();
    SpecialPowers.focus();
    iframe.focus();
    if (retry < 3) {
      window.setTimeout(function () {
        TestRunner._makeIframe(url, retry + 1);
      }, 1000);
      return;
    }

    TestRunner.structuredLogger.info(
      "Error: Unable to restore focus, expect failures and timeouts."
    );
  }
  window.scrollTo(0, $("indicator").offsetTop);
  try {
    let urlObj = new URL(url);
    if (TestRunner.xOriginTests) {
      // The test will run in a xorigin iframe, so we pass in additional test params in the
      // URL since the content process won't be able to access them from the parentRunner
      // directly.
      let params = TestRunner.getParameterInfo();
      urlObj.searchParams.append(
        "currentTestURL",
        urlObj.pathname.replace("/tests/""")
      );
      urlObj.searchParams.append("closeWhenDone", params.closeWhenDone);
      urlObj.searchParams.append("showTestReport", TestRunner.showTestReport);
      urlObj.searchParams.append("expected", TestRunner.expected);
      iframe.src = urlObj.href;
    } else {
      iframe.src = url;
    }
  } catch {
    // If the provided `url` is not a valid URL (i.e. doesn't include a protocol)
    // then the new URL() constructor will raise a TypeError. This is expected in the
    // usual case (i.e. non-xorigin iFrame tests) so set the URL in the usual way.
    iframe.src = url;
  }
  iframe.name = url;
  iframe.width = "500";
};

/**
 * Returns the current test URL.
 * We use this to tell whether the test has navigated to another test without
 * being finished first.
 */

TestRunner.getLoadedTestURL = function () {
  if (!testInXOriginFrame()) {
    var prefix = "";
    // handle mochitest-chrome URIs
    if ($("testframe").contentWindow.location.protocol == "chrome:") {
      prefix = "chrome://mochitests";
    }
    return prefix + $("testframe").contentWindow.location.pathname;
  }
  return TestRunner.currentTestURL;
};

TestRunner.setParameterInfo = function (params) {
  this._params = params;
};

TestRunner.getParameterInfo = function () {
  return this._params;
};

/**
 * Print information about which prefs are set.
 * This is used to help validate that the tests are actually
 * running in the expected context.
 */

TestRunner.dumpPrefContext = function () {
  let prefs = ["fission.autostart"];

  let message = ["Dumping test context:"];
  prefs.forEach(function formatPref(pref) {
    let val = SpecialPowers.getBoolPref(pref);
    message.push(pref + "=" + val);
  });
  TestRunner.structuredLogger.info(message.join("\n "));
};

/**
 * TestRunner entry point.
 *
 * The arguments are the URLs of the test to be ran.
 *
 **/

TestRunner.runTests = function (/*url...*/) {
  TestRunner.structuredLogger.info("SimpleTest START");
  TestRunner.dumpPrefContext();
  TestRunner.originalTestURL = $("current-test").innerHTML;

  SpecialPowers.registerProcessCrashObservers();

  // Initialize code coverage
  if (TestRunner.jscovDirPrefix != "") {
    var { CoverageCollector } = SpecialPowers.ChromeUtils.importESModule(
      "resource://testing-common/CoverageUtils.sys.mjs"
    );
    coverageCollector = new CoverageCollector(TestRunner.jscovDirPrefix);
  }

  SpecialPowers.requestResetCoverageCounters().then(() => {
    TestRunner._urls = flattenArguments(arguments);

    var singleTestRun = this._urls.length <= 1 && TestRunner.repeat <= 1;
    TestRunner.showTestReport = singleTestRun;
    var frame = $("testframe");
    frame.src = "";
    if (singleTestRun) {
      // Can't use document.body because this runs in a XUL doc as well...
      var body = document.getElementsByTagName("body")[0];
      body.setAttribute("singletest""true");
      frame.removeAttribute("scrolling");
    }
    TestRunner._checkForHangs();
    TestRunner.runNextTest();
  });
};

/**
 * Used for running a set of tests in a loop for debugging purposes
 * Takes an array of URLs
 **/

TestRunner.resetTests = function (listURLs) {
  TestRunner._currentTest = 0;
  // Reset our "Current-test" line - functionality depends on it
  $("current-test").innerHTML = TestRunner.originalTestURL;
  if (TestRunner.logEnabled) {
    TestRunner.structuredLogger.info(
      "SimpleTest START Loop " + TestRunner._currentLoop
    );
  }

  TestRunner._urls = listURLs;
  $("testframe").src = "";
  TestRunner._checkForHangs();
  TestRunner.runNextTest();
};

TestRunner.getNextUrl = function () {
  var url = "";
  // sometimes we have a subtest/harness which doesn't use a manifest
  if (
    TestRunner._urls[TestRunner._currentTest] instanceof Object &&
    "test" in TestRunner._urls[TestRunner._currentTest]
  ) {
    url = TestRunner._urls[TestRunner._currentTest].test.url;
    TestRunner.expected =
      TestRunner._urls[TestRunner._currentTest].test.expected;
  } else {
    url = TestRunner._urls[TestRunner._currentTest];
    TestRunner.expected = "pass";
  }
  return url;
};

/**
 * Run the next test. If no test remains, calls onComplete().
 **/

TestRunner._haltTests = false;
async function _runNextTest() {
  if (
    TestRunner._currentTest < TestRunner._urls.length &&
    !TestRunner._haltTests
  ) {
    var url = TestRunner.getNextUrl();
    TestRunner.currentTestURL = url;

    $("current-test-path").innerHTML = url;

    TestRunner._currentTestStartTimestamp = SpecialPowers.Cu.now();
    TestRunner._currentTestStartTime = new Date().valueOf();
    TestRunner._timeoutFactor = 1;
    TestRunner._expectedMinAsserts = 0;
    TestRunner._expectedMaxAsserts = 0;

    TestRunner.structuredLogger.testStart(url);

    if (TestRunner._urls[TestRunner._currentTest].test.allow_xul_xbl) {
      await SpecialPowers.pushPermissions([
        { type: "allowXULXBL", allow: true, context: "http://mochi.test:8888" },
        { type: "allowXULXBL", allow: true, context: "http://example.org" },
      ]);
    }
    if (TestRunner._urls[TestRunner._currentTest].test.https_first_disabled) {
      await SpecialPowers.pushPrefEnv({
        set: [["dom.security.https_first"false]],
      });
    }
    TestRunner._makeIframe(url, 0);
  } else {
    $("current-test").innerHTML = "Finished";
    // Only unload the last test to run if we're running more than one test.
    if (TestRunner._urls.length > 1) {
      TestRunner._makeIframe("about:blank", 0);
    }

    var passCount = parseInt($("pass-count").innerHTML, 10);
    var failCount = parseInt($("fail-count").innerHTML, 10);
    var todoCount = parseInt($("todo-count").innerHTML, 10);

    if (passCount === 0 && failCount === 0 && todoCount === 0) {
      // No |$('testframe').contentWindow|, so manually update: ...
      // ... the log,
      TestRunner.structuredLogger.error(
        "TEST-UNEXPECTED-FAIL | SimpleTest/TestRunner.js | No checks actually run"
      );
      // ... the count,
      $("fail-count").innerHTML = 1;
      // ... the indicator.
      var indicator = $("indicator");
      indicator.innerHTML = "Status: Fail (No checks actually run)";
      indicator.style.backgroundColor = "red";
    }

    let e10sMode = SpecialPowers.isMainProcess() ? "non-e10s" : "e10s";

    TestRunner.structuredLogger.info("TEST-START | Shutdown");
    TestRunner.structuredLogger.info("Passed: " + passCount);
    TestRunner.structuredLogger.info("Failed: " + failCount);
    TestRunner.structuredLogger.info("Todo: " + todoCount);
    TestRunner.structuredLogger.info("Mode: " + e10sMode);
    TestRunner.structuredLogger.info(
      "Slowest: " +
        TestRunner.slowestTestTime +
        "ms - " +
        TestRunner.slowestTestURL
    );

    // If we are looping, don't send this cause it closes the log file,
    // also don't unregister the crash observers until we're done.
    if (TestRunner.repeat === 0) {
      SpecialPowers.unregisterProcessCrashObservers();
      TestRunner.structuredLogger.info("SimpleTest FINISHED");
    }

    if (TestRunner.repeat === 0 && TestRunner.onComplete) {
      TestRunner.onComplete();
    }

    if (
      TestRunner._currentLoop <= TestRunner.repeat &&
      !TestRunner._haltTests
    ) {
      TestRunner._currentLoop++;
      TestRunner.resetTests(TestRunner._urls);
      TestRunner._loopIsRestarting = true;
    } else {
      // Loops are finished
      if (TestRunner.logEnabled) {
        TestRunner.structuredLogger.info(
          "TEST-INFO | Ran " + TestRunner._currentLoop + " Loops"
        );
        TestRunner.structuredLogger.info("SimpleTest FINISHED");
      }

      if (TestRunner.onComplete) {
        TestRunner.onComplete();
      }
    }
    TestRunner.generateFailureList();

    if (TestRunner.jscovDirPrefix != "") {
      coverageCollector.finalize();
    }
  }
}
TestRunner.runNextTest = _runNextTest;

TestRunner.expectChildProcessCrash = function () {
  TestRunner._expectingProcessCrash = true;
};

/**
 * This stub is called by SimpleTest when a test is finished.
 **/

TestRunner.testFinished = function (tests) {
  // Need to track subtests recorded here separately or else they'll
  // trigger the `result after SimpleTest.finish()` error.
  var extraTests = [];
  var result = "OK";

  // Prevent a test from calling finish() multiple times before we
  // have a chance to unload it.
  if (
    TestRunner._currentTest == TestRunner._lastTestFinished &&
    !TestRunner._loopIsRestarting
  ) {
    TestRunner.structuredLogger.testEnd(
      TestRunner.currentTestURL,
      "ERROR",
      "OK",
      "called finish() multiple times"
    );
    TestRunner.updateUI([{ result: false }]);
    return;
  }

  if (TestRunner.jscovDirPrefix != "") {
    coverageCollector.recordTestCoverage(TestRunner.currentTestURL);
  }

  SpecialPowers.requestDumpCoverageCounters().then(() => {
    TestRunner._lastTestFinished = TestRunner._currentTest;
    TestRunner._loopIsRestarting = false;

    // TODO : replace this by a function that returns the mem data as an object
    // that's dumped later with the test_end message
    MemoryStats.dump(
      TestRunner._currentTest,
      TestRunner.currentTestURL,
      TestRunner.dumpOutputDirectory,
      TestRunner.dumpAboutMemoryAfterTest,
      TestRunner.dumpDMDAfterTest
    );

    async function cleanUpCrashDumpFiles() {
      if (
        !(await SpecialPowers.removeExpectedCrashDumpFiles(
          TestRunner._expectingProcessCrash
        ))
      ) {
        let subtest = "expected-crash-dump-missing";
        TestRunner.structuredLogger.testStatus(
          TestRunner.currentTestURL,
          subtest,
          "ERROR",
          "PASS",
          "This test did not leave any crash dumps behind, but we were expecting some!"
        );
        extraTests.push({ name: subtest, result: false });
        result = "ERROR";
      }

      var unexpectedCrashDumpFiles =
        await SpecialPowers.findUnexpectedCrashDumpFiles();
      TestRunner._expectingProcessCrash = false;
      if (unexpectedCrashDumpFiles.length) {
        let subtest = "unexpected-crash-dump-found";
        TestRunner.structuredLogger.testStatus(
          TestRunner.currentTestURL,
          subtest,
          "ERROR",
          "PASS",
          "This test left crash dumps behind, but we " +
            "weren't expecting it to!",
          null,
          { unexpected_crashdump_files: unexpectedCrashDumpFiles }
        );
        extraTests.push({ name: subtest, result: false });
        result = "CRASH";
        unexpectedCrashDumpFiles.sort().forEach(function (aFilename) {
          TestRunner.structuredLogger.info(
            "Found unexpected crash dump file " + aFilename + "."
          );
        });
      }

      if (TestRunner.cleanupCrashes) {
        if (await SpecialPowers.removePendingCrashDumpFiles()) {
          TestRunner.structuredLogger.info(
            "This test left pending crash dumps"
          );
        }
      }
    }

    function runNextTest() {
      if (TestRunner.currentTestURL != TestRunner.getLoadedTestURL()) {
        TestRunner.structuredLogger.testStatus(
          TestRunner.currentTestURL,
          TestRunner.getLoadedTestURL(),
          "FAIL",
          "PASS",
          "finished in a non-clean fashion, probably" +
            " because it didn't call SimpleTest.finish()",
          { loaded_test_url: TestRunner.getLoadedTestURL() }
        );
        extraTests.push({ name: "clean-finish", result: false });
        result = result != "CRASH" ? "ERROR" : result;
      }

      SpecialPowers.addProfilerMarker(
        "TestRunner",
        { category: "Test", startTime: TestRunner._currentTestStartTimestamp },
        TestRunner.currentTestURL
      );
      var runtime = new Date().valueOf() - TestRunner._currentTestStartTime;

      if (
        TestRunner.slowestTestTime < runtime &&
        TestRunner._timeoutFactor >= 1
      ) {
        TestRunner.slowestTestTime = runtime;
        TestRunner.slowestTestURL = TestRunner.currentTestURL;
      }

      TestRunner.updateUI(tests.concat(extraTests));

      // Don't show the interstitial if we just run one test with no repeats:
      if (TestRunner._urls.length == 1 && TestRunner.repeat <= 1) {
        TestRunner.testUnloaded(result, runtime);
        return;
      }

      var interstitialURL;
      if (
        !testInXOriginFrame() &&
        $("testframe").contentWindow.location.protocol == "chrome:"
      ) {
        interstitialURL =
          "tests/SimpleTest/iframe-between-tests.html?result=" +
          result +
          "&runtime=" +
          runtime;
      } else {
        interstitialURL =
          "/tests/SimpleTest/iframe-between-tests.html?result=" +
          result +
          "&runtime=" +
          runtime;
      }
      // check if there were test run after SimpleTest.finish, which should never happen
      if (!testInXOriginFrame()) {
        $("testframe").contentWindow.addEventListener("unload"function () {
          var testwin = $("testframe").contentWindow;
          if (testwin.SimpleTest) {
            if (typeof testwin.SimpleTest.testsLength === "undefined") {
              TestRunner.structuredLogger.error(
                "TEST-UNEXPECTED-FAIL | " +
                  TestRunner.currentTestURL +
                  " fired an unload callback with missing test data," +
                  " possibly due to the test navigating or reloading"
              );
              TestRunner.updateUI([{ result: false }]);
            } else if (
              testwin.SimpleTest._tests.length != testwin.SimpleTest.testsLength
            ) {
              var didReportError = false;
              var wrongtestlength =
                testwin.SimpleTest._tests.length -
                testwin.SimpleTest.testsLength;
              var wrongtestname = "";
              for (var i = 0; i < wrongtestlength; i++) {
                wrongtestname =
                  testwin.SimpleTest._tests[testwin.SimpleTest.testsLength + i]
                    .name;
                TestRunner.structuredLogger.error(
                  "TEST-UNEXPECTED-FAIL | " +
                    TestRunner.currentTestURL +
                    " logged result after SimpleTest.finish(): " +
                    wrongtestname
                );
                didReportError = true;
              }
              if (!didReportError) {
                // This clause shouldn't be reachable, but if we somehow get
                // here (e.g. if wrongtestlength is somehow negative), it's
                // important that we log *something* for the { result: false }
                // test-failure that we're about to post.
                TestRunner.structuredLogger.error(
                  "TEST-UNEXPECTED-FAIL | " +
                    TestRunner.currentTestURL +
                    " hit an unexpected condition when checking for" +
                    " logged results after SimpleTest.finish()"
                );
              }
              TestRunner.updateUI([{ result: false }]);
            }
          }
        });
      }
      TestRunner._makeIframe(interstitialURL, 0);
    }

    SpecialPowers.executeAfterFlushingMessageQueue(async function () {
      await SpecialPowers.waitForCrashes(TestRunner._expectingProcessCrash);
      await cleanUpCrashDumpFiles();
      await SpecialPowers.flushPermissions();
      await SpecialPowers.flushPrefEnv();
      SpecialPowers.cleanupAllClipboard(window);
      runNextTest();
    });
  });
};

/**
 * This stub is called by XOrigin Tests to report assertion count.
 **/

TestRunner._xoriginAssertionCount = 0;
TestRunner.addAssertionCount = function (count) {
  if (!testInXOriginFrame()) {
    TestRunner.error(
      `addAssertionCount should only be called by a cross origin test`
    );
    return;
  }

  if (testInDifferentProcess()) {
    TestRunner._xoriginAssertionCount += count;
  }
};

TestRunner.testUnloaded = function (result, runtime) {
  // If we're in a debug build, check assertion counts.  This code is
  // similar to the code in Tester_nextTest in browser-test.js used
  // for browser-chrome mochitests.
  if (SpecialPowers.isDebugBuild) {
    var newAssertionCount =
      SpecialPowers.assertionCount() + TestRunner._xoriginAssertionCount;
    var numAsserts = newAssertionCount - TestRunner._lastAssertionCount;
    TestRunner._lastAssertionCount = newAssertionCount;

    var max = TestRunner._expectedMaxAsserts;
    var min = TestRunner._expectedMinAsserts;
    if (Array.isArray(TestRunner.expected)) {
      // Accumulate all assertion counts recorded in the failure pattern file.
      let additionalAsserts = TestRunner.expected.reduce(
        (acc, [pat, count]) => {
          return pat == "ASSERTION" ? acc + count : acc;
        },
        0
      );
      min += additionalAsserts;
      max += additionalAsserts;
    }

    TestRunner.structuredLogger.assertionCount(
      TestRunner.currentTestURL,
      numAsserts,
      min,
      max
    );

    if (numAsserts < min || numAsserts > max) {
      result = "ERROR";

      var direction = "more";
      var target = max;
      if (numAsserts < min) {
        direction = "less";
        target = min;
      }
      TestRunner.structuredLogger.testStatus(
        TestRunner.currentTestURL,
        "Assertion Count",
        "ERROR",
        "PASS",
        numAsserts +
          " is " +
          direction +
          " than expected " +
          target +
          " assertions"
      );

      // reset result so we don't print a second error on test-end
      result = "OK";
    }
  }

  TestRunner.structuredLogger.testEnd(
    TestRunner.currentTestURL,
    result,
    "OK",
    "Finished in " + runtime + "ms",
    { runtime }
  );

  // Always do this, so we can "reset" preferences between tests
  SpecialPowers.comparePrefsToBaseline(
    TestRunner.ignorePrefs,
    TestRunner.verifyPrefsNextTest
  );
};

TestRunner.verifyPrefsNextTest = function (p) {
  if (TestRunner.comparePrefs) {
    let prefs = Array.from(SpecialPowers.Cu.waiveXrays(p), x =>
      SpecialPowers.unwrapIfWrapped(SpecialPowers.Cu.unwaiveXrays(x))
    );
    prefs.forEach(pr =>
      TestRunner.structuredLogger.error(
        "TEST-UNEXPECTED-FAIL | " +
          TestRunner.currentTestURL +
          " | changed preference: " +
          pr
      )
    );
  }
  TestRunner.doNextTest();
};

TestRunner.doNextTest = function () {
  TestRunner._currentTest++;
  if (TestRunner.runSlower) {
    setTimeout(TestRunner.runNextTest, 1000);
  } else {
    TestRunner.runNextTest();
  }
};

/**
 * Get the results.
 */

TestRunner.countResults = function (tests) {
  var nOK = 0;
  var nNotOK = 0;
  var nTodo = 0;
  for (var i = 0; i < tests.length; ++i) {
    var test = tests[i];
    if (test.todo && !test.result) {
      nTodo++;
    } else if (test.result && !test.todo) {
      nOK++;
    } else {
      nNotOK++;
    }
  }
  return { OK: nOK, notOK: nNotOK, todo: nTodo };
};

/**
 * Print out table of any error messages found during looped run
 */

TestRunner.displayLoopErrors = function (tableName, tests) {
  if (TestRunner.countResults(tests).notOK > 0) {
    var table = $(tableName);
    var curtest;
    if (!table.rows.length) {
      //if table headers are not yet generated, make them
      var row = table.insertRow(table.rows.length);
      var cell = row.insertCell(0);
      var textNode = document.createTextNode("Test File Name:");
      cell.appendChild(textNode);
      cell = row.insertCell(1);
      textNode = document.createTextNode("Test:");
      cell.appendChild(textNode);
      cell = row.insertCell(2);
      textNode = document.createTextNode("Error message:");
      cell.appendChild(textNode);
    }

    //find the broken test
    for (var testnum in tests) {
      curtest = tests[testnum];
      if (
        !(
          (curtest.todo && !curtest.result) ||
          (curtest.result && !curtest.todo)
        )
      ) {
        //this is a failed test or the result of todo test. Display the related message
        row = table.insertRow(table.rows.length);
        cell = row.insertCell(0);
        textNode = document.createTextNode(TestRunner.currentTestURL);
        cell.appendChild(textNode);
        cell = row.insertCell(1);
        textNode = document.createTextNode(curtest.name);
        cell.appendChild(textNode);
        cell = row.insertCell(2);
        textNode = document.createTextNode(curtest.diag ? curtest.diag : "");
        cell.appendChild(textNode);
      }
    }
  }
};

TestRunner.updateUI = function (tests) {
  var results = TestRunner.countResults(tests);
  var passCount = parseInt($("pass-count").innerHTML) + results.OK;
  var failCount = parseInt($("fail-count").innerHTML) + results.notOK;
  var todoCount = parseInt($("todo-count").innerHTML) + results.todo;
  $("pass-count").innerHTML = passCount;
  $("fail-count").innerHTML = failCount;
  $("todo-count").innerHTML = todoCount;

  // Set the top Green/Red bar
  var indicator = $("indicator");
  if (failCount > 0) {
    indicator.innerHTML = "Status: Fail";
    indicator.style.backgroundColor = "red";
  } else if (passCount > 0) {
    indicator.innerHTML = "Status: Pass";
    indicator.style.backgroundColor = "#0d0";
  } else {
    indicator.innerHTML = "Status: ToDo";
    indicator.style.backgroundColor = "orange";
  }

  // Set the table values
  var trID = "tr-" + $("current-test-path").innerHTML;
  var row = $(trID);

  // Only update the row if it actually exists (autoUI)
  if (row != null) {
    var tds = row.getElementsByTagName("td");
    tds[0].style.backgroundColor = "#0d0";
    tds[0].innerHTML = parseInt(tds[0].innerHTML) + parseInt(results.OK);
    tds[1].style.backgroundColor = results.notOK > 0 ? "red" : "#0d0";
    tds[1].innerHTML = parseInt(tds[1].innerHTML) + parseInt(results.notOK);
    tds[2].style.backgroundColor = results.todo > 0 ? "orange" : "#0d0";
    tds[2].innerHTML = parseInt(tds[2].innerHTML) + parseInt(results.todo);
  }

  //if we ran in a loop, display any found errors
  if (TestRunner.repeat > 0) {
    TestRunner.displayLoopErrors("fail-table", tests);
  }
};

// XOrigin Tests
// If "--enable-xorigin-tests" is set, mochitests are run in a cross origin iframe.
// The parent process will run at http://mochi.xorigin-test:8888", and individual
// mochitests will be launched in a cross-origin iframe at http://mochi.test:8888.

var xOriginDispatchMap = {
  runner: TestRunner,
  logger: TestRunner.structuredLogger,
  addFailedTest: TestRunner.addFailedTest,
  expectAssertions: TestRunner.expectAssertions,
  expectChildProcessCrash: TestRunner.expectChildProcessCrash,
  requestLongerTimeout: TestRunner.requestLongerTimeout,
  "structuredLogger.deactivateBuffering":
    TestRunner.structuredLogger.deactivateBuffering,
  "structuredLogger.activateBuffering":
    TestRunner.structuredLogger.activateBuffering,
  "structuredLogger.testStatus": TestRunner.structuredLogger.testStatus,
  "structuredLogger.info": TestRunner.structuredLogger.info,
  "structuredLogger.warning": TestRunner.structuredLogger.warning,
  "structuredLogger.error": TestRunner.structuredLogger.error,
  testFinished: TestRunner.testFinished,
  addAssertionCount: TestRunner.addAssertionCount,
};

function xOriginTestRunnerHandler(event) {
  if (event.data.harnessType != "SimpleTest") {
    return;
  }
  // Handles messages from xOriginRunner in SimpleTest.js.
  if (event.data.command in xOriginDispatchMap) {
    xOriginDispatchMap[event.data.command].apply(
      xOriginDispatchMap[event.data.applyOn],
      event.data.params
    );
  } else {
    TestRunner.error(`Command ${event.data.command} not found
      in xOriginDispatchMap`);
  }
}

TestRunner.setXOriginEventHandler = function () {
  window.addEventListener("message", xOriginTestRunnerHandler);
};

Messung V0.5
C=92 H=97 G=94

¤ Dauer der Verarbeitung: 0.16 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.