Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/netwerk/test/unit/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 13 kB image not shown  

Quelle  test_resumable_channel.js   Sprache: JAVA

 
/* Tests various aspects of nsIResumableChannel in combination with HTTP */
"use strict";

const { HttpServer } = ChromeUtils.importESModule(
  "resource://testing-common/httpd.sys.mjs"
);

ChromeUtils.defineLazyGetter(this"URL"function () {
  return "http://localhost:" + httpserver.identity.primaryPort;
});

var httpserver = null;

const NS_ERROR_ENTITY_CHANGED = 0x804b0020;
const NS_ERROR_NOT_RESUMABLE = 0x804b0019;

const rangeBody = "Body of the range request handler.\r\n";

function make_channel(url) {
  return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
}

function AuthPrompt2() {}

AuthPrompt2.prototype = {
  user: "guest",
  pass: "guest",

  QueryInterface: ChromeUtils.generateQI(["nsIAuthPrompt2"]),

  promptAuth: function ap2_promptAuth(channel, level, authInfo) {
    authInfo.username = this.user;
    authInfo.password = this.pass;
    return true;
  },

  asyncPromptAuth: function ap2_async() {
    throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED);
  },
};

function Requestor() {}

Requestor.prototype = {
  QueryInterface: ChromeUtils.generateQI(["nsIInterfaceRequestor"]),

  getInterface: function requestor_gi(iid) {
    if (iid.equals(Ci.nsIAuthPrompt2)) {
      // Allow the prompt to store state by caching it here
      if (!this.prompt2) {
        this.prompt2 = new AuthPrompt2();
      }
      return this.prompt2;
    }

    throw Components.Exception("", Cr.NS_ERROR_NO_INTERFACE);
  },

  prompt2: null,
};

function run_test() {
  dump("*** run_test\n");
  httpserver = new HttpServer();
  httpserver.registerPathHandler("/auth", authHandler);
  httpserver.registerPathHandler("/range", rangeHandler);
  httpserver.registerPathHandler("/acceptranges", acceptRangesHandler);
  httpserver.registerPathHandler("/redir", redirHandler);

  var entityID;

  function get_entity_id(request) {
    dump("*** get_entity_id()\n");
    Assert.ok(
      request instanceof Ci.nsIResumableChannel,
      "must be a resumable channel"
    );
    entityID = request.entityID;
    dump("*** entity id = " + entityID + "\n");

    // Try a non-resumable URL (responds with 200)
    var chan = make_channel(URL);
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.asyncOpen(new ChannelListener(try_resume, null, CL_EXPECT_FAILURE));
  }

  function try_resume(request) {
    dump("*** try_resume()\n");
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);

    // Try a successful resume
    var chan = make_channel(URL + "/range");
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.asyncOpen(new ChannelListener(try_resume_zero, null));
  }

  function try_resume_zero(request, data) {
    dump("*** try_resume_zero()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody.substring(1));

    // Try a server which doesn't support range requests
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.nsIHttpChannel.setRequestHeader("X-Range-Type""none"false);
    chan.asyncOpen(new ChannelListener(try_no_range, null, CL_EXPECT_FAILURE));
  }

  function try_no_range(request) {
    dump("*** try_no_range()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);

    // Try a server which supports "bytes" range requests
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.nsIHttpChannel.setRequestHeader("X-Range-Type""bytes"false);
    chan.asyncOpen(new ChannelListener(try_bytes_range, null));
  }

  function try_bytes_range(request, data) {
    dump("*** try_bytes_range()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody);

    // Try a server which supports "foo" and "bar" range requests
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.nsIHttpChannel.setRequestHeader("X-Range-Type""foo, bar"false);
    chan.asyncOpen(
      new ChannelListener(try_foo_bar_range, null, CL_EXPECT_FAILURE)
    );
  }

  function try_foo_bar_range(request) {
    dump("*** try_foo_bar_range()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);

    // Try a server which supports "foobar" range requests
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.nsIHttpChannel.setRequestHeader("X-Range-Type""foobar"false);
    chan.asyncOpen(
      new ChannelListener(try_foobar_range, null, CL_EXPECT_FAILURE)
    );
  }

  function try_foobar_range(request) {
    dump("*** try_foobar_range()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);

    // Try a server which supports "bytes" and "foobar" range requests
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.nsIHttpChannel.setRequestHeader(
      "X-Range-Type",
      "bytes, foobar",
      false
    );
    chan.asyncOpen(new ChannelListener(try_bytes_foobar_range, null));
  }

  function try_bytes_foobar_range(request, data) {
    dump("*** try_bytes_foobar_range()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody);

    // Try a server which supports "bytesfoo" and "bar" range requests
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.nsIHttpChannel.setRequestHeader(
      "X-Range-Type",
      "bytesfoo, bar",
      false
    );
    chan.asyncOpen(
      new ChannelListener(try_bytesfoo_bar_range, null, CL_EXPECT_FAILURE)
    );
  }

  function try_bytesfoo_bar_range(request) {
    dump("*** try_bytesfoo_bar_range()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);

    // Try a server which doesn't send Accept-Ranges header at all
    var chan = make_channel(URL + "/acceptranges");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.asyncOpen(new ChannelListener(try_no_accept_ranges, null));
  }

  function try_no_accept_ranges(request, data) {
    dump("*** try_no_accept_ranges()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody);

    // Try a successful suspend/resume from 0
    var chan = make_channel(URL + "/range");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.asyncOpen(
      new ChannelListener(
        try_suspend_resume,
        null,
        CL_SUSPEND | CL_EXPECT_3S_DELAY
      )
    );
  }

  function try_suspend_resume(request, data) {
    dump("*** try_suspend_resume()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody);

    // Try a successful resume from 0
    var chan = make_channel(URL + "/range");
    chan.nsIResumableChannel.resumeAt(0, entityID);
    chan.asyncOpen(new ChannelListener(success, null));
  }

  function success(request, data) {
    dump("*** success()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody);

    // Authentication (no password; working resume)
    // (should not give us any data)
    var chan = make_channel(URL + "/range");
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.nsIHttpChannel.setRequestHeader("X-Need-Auth""true"false);
    chan.asyncOpen(
      new ChannelListener(test_auth_nopw, null, CL_EXPECT_FAILURE)
    );
  }

  function test_auth_nopw(request) {
    dump("*** test_auth_nopw()\n");
    Assert.ok(!request.nsIHttpChannel.requestSucceeded);
    Assert.equal(request.status, NS_ERROR_ENTITY_CHANGED);

    // Authentication + not working resume
    var chan = make_channel(
      "http://guest:guest@localhost:" +
        httpserver.identity.primaryPort +
        "/auth"
    );
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.notificationCallbacks = new Requestor();
    chan.asyncOpen(new ChannelListener(test_auth, null, CL_EXPECT_FAILURE));
  }
  function test_auth(request) {
    dump("*** test_auth()\n");
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);
    Assert.ok(request.nsIHttpChannel.responseStatus < 300);

    // Authentication + working resume
    var chan = make_channel(
      "http://guest:guest@localhost:" +
        httpserver.identity.primaryPort +
        "/range"
    );
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.notificationCallbacks = new Requestor();
    chan.nsIHttpChannel.setRequestHeader("X-Need-Auth""true"false);
    chan.asyncOpen(new ChannelListener(test_auth_resume, null));
  }

  function test_auth_resume(request, data) {
    dump("*** test_auth_resume()\n");
    Assert.equal(data, rangeBody.substring(1));
    Assert.ok(request.nsIHttpChannel.requestSucceeded);

    // 404 page (same content length as real content)
    var chan = make_channel(URL + "/range");
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.nsIHttpChannel.setRequestHeader("X-Want-404""true"false);
    chan.asyncOpen(new ChannelListener(test_404, null, CL_EXPECT_FAILURE));
  }

  function test_404(request) {
    dump("*** test_404()\n");
    Assert.equal(request.status, NS_ERROR_ENTITY_CHANGED);
    Assert.equal(request.nsIHttpChannel.responseStatus, 404);

    // 416 Requested Range Not Satisfiable
    var chan = make_channel(URL + "/range");
    chan.nsIResumableChannel.resumeAt(1000, entityID);
    chan.asyncOpen(new ChannelListener(test_416, null, CL_EXPECT_FAILURE));
  }

  function test_416(request) {
    dump("*** test_416()\n");
    Assert.equal(request.status, NS_ERROR_ENTITY_CHANGED);
    Assert.equal(request.nsIHttpChannel.responseStatus, 416);

    // Redirect + successful resume
    var chan = make_channel(URL + "/redir");
    chan.nsIHttpChannel.setRequestHeader("X-Redir-To", URL + "/range"false);
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.asyncOpen(new ChannelListener(test_redir_resume, null));
  }

  function test_redir_resume(request, data) {
    dump("*** test_redir_resume()\n");
    Assert.ok(request.nsIHttpChannel.requestSucceeded);
    Assert.equal(data, rangeBody.substring(1));
    Assert.equal(request.nsIHttpChannel.responseStatus, 206);

    // Redirect + failed resume
    var chan = make_channel(URL + "/redir");
    chan.nsIHttpChannel.setRequestHeader("X-Redir-To", URL + "/"false);
    chan.nsIResumableChannel.resumeAt(1, entityID);
    chan.asyncOpen(
      new ChannelListener(test_redir_noresume, null, CL_EXPECT_FAILURE)
    );
  }

  function test_redir_noresume(request) {
    dump("*** test_redir_noresume()\n");
    Assert.equal(request.status, NS_ERROR_NOT_RESUMABLE);

    httpserver.stop(do_test_finished);
  }

  httpserver.start(-1);
  var chan = make_channel(URL + "/range");
  chan.asyncOpen(new ChannelListener(get_entity_id, null));
  do_test_pending();
}

// HANDLERS

function handleAuth(metadata, response) {
  // btoa("guest:guest"), but that function is not available here
  var expectedHeader = "Basic Z3Vlc3Q6Z3Vlc3Q=";

  if (
    metadata.hasHeader("Authorization") &&
    metadata.getHeader("Authorization") == expectedHeader
  ) {
    response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
    response.setHeader("WWW-Authenticate"'Basic realm="secret"'false);

    return true;
  }
  // didn't know guest:guest, failure
  response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
  response.setHeader("WWW-Authenticate"'Basic realm="secret"'false);
  return false;
}

// /auth
function authHandler(metadata, response) {
  response.setHeader("Content-Type""text/html"false);
  var body = handleAuth(metadata, response) ? "success" : "failure";
  response.bodyOutputStream.write(body, body.length);
}

// /range
function rangeHandler(metadata, response) {
  response.setHeader("Content-Type""text/html"false);

  if (metadata.hasHeader("X-Need-Auth")) {
    if (!handleAuth(metadata, response)) {
      body = "auth failed";
      response.bodyOutputStream.write(body, body.length);
      return;
    }
  }

  if (metadata.hasHeader("X-Want-404")) {
    response.setStatusLine(metadata.httpVersion, 404, "Not Found");
    body = rangeBody;
    response.bodyOutputStream.write(body, body.length);
    return;
  }

  var body = rangeBody;

  if (metadata.hasHeader("Range")) {
    // Syntax: bytes=[from]-[to] (we don't support multiple ranges)
    var matches = metadata
      .getHeader("Range")
      .match(/^\s*bytes=(\d+)?-(\d+)?\s*$/);
    var from = matches[1] === undefined ? 0 : matches[1];
    var to = matches[2] === undefined ? rangeBody.length - 1 : matches[2];
    if (from >= rangeBody.length) {
      response.setStatusLine(metadata.httpVersion, 416, "Start pos too high");
      response.setHeader("Content-Range""*/" + rangeBody.length, false);
      return;
    }
    body = body.substring(from, to + 1);
    // always respond to successful range requests with 206
    response.setStatusLine(metadata.httpVersion, 206, "Partial Content");
    response.setHeader(
      "Content-Range",
      from + "-" + to + "/" + rangeBody.length,
      false
    );
  }

  response.bodyOutputStream.write(body, body.length);
}

// /acceptranges
function acceptRangesHandler(metadata, response) {
  response.setHeader("Content-Type""text/html"false);
  if (metadata.hasHeader("X-Range-Type")) {
    response.setHeader(
      "Accept-Ranges",
      metadata.getHeader("X-Range-Type"),
      false
    );
  }
  response.bodyOutputStream.write(rangeBody, rangeBody.length);
}

// /redir
function redirHandler(metadata, response) {
  response.setStatusLine(metadata.httpVersion, 302, "Found");
  response.setHeader("Content-Type""text/html"false);
  response.setHeader("Location", metadata.getHeader("X-Redir-To"), false);
  var body = "redirect\r\n";
  response.bodyOutputStream.write(body, body.length);
}

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

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© 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.