Bug 381598 - HTTP server tests cleanup. r=me because I don't think it's a good use of anyone's time to disentangle the tests as they were written prior to this checkin
authorJeff Walden <jwalden@mit.edu>
Mon, 15 Dec 2008 21:02:41 -0800
changeset 22829 62cef3062efd8e590833ea6acc4b00b2b66464e5
parent 22828 68395c6df140f1724b93bb1ec47e5a9b979f75da
child 22830 37c2721a512d3beba7a0bce135070a6c3b92e582
push id4207
push userjwalden@mit.edu
push dateTue, 16 Dec 2008 05:11:29 +0000
treeherdermozilla-central@62cef3062efd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs381598
milestone1.9.2a1pre
Bug 381598 - HTTP server tests cleanup. r=me because I don't think it's a good use of anyone's time to disentangle the tests as they were written prior to this checkin
netwerk/test/httpserver/test/test_basic_functionality.js
netwerk/test/httpserver/test/test_empty_body.js
netwerk/test/httpserver/test/test_errorhandler_exception.js
netwerk/test/httpserver/test/test_registerdirectory.js
netwerk/test/httpserver/test/test_response_write.js
--- a/netwerk/test/httpserver/test/test_basic_functionality.js
+++ b/netwerk/test/httpserver/test/test_basic_functionality.js
@@ -33,125 +33,96 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // basic functionality test, from the client programmer's POV
 
-
-var paths =
+var tests =
   [
-   "http://localhost:4444/objHandler",
-   "http://localhost:4444/functionHandler",
-   "http://localhost:4444/non-existent-path"  // intended to produce 404
+   new Test("http://localhost:4444/objHandler",
+            null, start_objHandler, null),
+   new Test("http://localhost:4444/functionHandler",
+            null, start_functionHandler, null),
+   new Test("http://localhost:4444/non-existent-path",
+            null, start_non_existent_path, null),
   ];
-var currPathIndex = 0;
-
-var listener =
-  {
-    // NSISTREAMLISTENER
-    onDataAvailable: function(request, cx, inputStream, offset, count)
-    {
-      makeBIS(inputStream).readByteArray(count); // required by API
-    },
-    // NSIREQUESTOBSERVER
-    onStartRequest: function(request, cx)
-    {
-      var ch = request.QueryInterface(Ci.nsIHttpChannel)
-                      .QueryInterface(Ci.nsIHttpChannelInternal);
-
-      // common properties *always* appended by server or invariants for every
-      // URL in paths
-      do_check_true(ch.contentLength > -1);
-      do_check_eq(ch.getResponseHeader("connection"), "close"); 
-      do_check_false(ch.isNoStoreResponse());
-
-      var reqMin = {}, reqMaj = {}, respMin = {}, respMaj = {};
-      switch (currPathIndex)
-      {
-        case 0:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_true(ch.requestSucceeded);
-          do_check_eq(ch.getResponseHeader("content-type"), "text/plain");
-          do_check_eq(ch.responseStatusText, "OK");
-
-          ch.getRequestVersion(reqMaj, reqMin);
-          ch.getResponseVersion(respMaj, respMin);
-          do_check_true(reqMaj.value == respMaj.value &&
-                        reqMin.value == respMin.value);
-          break;
-
-        case 1:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          do_check_eq(ch.getResponseHeader("foopy"), "quux-baz");
-          do_check_eq(ch.responseStatusText, "Page Not Found");
-
-          ch.getResponseVersion(respMaj, respMin);
-          do_check_true(respMaj.value == 1 && respMin.value == 1);
-          break;
-
-        case 2:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
-      }
-    },
-    onStopRequest: function(request, cx, status)
-    {
-      if (++currPathIndex == paths.length)
-        srv.stop();
-      else
-        performNextTest();
-      do_test_finished();
-    },
-    // NSISUPPORTS
-    QueryInterface: function(aIID)
-    {
-      if (aIID.equals(Ci.nsIStreamListener) ||
-          aIID.equals(Ci.nsIRequestObserver) ||
-          aIID.equals(Ci.nsISupports))
-        return this;
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
-  };
-
-
-function performNextTest()
-{
-  do_test_pending();
-
-  var ch = makeChannel(paths[currPathIndex]);
-  ch.asyncOpen(listener, null);
-}
-
-var srv;
 
 function run_test()
 {
-  srv = createServer();
+  var srv = createServer();
 
   // base path
   // XXX should actually test this works with a file by comparing streams!
   var dirServ = Cc["@mozilla.org/file/directory_service;1"]
                   .getService(Ci.nsIProperties);
   var path = dirServ.get("CurProcD", Ci.nsILocalFile);
   srv.registerDirectory("/", path);
 
   // register a few test paths
   srv.registerPathHandler("/objHandler", objHandler);
   srv.registerPathHandler("/functionHandler", functionHandler);
 
   srv.start(4444);
 
-  performNextTest();
+  runHttpTests(tests, function() { srv.stop(); });
+}
+
+
+// TEST DATA
+
+// common properties *always* appended by server
+// or invariants for every URL in paths
+function commonCheck(ch)
+{
+  do_check_true(ch.contentLength > -1);
+  do_check_eq(ch.getResponseHeader("connection"), "close");
+  do_check_false(ch.isNoStoreResponse());
 }
 
+function start_objHandler(ch, cx)
+{
+  commonCheck(ch);
+
+  do_check_eq(ch.responseStatus, 200);
+  do_check_true(ch.requestSucceeded);
+  do_check_eq(ch.getResponseHeader("content-type"), "text/plain");
+  do_check_eq(ch.responseStatusText, "OK");
+
+  var reqMin = {}, reqMaj = {}, respMin = {}, respMaj = {};
+  ch.getRequestVersion(reqMaj, reqMin);
+  ch.getResponseVersion(respMaj, respMin);
+  do_check_true(reqMaj.value == respMaj.value &&
+                reqMin.value == respMin.value);
+}
+
+function start_functionHandler(ch, cx)
+{
+  commonCheck(ch);
+
+  do_check_eq(ch.responseStatus, 404);
+  do_check_false(ch.requestSucceeded);
+  do_check_eq(ch.getResponseHeader("foopy"), "quux-baz");
+  do_check_eq(ch.responseStatusText, "Page Not Found");
+
+  ch.getResponseVersion(respMaj, respMin);
+  do_check_true(respMaj.value == 1 && respMin.value == 1);
+}
+
+function start_non_existent_path(ch, cx)
+{
+  commonCheck(ch);
+
+  do_check_eq(ch.responseStatus, 404);
+  do_check_false(ch.requestSucceeded);
+}
+
+
 // PATH HANDLERS
 
 // /objHandler
 var objHandler =
   {
     handle: function(metadata, response)
     {
       response.setStatusLine(metadata.httpVersion, 200, "OK");
--- a/netwerk/test/httpserver/test/test_empty_body.js
+++ b/netwerk/test/httpserver/test/test_empty_body.js
@@ -34,78 +34,42 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // in its original incarnation, the server didn't like empty response-bodies;
 // see the comment in _end for details
 
-var paths =
+var tests =
   [
-   "http://localhost:4444/empty-body-unwritten",
-   "http://localhost:4444/empty-body-written"
+   new Test("http://localhost:4444/empty-body-unwritten",
+            null, ensureEmpty, null),
+   new Test("http://localhost:4444/empty-body-written",
+            null, ensureEmpty, null),
   ];
-var currPathIndex = 0;
-
-var listener =
-  {
-    // NSISTREAMLISTENER
-    onDataAvailable: function(request, cx, inputStream, offset, count)
-    {
-      makeBIS(inputStream).readByteArray(count); // required by API
-    },
-    // NSIREQUESTOBSERVER
-    onStartRequest: function(request, cx)
-    {
-      var ch = request.QueryInterface(Ci.nsIHttpChannel)
-                      .QueryInterface(Ci.nsIHttpChannelInternal);
-      do_check_true(ch.contentLength == 0);
-    },
-    onStopRequest: function(request, cx, status)
-    {
-      if (++currPathIndex == paths.length)
-        srv.stop();
-      else
-        performNextTest();
-      do_test_finished();
-    },
-    // NSISUPPORTS
-    QueryInterface: function(aIID)
-    {
-      if (aIID.equals(Ci.nsIStreamListener) ||
-          aIID.equals(Ci.nsIRequestObserver) ||
-          aIID.equals(Ci.nsISupports))
-        return this;
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
-  };
-
-
-function performNextTest()
-{
-  do_test_pending();
-
-  var ch = makeChannel(paths[currPathIndex]);
-  ch.asyncOpen(listener, null);
-}
-
-var srv;
 
 function run_test()
 {
-  srv = createServer();
+  var srv = createServer();
 
   // register a few test paths
   srv.registerPathHandler("/empty-body-unwritten", emptyBodyUnwritten);
   srv.registerPathHandler("/empty-body-written", emptyBodyWritten);
 
   srv.start(4444);
 
-  performNextTest();
+  runHttpTests(tests, function() { srv.stop(); });
+}
+
+// TEST DATA
+
+function ensureEmpty(ch, cx)
+{
+  do_check_true(ch.contentLength == 0);
 }
 
 // PATH HANDLERS
 
 // /empty-body-unwritten
 function emptyBodyUnwritten(metadata, response)
 {
   response.setStatusLine("1.1", 200, "OK");
--- a/netwerk/test/httpserver/test/test_errorhandler_exception.js
+++ b/netwerk/test/httpserver/test/test_errorhandler_exception.js
@@ -34,118 +34,79 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Request handlers may throw exceptions, and those exception should be caught
 // by the server and converted into the proper error codes.
 
-var paths =
+var tests =
   [
-   "http://localhost:4444/throws/exception",
-   "http://localhost:4444/this/file/does/not/exist/and/404s",
-   "http://localhost:4444/attempts/404/fails/so/400/fails/so/500s"
+   new Test("http://localhost:4444/throws/exception",
+            null, start_throws_exception, succeeded),
+   new Test("http://localhost:4444/this/file/does/not/exist/and/404s",
+            null, start_nonexistent_404_fails_so_400, succeeded),
+   new Test("http://localhost:4444/attempts/404/fails/so/400/fails/so/500s",
+            register400Handler, start_multiple_exceptions_500, succeeded),
   ];
-var currPathIndex = 0;
 
-var listener =
-  {
-    // NSISTREAMLISTENER
-    onDataAvailable: function(request, cx, inputStream, offset, count)
-    {
-      makeBIS(inputStream).readByteArray(count); // required by API
-    },
-    // NSIREQUESTOBSERVER
-    onStartRequest: function(request, cx)
-    {
-      var ch = request.QueryInterface(Ci.nsIHttpChannel)
-                      .QueryInterface(Ci.nsIHttpChannelInternal);
-
-      switch (currPathIndex)
-      {
-        case 0:
-          checkStatusLine(ch, 1, 1, 500, "Internal Server Error");
-          break;
-
-        case 1:
-          checkStatusLine(ch, 1, 1, 400, "Bad Request");
-          break;
+var srv;
 
-        case 2:
-          checkStatusLine(ch, 1, 1, 500, "Internal Server Error");
-          break;
-      }
-    },
-    onStopRequest: function(request, cx, status)
-    {
-      do_check_true(Components.isSuccessCode(status));
+function run_test()
+{
+  srv = createServer();
 
-      switch (currPathIndex)
-      {
-        case 0:
-          break;
-
-        case 1:
-          srv.registerErrorHandler(400, throwsException);
-          break;
+  srv.registerErrorHandler(404, throwsException);
+  srv.registerPathHandler("/throws/exception", throwsException);
 
-        case 2:
-          break;
-      }
+  srv.start(4444);
 
-      if (++currPathIndex == paths.length)
-        srv.stop();
-      else
-        performNextTest();
-      do_test_finished();
-    },
-    // NSISUPPORTS
-    QueryInterface: function(aIID)
-    {
-      if (aIID.equals(Ci.nsIStreamListener) ||
-          aIID.equals(Ci.nsIRequestObserver) ||
-          aIID.equals(Ci.nsISupports))
-        return this;
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
-  };
+  runHttpTests(tests, function() { srv.stop(); });
+}
+
+
+// TEST DATA
 
 function checkStatusLine(channel, httpMaxVer, httpMinVer, httpCode, statusText)
 {
   do_check_eq(channel.responseStatus, httpCode);
   do_check_eq(channel.responseStatusText, statusText);
 
   var respMaj = {}, respMin = {};
   channel.getResponseVersion(respMaj, respMin);
   do_check_eq(respMaj.value, httpMaxVer);
   do_check_eq(respMin.value, httpMinVer);
 }
 
-function performNextTest()
+function start_throws_exception(ch, cx)
 {
-  do_test_pending();
+  checkStatusLine(ch, 1, 1, 500, "Internal Server Error");
+}
 
-  var ch = makeChannel(paths[currPathIndex]);
-  ch.asyncOpen(listener, null);
+function start_nonexistent_404_fails_so_400(ch, cx)
+{
+  checkStatusLine(ch, 1, 1, 400, "Bad Request");
 }
 
-var srv;
-
-function run_test()
+function start_multiple_exceptions_500(ch, cx)
 {
-  srv = createServer();
+  checkStatusLine(ch, 1, 1, 500, "Internal Server Error");
+}
 
-  srv.registerErrorHandler(404, throwsException);
-  srv.registerPathHandler("/throws/exception", throwsException);
+function succeeded(ch, cx, status, data)
+{
+  do_check_true(Components.isSuccessCode(status));
+}
 
-  srv.start(4444);
+function register400Handler(ch)
+{
+  srv.registerErrorHandler(400, throwsException);
+}
 
-  performNextTest();
-}
 
 // PATH HANDLERS
 
 // /throws/exception (and also a 404 and 400 error handler)
 function throwsException(metadata, response)
 {
   throw "this shouldn't cause an exit...";
   do_throw("Not reached!");
--- a/netwerk/test/httpserver/test/test_registerdirectory.js
+++ b/netwerk/test/httpserver/test/test_registerdirectory.js
@@ -35,270 +35,301 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // tests the registerDirectory API
 
 const BASE = "http://localhost:4444";
 
-var paths =
-  [
-/* 0*/ BASE + "/test_registerdirectory.js", // without a base path
-/* 1*/ BASE + "/test_registerdirectory.js", // with a base path
-/* 2*/ BASE + "/test_registerdirectory.js", // without a base path
+var tests = [];
+var test;
+
 
-/* 3*/ BASE + "/test_registerdirectory.js", // no registered path handler
-/* 4*/ BASE + "/test_registerdirectory.js", // registered path handler
-/* 5*/ BASE + "/test_registerdirectory.js", // removed path handler
+function nocache(ch)
+{
+  ch.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; // important!
+}
 
-/* 6*/ BASE + "/test_registerdirectory.js", // with a base path
-/* 7*/ BASE + "/test_registerdirectory.js", // ...and a path handler
-/* 8*/ BASE + "/test_registerdirectory.js", // removed base handler
-/* 9*/ BASE + "/test_registerdirectory.js",  // removed path handler
+function notFound(ch)
+{
+  do_check_eq(ch.responseStatus, 404);
+  do_check_false(ch.requestSucceeded);
+}
 
-/*10*/ BASE + "/foo/test_registerdirectory.js", // mapping set up, works
-/*11*/ BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js", // no mapping, fails
-/*12*/ BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js", // mapping, works
-/*13*/ BASE + "/foo/test_registerdirectory.js", // two mappings set up, still works
-/*14*/ BASE + "/foo/test_registerdirectory.js", // mapping was removed
-/*15*/ BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js", // mapping still present, works
-/*16*/ BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js", // mapping removed
-  ];
-var currPathIndex = 0;
+function checkOverride(ch)
+{
+  do_check_eq(ch.responseStatus, 200);
+  do_check_eq(ch.responseStatusText, "OK");
+  do_check_true(ch.requestSucceeded);
+  do_check_eq(ch.getResponseHeader("Override-Succeeded"), "yes");
+}
+
+function check200(ch)
+{
+  do_check_eq(ch.responseStatus, 200);
+  do_check_eq(ch.responseStatusText, "OK");
+}
 
-var listener =
-  {
-    // NSISTREAMLISTENER
-    onDataAvailable: function(request, cx, inputStream, offset, count)
-    {
-      makeBIS(inputStream).readByteArray(count); // required by API
-    },
-    // NSIREQUESTOBSERVER
-    onStartRequest: function(request, cx)
-    {
-      var ch = request.QueryInterface(Ci.nsIHttpChannel);
+function checkFile(ch)
+{
+  do_check_eq(ch.responseStatus, 200);
+  do_check_true(ch.requestSucceeded);
+
+  var actualFile = serverBasePath.clone();
+  actualFile.append("test_registerdirectory.js");
+  do_check_eq(ch.getResponseHeader("Content-Length"),
+              actualFile.fileSize.toString());
+}
+
+
+/***********************
+ * without a base path *
+ ***********************/
 
-      switch (currPathIndex)
-      {
-        case 0:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                nocache, notFound, null),
+tests.push(test);
 
-        case 1:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_true(ch.requestSucceeded);
+
+/********************
+ * with a base path *
+ ********************/
 
-          var actualFile = serverBasePath.clone();
-          actualFile.append("test_registerdirectory.js");
-          do_check_eq(ch.getResponseHeader("Content-Length"),
-                      actualFile.fileSize.toString());
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  serverBasePath = testsDirectory.clone();
+                  srv.registerDirectory("/", serverBasePath);
+                },
+                checkFile,
+                null);
+tests.push(test);
 
-        case 2:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
 
-        case 3:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
+/*****************************
+ * without a base path again *
+ *****************************/
 
-        case 4:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_eq(ch.responseStatusText, "OK");
-          do_check_true(ch.requestSucceeded);
-          do_check_eq(ch.getResponseHeader("Override-Succeeded"), "yes");
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  serverBasePath = null;
+                  srv.registerDirectory("/", serverBasePath);
+                },
+                notFound,
+                null);
+tests.push(test);
+
 
-        case 5:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
+/***************************
+ * registered path handler *
+ ***************************/
 
-        case 6:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_true(ch.requestSucceeded);
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  srv.registerPathHandler("/test_registerdirectory.js",
+                                          override_test_registerdirectory);
+                },
+                checkOverride,
+                null);
+tests.push(test);
 
-          var actualFile = serverBasePath.clone();
-          actualFile.append("test_registerdirectory.js");
-          do_check_eq(ch.getResponseHeader("Content-Length"),
-                      actualFile.fileSize.toString());
-          break;
 
-        case 7:
-        case 8:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_eq(ch.responseStatusText, "OK");
-          do_check_true(ch.requestSucceeded);
-          do_check_eq(ch.getResponseHeader("Override-Succeeded"), "yes");
-          break;
+/************************
+ * removed path handler *
+ ************************/
 
-        case 9:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function init_registerDirectory6(ch)
+                {
+                  nocache(ch);
+                  srv.registerPathHandler("/test_registerdirectory.js", null);
+                },
+                notFound,
+                null);
+tests.push(test);
+
 
-        case 10:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_eq(ch.responseStatusText, "OK");
-          break;
+/********************
+ * with a base path *
+ ********************/
 
-        case 11:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
 
-        case 12:
-        case 13:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_eq(ch.responseStatusText, "OK");
-          break;
+                  // set the base path again
+                  serverBasePath = testsDirectory.clone();
+                  srv.registerDirectory("/", serverBasePath);
+                },
+                checkFile,
+                null);
+tests.push(test);
 
-        case 14:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
+
+/*************************
+ * ...and a path handler *
+ *************************/
 
-        case 15:
-          do_check_eq(ch.responseStatus, 200);
-          do_check_eq(ch.responseStatusText, "OK");
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  srv.registerPathHandler("/test_registerdirectory.js",
+                                          override_test_registerdirectory);
+                },
+                checkOverride,
+                null);
+tests.push(test);
+
 
-        case 16:
-          do_check_eq(ch.responseStatus, 404);
-          do_check_false(ch.requestSucceeded);
-          break;
-      }
-    },
-    onStopRequest: function(request, cx, status)
-    {
-      switch (currPathIndex)
-      {
-        case 0:
-          // now set a base path
-          serverBasePath = testsDirectory.clone();
-          srv.registerDirectory("/", serverBasePath);
-          break;
+/************************
+ * removed base handler *
+ ************************/
 
-        case 1:
-          // remove base path
-          serverBasePath = null;
-          srv.registerDirectory("/", serverBasePath);
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  serverBasePath = null;
+                  srv.registerDirectory("/", serverBasePath);
+                },
+                checkOverride,
+                null);
+tests.push(test);
+
 
-        case 3:
-          // register overriding path
-          srv.registerPathHandler("/test_registerdirectory.js",
-                                  override_test_registerdirectory);
-          break;
+/************************
+ * removed path handler *
+ ************************/
 
-        case 4:
-          // unregister overriding path
-          srv.registerPathHandler("/test_registerdirectory.js", null);
-          break;
+test = new Test(BASE + "/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  srv.registerPathHandler("/test_registerdirectory.js", null);
+                },
+                notFound,
+                null);
+tests.push(test);
+
 
-        case 5:
-          // set the base path again
-          serverBasePath = testsDirectory.clone();
-          srv.registerDirectory("/", serverBasePath);
-          break;
+/*************************
+ * mapping set up, works *
+ *************************/
 
-        case 6:
-          // register overriding path
-          srv.registerPathHandler("/test_registerdirectory.js",
-                                  override_test_registerdirectory);
-          break;
+test = new Test(BASE + "/foo/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  serverBasePath = testsDirectory.clone();
+                  srv.registerDirectory("/foo/", serverBasePath);
+                },
+                check200,
+                null);
+tests.push(test);
 
-        case 7:
-          // remove base path
-          serverBasePath = null;
-          srv.registerDirectory("/", serverBasePath);
-          break;
+
+/*********************
+ * no mapping, fails *
+ *********************/
 
-        case 8:
-          // unregister overriding path
-          srv.registerPathHandler("/test_registerdirectory.js", null);
-          break;
+test = new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
+                nocache,
+                notFound,
+                null);
+tests.push(test);
 
-        case 9:
-          // register /foo/ as a base path
-          serverBasePath = testsDirectory.clone();
-          srv.registerDirectory("/foo/", serverBasePath);
-          break;
 
-        case 10:
-          // do nothing
-          break;
+/******************
+ * mapping, works *
+ ******************/
 
-        case 11:
-          // now register an overriding path to handle the URL that just failed
-          srv.registerDirectory("/foo/test_registerdirectory.js/", serverBasePath);
-          break;
+test = new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  srv.registerDirectory("/foo/test_registerdirectory.js/",
+                                        serverBasePath);
+                },
+                checkFile,
+                null);
+tests.push(test);
+
 
-        case 12:
-          // do nothing
-          break;
+/************************************
+ * two mappings set up, still works *
+ ************************************/
 
-        case 13:
-          srv.registerDirectory("/foo/", null);
-          break;
+test = new Test(BASE + "/foo/test_registerdirectory.js",
+                nocache, checkFile, null);
+tests.push(test);
 
-        case 14:
-          // do nothing
-          break;
+
+/**************************
+ * remove topmost mapping *
+ **************************/
 
-        case 15:
-          srv.registerDirectory("/foo/test_registerdirectory.js/", null);
-          break;
-      }
+test = new Test(BASE + "/foo/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  srv.registerDirectory("/foo/", null);
+                },
+                notFound,
+                null);
+tests.push(test);
 
-      if (!paths[++currPathIndex])
-        srv.stop();
-      else
-        performNextTest();
+
+/**************************************
+ * lower mapping still present, works *
+ **************************************/
 
-      do_test_finished();
-    },
-    // NSISUPPORTS
-    QueryInterface: function(aIID)
-    {
-      if (aIID.equals(Ci.nsIStreamListener) ||
-          aIID.equals(Ci.nsIRequestObserver) ||
-          aIID.equals(Ci.nsISupports))
-        return this;
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
-  };
+test = new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
+                nocache, checkFile, null);
+tests.push(test);
+
+
+/*******************
+ * mapping removed *
+ *******************/
 
-function performNextTest()
-{
-  do_test_pending();
+test = new Test(BASE + "/foo/test_registerdirectory.js/test_registerdirectory.js",
+                function(ch)
+                {
+                  nocache(ch);
+                  srv.registerDirectory("/foo/test_registerdirectory.js/", null);
+                },
+                notFound,
+                null);
+tests.push(test);
 
-  var ch = makeChannel(paths[currPathIndex]);
-  ch.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; // important!
-  ch.asyncOpen(listener, null);
-}
+
 
 var srv;
 var serverBasePath;
 var testsDirectory;
 
 function run_test()
 {
   testsDirectory = do_get_file("netwerk/test/httpserver/test/");
 
   srv = createServer();
   srv.start(4444);
 
-  performNextTest();
+  runHttpTests(tests, function() { srv.stop(); });
 }
 
+
 // PATH HANDLERS
 
 // override of /test_registerdirectory.js
 function override_test_registerdirectory(metadata, response)
 {
   response.setStatusLine("1.1", 200, "OK");
   response.setHeader("Override-Succeeded", "yes", false);
 
--- a/netwerk/test/httpserver/test/test_response_write.js
+++ b/netwerk/test/httpserver/test/test_response_write.js
@@ -33,88 +33,50 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // make sure response.write works for strings, and coerces other args to strings
 
-var paths =
+var tests =
   [
-   "http://localhost:4444/writeString",
-   "http://localhost:4444/writeInt"
+   new Test("http://localhost:4444/writeString",
+            null, check_1234, succeeded),
+   new Test("http://localhost:4444/writeInt",
+            null, check_1234, succeeded),
   ];
-var currPathIndex = 0;
-
-var listener =
-  {
-    // NSISTREAMLISTENER
-    onDataAvailable: function(request, cx, inputStream, offset, count)
-    {
-      makeBIS(inputStream).readByteArray(count); // required by API
-    },
-    // NSIREQUESTOBSERVER
-    onStartRequest: function(request, cx)
-    {
-      var ch = request.QueryInterface(Ci.nsIHttpChannel)
-                      .QueryInterface(Ci.nsIHttpChannelInternal);
-
-      switch (currPathIndex)
-      {
-        case 0:
-          do_check_eq(ch.getResponseHeader("Content-Length"), "4");
-          break;
-
-        case 1:
-          do_check_eq(ch.getResponseHeader("Content-Length"), "4");
-          break;
-      }
-    },
-    onStopRequest: function(request, cx, status)
-    {
-      do_check_true(Components.isSuccessCode(status));
-      if (++currPathIndex == paths.length)
-        srv.stop();
-      else
-        performNextTest();
-      do_test_finished();
-    },
-    // NSISUPPORTS
-    QueryInterface: function(aIID)
-    {
-      if (aIID.equals(Ci.nsIStreamListener) ||
-          aIID.equals(Ci.nsIRequestObserver) ||
-          aIID.equals(Ci.nsISupports))
-        return this;
-      throw Cr.NS_ERROR_NO_INTERFACE;
-    }
-  };
-
-function performNextTest()
-{
-  do_test_pending();
-
-  var ch = makeChannel(paths[currPathIndex]);
-  ch.asyncOpen(listener, null);
-}
-
-var srv;
 
 function run_test()
 {
-  srv = createServer();
+  var srv = createServer();
 
   srv.registerPathHandler("/writeString", writeString);
   srv.registerPathHandler("/writeInt", writeInt);
   srv.start(4444);
 
-  performNextTest();
+  runHttpTests(tests, function() { srv.stop(); });
 }
 
+
+// TEST DATA
+
+function succeeded(ch, cx, status)
+{
+
+  do_check_true(Components.isSuccessCode(status));
+}
+
+function check_1234(ch, cx)
+{
+  do_check_eq(ch.getResponseHeader("Content-Length"), "4");
+}
+
+
 // PATH HANDLERS
 
 function writeString(metadata, response)
 {
   response.write("1234");
 }
 
 function writeInt(metadata, response)