From b2c871b27911e7d9646c2843abda8006ed2f4fc6 Mon Sep 17 00:00:00 2001 From: Jason Duell Date: Sat, 17 Oct 2009 00:05:27 -0700 Subject: [PATCH] Add run_test_in_child() and do_load_child_test_harness() xpcshell functions (bug 521922). r=bent sr=ted Add necko 'unit_ipc' test directory under e10s, plus simple HTTP test. --- netwerk/test/Makefile.in | 3 + netwerk/test/unit/test_simple.js | 53 ++++++++++++++++ netwerk/test/unit_ipc/head_channels_clone.js | 6 ++ netwerk/test/unit_ipc/test_simple_wrap.js | 7 +++ testing/xpcshell/head.js | 64 ++++++++++++++++++++ testing/xpcshell/runxpcshelltests.py | 6 +- 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 netwerk/test/unit/test_simple.js create mode 100644 netwerk/test/unit_ipc/head_channels_clone.js create mode 100644 netwerk/test/unit_ipc/test_simple_wrap.js diff --git a/netwerk/test/Makefile.in b/netwerk/test/Makefile.in index 8d76f04cf083..4a4640cda454 100644 --- a/netwerk/test/Makefile.in +++ b/netwerk/test/Makefile.in @@ -95,6 +95,9 @@ LIBS = $(EXTRA_DSO_LIBS) \ DEFINES += $(TK_CFLAGS) XPCSHELL_TESTS = unit +ifdef MOZ_IPC +XPCSHELL_TESTS += unit_ipc +endif include $(topsrcdir)/config/rules.mk diff --git a/netwerk/test/unit/test_simple.js b/netwerk/test/unit/test_simple.js new file mode 100644 index 000000000000..7d620e8cc59e --- /dev/null +++ b/netwerk/test/unit/test_simple.js @@ -0,0 +1,53 @@ +// +// Simple HTTP test: fetches page +// + +// Note: sets Cc and Ci variables +do_load_httpd_js(); + +var httpserver = new nsHttpServer(); +var testpath = "/simple"; +var httpbody = "0123456789"; +var buffer = ""; + +var dbg=0 +if (dbg) { print("============== START =========="); } + +function run_test() { + setup_test(); + do_test_pending(); +} + +function setup_test() { + if (dbg) { print("============== setup_test: in"); } + httpserver.registerPathHandler(testpath, serverHandler); + httpserver.start(4444); + var channel = setupChannel(testpath); + // ChannelListener defined in head_channels.js + channel.asyncOpen(new ChannelListener(checkRequest, channel), null); + if (dbg) { print("============== setup_test: out"); } +} + +function setupChannel(path) { + var ios = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var chan = ios.newChannel("http://localhost:4444" + path, "", null); + chan.QueryInterface(Ci.nsIHttpChannel); + chan.requestMethod = "GET"; + return chan; +} + +function serverHandler(metadata, response) { + if (dbg) { print("============== serverHandler: in"); } + response.setHeader("Content-Type", "text/plain", false); + response.bodyOutputStream.write(httpbody, httpbody.length); + if (dbg) { print("============== serverHandler: out"); } +} + +function checkRequest(request, data, context) { + if (dbg) { print("============== checkRequest: in"); } + do_check_eq(data, httpbody); + httpserver.stop(do_test_finished); + if (dbg) { print("============== checkRequest: out"); } +} + diff --git a/netwerk/test/unit_ipc/head_channels_clone.js b/netwerk/test/unit_ipc/head_channels_clone.js new file mode 100644 index 000000000000..b947d093ef70 --- /dev/null +++ b/netwerk/test/unit_ipc/head_channels_clone.js @@ -0,0 +1,6 @@ +// +// Load standard base class for network tests into child process +// + +load("../unit/head_channels.js"); + diff --git a/netwerk/test/unit_ipc/test_simple_wrap.js b/netwerk/test/unit_ipc/test_simple_wrap.js new file mode 100644 index 000000000000..8c6957e94490 --- /dev/null +++ b/netwerk/test/unit_ipc/test_simple_wrap.js @@ -0,0 +1,7 @@ +// +// Run test script in content process instead of chrome (xpcshell's default) +// + +function run_test() { + run_test_in_child("../unit/test_simple.js"); +} diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index 9fe188447e69..f8aa1710864a 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -408,3 +408,67 @@ function do_get_profile() { .registerProvider(provider); return file.clone(); } + +/** + * This function loads head.js (this file) in the child process, so that all + * functions defined in this file (do_throw, etc) are available to subsequent + * sendCommand calls. It also sets various constants used by these functions. + * + * (Note that you may use sendCommand without calling this function first; you + * simply won't have any of the functions in this file available.) + */ +function do_load_child_test_harness() +{ + // Make sure this isn't called from child process + var runtime = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULRuntime); + if (runtime.processType != + Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT) + { + do_throw("run_test_in_child cannot be called from child!"); + } + + // Allow to be called multiple times, but only run once + if (typeof do_load_child_test_harness.alreadyRun != "undefined") + return; + do_load_child_test_harness.alreadyRun = 1; + + function addQuotes (str) { + return '"' + str + '"'; + } + var quoted_head_files = _HEAD_FILES.map(addQuotes); + var quoted_tail_files = _TAIL_FILES.map(addQuotes); + + sendCommand( + "const _HEAD_JS_PATH='" + _HEAD_JS_PATH + "'; " + + "const _HTTPD_JS_PATH='" + _HTTPD_JS_PATH + "'; " + + "const _HEAD_FILES=[" + quoted_head_files.join() + "];" + + "const _TAIL_FILES=[" + quoted_tail_files.join() + "];" + + "load(_HEAD_JS_PATH);"); +} + +/** + * Runs an entire xpcshell unit test in a child process (rather than in chrome, + * which is the default). + * + * This function returns immediately, before the test has completed. + * + * @param testFile + * The name of the script to run. Path format same as load(). + * @param optionalCallback. + * Optional function to be called (in parent) when test on child is + * complete. If provided, the function must call do_test_finished(); + */ +function run_test_in_child(testFile, optionalCallback) +{ + var callback = (typeof optionalCallback == 'undefined') ? + do_test_finished : optionalCallback; + + do_load_child_test_harness(); + + var testPath = do_get_file(testFile).path.replace(/\\/g, "/"); + do_test_pending(); + sendCommand("const _TEST_FILE=['" + testPath + "']; _execute_test();", + callback); +} + diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index 77ee849a52d0..d9488d290595 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -106,6 +106,7 @@ class XPCShellTests(object): failCount = 0 testharnessdir = os.path.dirname(os.path.abspath(__file__)) + headJSPath = testharnessdir.replace("\\", "/") + "/head.js" xpcshell = os.path.abspath(xpcshell) # we assume that httpd.js lives in components/ relative to xpcshell httpdJSPath = os.path.join(os.path.dirname(xpcshell), "components", "httpd.js").replace("\\", "/"); @@ -151,9 +152,12 @@ class XPCShellTests(object): pStderr = STDOUT # has to be loaded by xpchell: it can't load itself. + # - NOTE: if you rename/add any of the constants set here, update + # do_load_child_test_harness() in head.js xpcsCmd = [xpcshell, '-g', xrePath, '-j', '-s'] + \ ['-e', 'const _HTTPD_JS_PATH = "%s";' % httpdJSPath, - '-f', os.path.join(testharnessdir, 'head.js')] + '-e', 'const _HEAD_JS_PATH = "%s";' % headJSPath, + '-f', os.path.join(testharnessdir, 'head.js')] if debuggerInfo: xpcsCmd = [debuggerInfo["path"]] + debuggerInfo["args"] + xpcsCmd