Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/netwerk/test/unit/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 18 kB image not shown  

Quelle  http3_common.js   Sprache: JAVA

 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


"use strict";

/* import-globals-from head_cache.js */
/* import-globals-from head_cookies.js */
/* import-globals-from head_channels.js */
/* import-globals-from head_http3.js */

function makeChan(uri) {
  let chan = NetUtil.newChannel({
    uri,
    loadUsingSystemPrincipal: true,
  }).QueryInterface(Ci.nsIHttpChannel);
  chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
  return chan;
}

// Promise-backed Http3CheckListener
class Http3CheckListener {
  constructor(
    { expectedStatus = Cr.NS_OK, expectedRoute = "" } = {},
    resolve,
    reject
  ) {
    this.onDataAvailableFired = false;
    this.expectedStatus = expectedStatus;
    this.expectedRoute = expectedRoute;
    this._resolve = resolve;
    this._reject = reject;
  }

  onStartRequest(request) {
    Assert.ok(request instanceof Ci.nsIHttpChannel);
    Assert.equal(request.status, this.expectedStatus);
    if (Components.isSuccessCode(this.expectedStatus)) {
      Assert.equal(request.responseStatus, 200);
    }
  }

  onDataAvailable(request, stream, off, cnt) {
    this.onDataAvailableFired = true;
    read_stream(stream, cnt);
  }

  onStopRequest(request, status) {
    Assert.equal(status, this.expectedStatus);

    let routed = "NA";
    try {
      routed = request.getRequestHeader("Alt-Used");
    } catch (e) {}
    dump("routed is " + routed + "\n");

    Assert.equal(routed, this.expectedRoute);

    if (Components.isSuccessCode(this.expectedStatus)) {
      let httpVersion = "";
      try {
        httpVersion = request.protocolVersion;
      } catch (e) {}
      Assert.equal(httpVersion, "h3");
      Assert.equal(this.onDataAvailableFired, true);
      Assert.equal(request.getResponseHeader("X-Firefox-Http3"), "h3");
    }

    this._resolve?.(request);
  }
}

class WaitForHttp3Listener extends Http3CheckListener {
  constructor(
    {
      expectedStatus = Cr.NS_OK,
      expectedRoute = "",
      uri = "",
      h3AltSvc = "",
      retry,
      delayMs = 500,
    } = {},
    resolve,
    reject
  ) {
    super({ expectedStatus, expectedRoute }, resolve, reject);
    this.uri = uri;
    this.h3AltSvc = h3AltSvc;
    this._retry = retry; // function to re-open the request
    this._delayMs = delayMs; // poll interval
  }

  onStopRequest(request, status) {
    Assert.equal(status, this.expectedStatus);

    let routed = "NA";
    try {
      routed = request.getRequestHeader("Alt-Used");
    } catch (e) {}
    dump(`routed is ${routed}\n`);

    let httpVersion = "";
    try {
      httpVersion = request.protocolVersion;
    } catch (e) {}

    if (routed === this.expectedRoute) {
      // (This is where run_next_test() used to be.)
      Assert.equal(routed, this.expectedRoute); // useful log/assert
      Assert.equal(httpVersion, "h3");
      this._resolve?.(request);
      return;
    }

    // Not routed yet: mirror old behavior (log + supportsHTTP3 check + retry)
    dump("poll later for alt-svc mapping\n");
    if (httpVersion === "h2") {
      request.QueryInterface(Ci.nsIHttpChannelInternal);
      Assert.ok(request.supportsHTTP3);
    }

    if (typeof this._retry === "function") {
      // schedule another attempt (replaces do_test_pending/do_timeout recursion)
      do_timeout(this._delayMs, () =>
        this._retry(this.uri, this.expectedRoute, this.h3AltSvc)
      );
    }
    // Promise remains pending until a later attempt matches expectedRoute.
  }
}

// Factory to create { listener, promise }
function createHttp3CheckListener(options = {}) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new Http3CheckListener(options, resolve, reject);
  return { listener, promise };
}

function createWaitForHttp3Listener(options = {}) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new WaitForHttp3Listener(options, resolve, reject);
  return { listener, promise };
}

// --- Async wrapper that does the polling by re-issuing the request ---
async function waitForHttp3Route(
  uri,
  expectedRoute,
  altSvc,
  { delayMs = 500 } = {}
) {
  let listenerRef;

  let firstAttempt = true;
  // Function to (re)open the channel using the same listener instance.
  const retry = () => {
    if (!firstAttempt) {
      // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
      do_timeout(1000, () => {
        Services.obs.notifyObservers(null, "net:cancel-all-connections");
        const chan = makeChan(uri);
        if (altSvc) {
          chan.setRequestHeader("x-altsvc", altSvc, false);
        }
        chan.asyncOpen(listenerRef);
      });
      return;
    }
    firstAttempt = false;
    const chan = makeChan(uri);
    if (altSvc) {
      chan.setRequestHeader("x-altsvc", altSvc, false);
    }
    chan.asyncOpen(listenerRef);
  };

  const { listener, promise } = createWaitForHttp3Listener({
    expectedStatus: Cr.NS_OK,
    expectedRoute,
    uri,
    h3AltSvc: altSvc,
    retry,
    delayMs,
  });
  listenerRef = listener;

  // Kick off first attempt; subsequent attempts are scheduled by the listener.
  retry();

  // Resolves only when routed === expectedRoute
  return promise;
}

// Promise-backed MultipleListener
class MultipleListener {
  constructor(
    {
      number_of_parallel_requests = 0,
      expectedRoute = "",
      with_error = Cr.NS_OK, // NS_OK means we expect success for all
    } = {},
    resolve,
    reject
  ) {
    this.number_of_parallel_requests = number_of_parallel_requests;
    this.expectedRoute = expectedRoute;
    this.with_error = with_error;

    this.count_of_done_requests = 0;
    this.error_found_onstart = false;
    this.error_found_onstop = false;
    this.need_cancel_found = false;

    this._resolve = resolve;
    this._reject = reject;
  }

  onStartRequest(request) {
    Assert.ok(request instanceof Ci.nsIHttpChannel);

    // Optional cancel behavior via header "CancelMe"
    let need_cancel = "";
    try {
      need_cancel = request.getRequestHeader("CancelMe");
    } catch (_) {}
    if (need_cancel !== "") {
      this.need_cancel_found = true;
      request.cancel(Cr.NS_ERROR_ABORT);
      return;
    }

    // Original logic: either 200 OK for success, or exactly one failure
    if (Components.isSuccessCode(request.status)) {
      Assert.equal(request.responseStatus, 200);
    } else if (this.error_found_onstart) {
      // Fail fast: more than one failing request on start
      this._reject?.(
        new Error("We should have only one request failing (onStart).")
      );
    } else {
      Assert.equal(request.status, this.with_error);
      this.error_found_onstart = true;
    }
  }

  onDataAvailable(request, stream, off, cnt) {
    read_stream(stream, cnt);
  }

  onStopRequest(request) {
    // Check Alt-Used routing matches expectation
    let routed = "";
    try {
      routed = request.getRequestHeader("Alt-Used");
    } catch (_) {}
    Assert.equal(routed, this.expectedRoute);

    // If success, ensure HTTP/3
    if (Components.isSuccessCode(request.status)) {
      let httpVersion = "";
      try {
        httpVersion = request.protocolVersion;
      } catch (_) {}
      Assert.equal(httpVersion, "h3");
    }

    // Track/validate failures (at most one)
    if (!Components.isSuccessCode(request.status)) {
      if (this.error_found_onstop) {
        this._reject?.(
          new Error("We should have only one request failing (onStop).")
        );
        return;
      }
      Assert.equal(request.status, this.with_error);
      this.error_found_onstop = true;
    }

    // Count completion and maybe resolve
    this.count_of_done_requests++;
    if (this.count_of_done_requests === this.number_of_parallel_requests) {
      if (Components.isSuccessCode(this.with_error)) {
        // All were expected to succeed
        Assert.equal(this.error_found_onstart, false);
        Assert.equal(this.error_found_onstop, false);
      } else {
        // One failure was expected OR a cancel path was exercised
        Assert.ok(this.error_found_onstart || this.need_cancel_found);
        Assert.equal(this.error_found_onstop, true);
      }
      this._resolve?.();
    }
  }
}

// Factory to create { listener, promise }
function createMultipleListener(options = {}) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new MultipleListener(options, resolve, reject);
  return { listener, promise };
}

async function do_test_multiple_requests(
  number_of_parallel_requests,
  h3Route,
  httpsOrigin
) {
  dump("test_multiple_requests()\n");

  const { listener, promise } = createMultipleListener({
    number_of_parallel_requests,
    expectedRoute: h3Route,
    with_error: Cr.NS_OK,
  });

  for (let i = 0; i < number_of_parallel_requests; i++) {
    const chan = makeChan(httpsOrigin + "20000");
    chan.asyncOpen(listener);
  }

  await promise;
}

async function do_test_request_cancelled_by_server(h3Route, httpsOrigin) {
  dump("do_test_request_cancelled_by_server()\n");

  const { listener, promise } = createHttp3CheckListener({
    expectedStatus: Cr.NS_ERROR_NET_INTERRUPT,
    expectedRoute: h3Route,
  });

  const chan = makeChan(httpsOrigin + "RequestCancelled");
  chan.asyncOpen(listener);

  // Resolves at the point where run_next_test() used to be called
  await promise;
}

// Server resets request stream with an unrecognized application error code.
// The transaction must retry via H2/H1 and succeed.
async function do_test_unknown_reset(httpsOrigin) {
  dump("do_test_unknown_reset()\n");

  const chan = makeChan(httpsOrigin + "UnknownReset");
  const promise = new Promise(resolve => {
    const listener = {
      onStartRequest(request) {
        Assert.ok(request instanceof Ci.nsIHttpChannel);
        Assert.equal(request.status, Cr.NS_OK);
        Assert.equal(request.responseStatus, 200);
      },
      onDataAvailable(request, stream, off, cnt) {
        read_stream(stream, cnt);
      },
      onStopRequest(request, status) {
        Assert.equal(status, Cr.NS_OK);
        let httpVersion = "";
        try {
          httpVersion = request.protocolVersion;
        } catch (e) {}
        Assert.notEqual(httpVersion, "h3");
        resolve(request);
      },
    };
    chan.asyncOpen(listener);
  });

  await promise;
}

// Promise-backed Http3CheckListener must already exist:
//   createHttp3CheckListener({ expectedStatus, expectedRoute })

class CancelRequestListener extends Http3CheckListener {
  constructor({ expectedRoute = "" } = {}, resolve, reject) {
    super(
      { expectedStatus: Cr.NS_ERROR_ABORT, expectedRoute },
      resolve,
      reject
    );
  }

  onStartRequest(request) {
    Assert.ok(request instanceof Ci.nsIHttpChannel);
    Assert.equal(Components.isSuccessCode(request.status), true);
    // Cancel the request immediately (simulate Necko cancelling)
    request.cancel(Cr.NS_ERROR_ABORT);
  }
}

function createCancelRequestListener(options = {}) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new CancelRequestListener(options, resolve, reject);
  return { listener, promise };
}

// Cancel stream after OnStartRequest.
async function do_test_stream_cancelled_by_necko(h3Route, httpsOrigin) {
  dump("do_test_stream_cancelled_by_necko()\n");

  const { listener, promise } = createCancelRequestListener({
    expectedRoute: h3Route,
  });

  const chan = makeChan(httpsOrigin + "20000");
  chan.asyncOpen(listener);

  // Resolves at the end of onStopRequest (where run_next_test() used to be)
  await promise;
}

async function do_test_multiple_request_one_is_cancelled(
  number_of_parallel_requests,
  h3Route,
  httpsOrigin
) {
  dump("do_test_multiple_request_one_is_cancelled()\n");

  const { listener, promise } = createMultipleListener({
    number_of_parallel_requests,
    expectedRoute: h3Route,
    with_error: Cr.NS_ERROR_NET_INTERRUPT, // one request is expected to fail (server-cancelled)
  });

  for (let i = 0; i < number_of_parallel_requests; i++) {
    let uri = httpsOrigin + "20000";
    if (i === 4) {
      // Add a request that will be cancelled by the server.
      uri = httpsOrigin + "RequestCancelled";
    }
    const chan = makeChan(uri);
    chan.asyncOpen(listener);
  }

  // Resolves when all parallel requests complete and invariants are checked
  await promise;
}

async function do_test_multiple_request_one_is_cancelled_by_necko(
  number_of_parallel_requests,
  h3Route,
  httpsOrigin
) {
  dump("do_test_multiple_request_one_is_cancelled_by_necko()\n");

  const { listener, promise } = createMultipleListener({
    number_of_parallel_requests,
    expectedRoute: h3Route,
    with_error: Cr.NS_ERROR_ABORT,
  });

  for (let i = 0; i < number_of_parallel_requests; i++) {
    let chan = makeChan(httpsOrigin + "20000");
    if (i === 4) {
      // MultipleListener will cancel request with this header.
      chan.setRequestHeader("CancelMe", "true", false);
    }
    chan.asyncOpen(listener);
  }

  // Resolves when all parallel requests complete and invariants are checked
  await promise;
}

// Promise-backed Http3CheckListener assumed available:
// function createHttp3CheckListener({ expectedStatus, expectedRoute })

class PostListener extends Http3CheckListener {
  constructor(opts = {}, resolve, reject) {
    super(opts, resolve, reject);
  }
  onDataAvailable(request, stream, off, cnt) {
    this.onDataAvailableFired = true;
    read_stream(stream, cnt);
  }
}

// Factory for PostListener
function createPostListener(options = {}) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new PostListener(options, resolve, reject);
  return { listener, promise };
}

// Helper to perform a POST (or any method with a body)
function openWithBody(
  content,
  chan,
  method = "POST",
  contentType = "text/plain"
) {
  const stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    Ci.nsIStringInputStream
  );
  stream.setByteStringData(content);

  const uchan = chan.QueryInterface(Ci.nsIUploadChannel);
  uchan.setUploadStream(stream, contentType, stream.available());
  chan.requestMethod = method;
  return chan;
}

// Generate a post with known pre-calculated md5 sum.
function generateContent(size) {
  let content = "";
  for (let i = 0; i < size; i++) {
    content += "0";
  }
  return content;
}

let post = generateContent(10);

// Test a simple POST (async)
async function do_test_post(httpsOrigin, h3Route) {
  dump("do_test_post()\n");

  const chan = makeChan(httpsOrigin + "post");
  openWithBody(post, chan, "POST");

  const { listener, promise } = createPostListener({
    expectedStatus: Cr.NS_OK,
    expectedRoute: h3Route,
  });

  chan.asyncOpen(listener);
  await promise; // resolves at end of onStopRequest in Http3CheckListener
}

// Test a simple PATCH
async function do_test_patch(httpsOrigin, h3Route) {
  dump("do_test_post()\n");

  const chan = makeChan(httpsOrigin + "patch");
  openWithBody(post, chan, "PATCH");

  const { listener, promise } = createPostListener({
    expectedStatus: Cr.NS_OK,
    expectedRoute: h3Route,
  });

  chan.asyncOpen(listener);
  await promise;
}

// Promise-backed base assumed available:
//   class Http3CheckListener { ... }
//   function createHttp3CheckListener(opts) { return { listener, promise }; }

class SlowReceiverListener extends Http3CheckListener {
  constructor(
    {
      expectedStatus = Cr.NS_OK,
      expectedRoute = "",
      expectedBytes = 10_000_000,
    } = {},
    resolve,
    reject
  ) {
    super({ expectedStatus, expectedRoute }, resolve, reject);
    this.count = 0;
    this.expectedBytes = expectedBytes;
  }

  onDataAvailable(request, stream, off, cnt) {
    this.onDataAvailableFired = true;
    this.count += cnt;
    read_stream(stream, cnt);
  }

  onStopRequest(request, status) {
    Assert.equal(status, this.expectedStatus);
    Assert.equal(this.count, this.expectedBytes);

    let routed = "NA";
    try {
      routed = request.getRequestHeader("Alt-Used");
    } catch (e) {}
    dump(`routed is ${routed}\n`);
    Assert.equal(routed, this.expectedRoute);

    if (Components.isSuccessCode(this.expectedStatus)) {
      let httpVersion = "";
      try {
        httpVersion = request.protocolVersion;
      } catch (e) {}
      Assert.equal(httpVersion, "h3");
      Assert.equal(this.onDataAvailableFired, true);
    }

    // Resolve where run_next_test() used to be
    this._resolve?.(request);
  }
}

function createSlowReceiverListener(options = {}) {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new SlowReceiverListener(options, resolve, reject);
  return { listener, promise };
}

// Test: slow receiver (suspend, then resume)
async function do_test_slow_receiver(httpsOrigin, h3Route) {
  dump("do_test_slow_receiver()\n");

  const chan = makeChan(httpsOrigin + "10000000");

  const { listener, promise } = createSlowReceiverListener({
    expectedStatus: Cr.NS_OK,
    expectedRoute: h3Route,
    expectedBytes: 10_000_000,
  });

  chan.asyncOpen(listener);

  // Suspend immediately, then resume after 1s (replaces do_test_pending/do_timeout)
  chan.suspend();
  await new Promise(r => do_timeout(1000, r));
  chan.resume();

  // Wait for completion (used to be run_next_test/do_test_finished)
  await promise;
}

// Promise-backed listener for version fallback checks
class CheckFallbackListener {
  constructor(resolve, reject) {
    this._resolve = resolve;
    this._reject = reject;
  }

  onStartRequest(request) {
    Assert.ok(request instanceof Ci.nsIHttpChannel);
    Assert.equal(request.status, Cr.NS_OK);
    Assert.equal(request.responseStatus, 200);
  }

  onDataAvailable(request, stream, off, cnt) {
    read_stream(stream, cnt);
  }

  onStopRequest(request, status) {
    Assert.equal(status, Cr.NS_OK);

    let routed = "NA";
    try {
      routed = request.getRequestHeader("Alt-Used");
    } catch (e) {}
    dump(`routed is ${routed}\n`);
    Assert.equal(routed, "0");

    let httpVersion = "";
    try {
      httpVersion = request.protocolVersion;
    } catch (e) {}
    Assert.equal(httpVersion, "http/1.1");

    // Resolve where run_next_test() used to be called
    this._resolve?.(request);
  }
}

// Factory to create { listener, promise }
function createCheckFallbackListener() {
  let resolve, reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  const listener = new CheckFallbackListener(resolve, reject);
  return { listener, promise };
}

// Server cancels request with VersionFallback.
async function do_test_version_fallback(httpsOrigin) {
  dump("do_test_version_fallback()\n");

  const chan = makeChan(httpsOrigin + "VersionFallback");
  const { listener, promise } = createCheckFallbackListener();

  chan.asyncOpen(listener);

  await promise;
}

Messung V0.5 in Prozent
C=91 H=90 G=90

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet am  2026-09-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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.