1 # Networking Test Guidelines
3 This is a high level document to introduce the different test types that are used in necko. The target audience is newcomer of necko team.
7 We only introduce tests under [netwerk/test](https://searchfox.org/mozilla-central/source/netwerk/test) folder in this section.
9 - [Chrome Tests](https://firefox-source-docs.mozilla.org/testing/chrome-tests/index.html)
10 - We usually write chrome tests when the code to be tested needs a browser windows to load some particular resources.
11 - Path: [netwerk/test/browser](https://searchfox.org/mozilla-central/source/netwerk/test/browser)
12 - [Reftest](https://firefox-source-docs.mozilla.org/testing/webrender/index.html)
13 - Rarely used in necko.
14 - [Mochitest](https://firefox-source-docs.mozilla.org/testing/mochitest-plain/index.html)
15 - Used when the code to be tested can be triggered by WebIDL. e.g., WebSocket and XMLHttpRequest.
16 - Path: [netwerk/test/mochitests](https://searchfox.org/mozilla-central/source/netwerk/test/mochitests)
17 - [XPCShell tests](https://firefox-source-docs.mozilla.org/testing/xpcshell/index.html#xpcshell-tests)
18 - Mostly used in necko to test objects that can be accessed by JS. e.g., `nsIHttpChannel`.
19 - Path: [netwerk/test/unit](https://searchfox.org/mozilla-central/source/netwerk/test/unit)
20 - [GTest](https://firefox-source-docs.mozilla.org/gtest/index.html)
21 - Useful when the code doesn't need a http server.
22 - Useful when writing code regarding to parsing strings. e.g., [Parsing Server Timing Header](https://searchfox.org/mozilla-central/rev/0249c123e74640ed91edeabba00649ef4d929372/netwerk/test/gtest/TestServerTimingHeader.cpp)
23 - [Performance tests](https://firefox-source-docs.mozilla.org/testing/perfdocs/index.html)
24 - Current tests in [netwerk/test/perf](https://searchfox.org/mozilla-central/source/netwerk/test/perf) are all for testing `HTTP/3` code.
26 There are also [web-platform-tests](https://firefox-source-docs.mozilla.org/web-platform/index.html) that is related to necko. We don't usually write new `web-platform-tests`. However, we do have lots of `web-platform-tests` for XHR, Fetch, and WebSocket.
28 ## Running Necko xpcshell-tests
32 Run all xpcshell-tests:
35 ./mach xpcshell-test netwerk/test/unit
38 Note that xpcshell-tests are run in parallel, sometimes we want to run them sequentially for debugging.
41 ./mach xpcshell-test --sequential netwerk/test/unit
47 ./mach xpcshell-test netwerk/test/unit/test_http3.js
50 Run with socket process enabled:
53 ./mach xpcshell-test --setpref="network.http.network_access_on_socket_process.enabled=true" netwerk/test/unit/test_http3.js
56 We usually debug networking issues with `HTTP Logging`. To enable logging when running tests:
59 MOZ_LOG=nsHttp:5 ./mach xpcshell-test netwerk/test/unit/test_http3.js
64 First of all, we need to know [Fuzzy Selector](https://firefox-source-docs.mozilla.org/tools/try/selectors/fuzzy.html), which is the tool we use to select which test to run on try. If you already know that your code change can be covered by necko xpcshell-tests, you can use the following command to run all tests in `netwerk/test/unit` on try.
67 ./mach try fuzzy netwerk/test/unit
70 Run a single test on try:
73 ./mach try fuzzy netwerk/test/unit/test_http3.js
76 Sometimes we want to debug the failed test on try with logging enabled:
79 ./mach try fuzzy --env "MOZ_LOG=nsHttp:5,nsHostResolver:5" netwerk/tesst/unit/test_http3.js
82 Note that it's not usually a good idea to enabling logging when running all tests in a folder on try, since the raw log file can be really huge. The log file might be not available if the size exceeds the limit on try.
83 In the case that your code change is too generic or you are not sure which tests to run, you can use [Auto Selector](https://firefox-source-docs.mozilla.org/tools/try/selectors/auto.html) to let it select tests for you.
85 ## Debugging intermittent test failures
87 There are a lot of intermittent failures on try (usually not able to reproduce locally). Debugging these failures can be really annoying and time consuming. Here are some general guidelines to help you debug intermittent failures more efficiently.
89 - Identify whether the failure is caused by your code change.
90 - Try to reproduce the intermittent failure locally. This is the most straightforward way. Adding `--verify` flag is also helpful when debugging locally (see this [document](https://firefox-source-docs.mozilla.org/testing/test-verification/index.html) for more details).
91 - We can check the failure summery on try to see if there is already a bug filed for this test failure. If yes, it's likely this is not caused by your code change.
92 - Re-trigger the failed test a few times and see if it passed. This can be easily done by clicking the `Push Health` button.
93 - Looking for similar failures happening now on other submissions. This can be done by:
95 click on failing job -> read failure summary -> find similar ones by other authors in similar jobs
97 - To re-run the failed test suite more times, you could add `rebuild` option to `./mach try`. For example, the following command allows to run necko xpcshell-tests 20 times on try.
99 ./mach try fuzzy netwerk/test/unit --rebuild 20
101 - In the case that we really need to debug an intermittent test failure, see this [document](https://firefox-source-docs.mozilla.org/devtools/tests/debugging-intermittents.html) first for some general tips. Unfortunately, there is no easy way to debug this. One can try to isolate the failed test first and enable `HTTP logging` on try to collect the log for further analysis.
103 ## Writing Necko XPCShell tests
105 The most typical form of necko xpcsehll-test is creating an HTTP server and test your code by letting the server return some specific responses (e.g., `103 Early Hint`). We will only introduce how to write this kind of test in this document.
107 - Code at server side
109 After [bug 1756557](https://bugzilla.mozilla.org/show_bug.cgi?id=1756557), it is possible to create a `nodejs` HTTP server in your test code. This saves us some time for writing code at the server side by reusing the HTTP module provided by `nodejs`.
110 This is what it looks like to create a simple HTTP server:
113 let server = new NodeHTTPServer();
114 await server.start();
115 registerCleanupFunction(async () => {
118 await server.registerPathHandler("/test", (req, resp) => {
124 We can also create a `HTTP/2` server easily by replacing `NodeHTTPServer` with `NodeHTTP2Server` and adding the server certification.
127 let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
130 addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
131 let server = new NodeHTTP2Server();
134 - Code at client side
136 The recommend way is to create and open an HTTP channel and handle the response with a `Promise` asynchronously.
137 The code would be like:
140 function makeChan(uri) {
141 let chan = NetUtil.newChannel({
143 loadUsingSystemPrincipal: true,
144 }).QueryInterface(Ci.nsIHttpChannel);
145 chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
148 let chan = makeChan(`http://localhost:${server.port()}/test`);
149 let req = await new Promise(resolve => {
150 chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
154 This is what it looks like to put everything together:
157 add_task(async function test_http() {
158 let server = new NodeHTTPServer();
159 await server.start();
160 registerCleanupFunction(async () => {
163 await server.registerPathHandler("/test", (req, resp) => {
167 let chan = makeChan(`http://localhost:${server.port()}/test`);
168 let req = await new Promise(resolve => {
169 chan.asyncOpen(new ChannelListener(resolve, null, CL_ALLOW_UNKNOWN_CL));
171 equal(req.status, Cr.NS_OK);
172 equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
173 equal(req.QueryInterface(Ci.nsIHttpChannel).protocolVersion, "http/1.1");