• Home
Name Date Size #Lines LOC

..--

clients/04-Jul-2025-3,4462,684

testenv/04-Jul-2025-4,3983,556

.gitignoreD04-Jul-2025108 75

CMakeLists.txtD04-Jul-20251.7 KiB5750

Makefile.amD04-Jul-20252.3 KiB8150

README.mdD04-Jul-20257.5 KiB151101

config.ini.inD04-Jul-20251.2 KiB4035

conftest.pyD04-Jul-20254.4 KiB12484

requirements.txtD04-Jul-20251.1 KiB3130

scorecard.pyD04-Jul-202534.2 KiB860771

test_01_basic.pyD04-Jul-20256.8 KiB15298

test_02_download.pyD04-Jul-202531.1 KiB691570

test_03_goaway.pyD04-Jul-20255.8 KiB14685

test_04_stuttered.pyD04-Jul-20256.4 KiB14395

test_05_errors.pyD04-Jul-20256 KiB13684

test_06_eyeballs.pyD04-Jul-20254.9 KiB11366

test_07_upload.pyD04-Jul-202535.6 KiB751625

test_08_caddy.pyD04-Jul-202511.4 KiB254196

test_09_push.pyD04-Jul-20253.3 KiB8547

test_10_proxy.pyD04-Jul-202518.7 KiB371301

test_11_unix.pyD04-Jul-20254.3 KiB13384

test_12_reuse.pyD04-Jul-20256.3 KiB14699

test_13_proxy_auth.pyD04-Jul-20257.1 KiB155109

test_14_auth.pyD04-Jul-20255.9 KiB13884

test_15_tracing.pyD04-Jul-20254 KiB11371

test_16_info.pyD04-Jul-20257.9 KiB176122

test_17_ssl_use.pyD04-Jul-202520.1 KiB427347

test_18_methods.pyD04-Jul-20252.7 KiB7232

test_19_shutdown.pyD04-Jul-20257.5 KiB176123

test_20_websockets.pyD04-Jul-20255.8 KiB154106

test_30_vsftpd.pyD04-Jul-20259.1 KiB217167

test_31_vsftpds.pyD04-Jul-202511.5 KiB265207

README.md

1<!--
2Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
3
4SPDX-License-Identifier: curl
5-->
6
7# The curl HTTP Test Suite
8
9This is an additional test suite using a combination of Apache httpd and nghttpx servers to perform various tests beyond the capabilities of the standard curl test suite.
10
11# Usage
12
13The test cases and necessary files are in `tests/http`. You can invoke
14`pytest` from there or from the top level curl checkout and it finds all
15tests.
16
17```
18curl> pytest test/http
19platform darwin -- Python 3.9.15, pytest-6.2.0, py-1.10.0, pluggy-0.13.1
20rootdir: /Users/sei/projects/curl
21collected 5 items
22
23tests/http/test_01_basic.py .....
24```
25
26Pytest takes arguments. `-v` increases its verbosity and can be used several times. `-k <expr>` can be used to run only matching test cases. The `expr` can be something resembling a python test or just a string that needs to match test cases in their names.
27
28```
29curl/tests/http> pytest -vv -k test_01_02
30```
31
32runs all test cases that have `test_01_02` in their name. This does not have to be the start of the name.
33
34Depending on your setup, some test cases may be skipped and appear as `s` in
35the output. If you run pytest verbose, it also gives you the reason for
36skipping.
37
38# Prerequisites
39
40You need:
41
421. a recent Python, the `cryptography` module and, of course, `pytest`
432. an apache httpd development version. On Debian/Ubuntu, the package `apache2-dev` has this
443. a local `curl` project build
453. optionally, a `nghttpx` with HTTP/3 enabled or h3 test cases are skipped
46
47### Configuration
48
49Via curl's `configure` script you may specify:
50
51  * `--with-test-nghttpx=<path-of-nghttpx>` if you have nghttpx to use somewhere outside your `$PATH`.
52  * `--with-test-httpd=<httpd-install-path>` if you have an Apache httpd installed somewhere else. On Debian/Ubuntu it will otherwise look into `/usr/bin` and `/usr/sbin` to find those.
53  * `--with-test-caddy=<caddy-install-path>` if you have a Caddy web server installed somewhere else.
54  * `--with-test-vsftpd=<vsftpd-install-path>` if you have a vsftpd ftp  server installed somewhere else.
55
56## Usage Tips
57
58Several test cases are parameterized, for example with the HTTP version to use. If you want to run a test with a particular protocol only, use a command line like:
59
60```
61curl/tests/http> pytest -k "test_02_06 and h2"
62```
63
64Test cases can be repeated, with the `pytest-repeat` module (`pip install pytest-repeat`). Like in:
65
66```
67curl/tests/http> pytest -k "test_02_06 and h2" --count=100
68```
69
70which then runs this test case a hundred times. In case of flaky tests, you can make pytest stop on the first one with:
71
72```
73curl/tests/http> pytest -k "test_02_06 and h2" --count=100 --maxfail=1
74```
75
76which allow you to inspect output and log files for the failed run. Speaking of log files, the verbosity of pytest is also used to collect curl trace output. If you specify `-v` three times, the `curl` command is started with `--trace`:
77
78```
79curl/tests/http> pytest -vvv -k "test_02_06 and h2" --count=100 --maxfail=1
80```
81
82all of curl's output and trace file are found in `tests/http/gen/curl`.
83
84## Writing Tests
85
86There is a lot of [`pytest` documentation](https://docs.pytest.org/) with examples. No use in repeating that here. Assuming you are somewhat familiar with it, it is useful how *this* general test suite is setup. Especially if you want to add test cases.
87
88### Servers
89
90In `conftest.py` 3 "fixtures" are defined that are used by all test cases:
91
921. `env`: the test environment. It is an instance of class
93   `testenv/env.py:Env`. It holds all information about paths, availability of
94   features (HTTP/3), port numbers to use, domains and SSL certificates for
95   those.
962. `httpd`: the Apache httpd instance, configured and started, then stopped at
97   the end of the test suite. It has sites configured for the domains from
98   `env`. It also loads a local module `mod_curltest?` and makes it available
99   in certain locations. (more on mod_curltest below).
1003. `nghttpx`: an instance of nghttpx that provides HTTP/3 support. `nghttpx`
101   proxies those requests to the `httpd` server. In a direct mapping, so you
102   may access all the resources under the same path as with HTTP/2. Only the
103   port number used for HTTP/3 requests are different.
104
105`pytest` manages these fixture so that they are created once and terminated
106before exit. This means you can `Ctrl-C` a running pytest and the server then
107shutdowns. Only when you brutally chop its head off, might there be servers
108left behind.
109
110### Test Cases
111
112Tests making use of these fixtures have them in their parameter list. This tells pytest that a particular test needs them, so it has to create them. Since one can invoke pytest for just a single test, it is important that a test references the ones it needs.
113
114All test cases start with `test_` in their name. We use a double number scheme to group them. This makes it ease to run only specific tests and also give a short mnemonic to communicate trouble with others in the project. Otherwise you are free to name test cases as you think fitting.
115
116Tests are grouped thematically in a file with a single Python test class. This is convenient if you need a special "fixture" for several tests. "fixtures" can have "class" scope.
117
118There is a curl helper class that knows how to invoke curl and interpret its output. Among other things, it does add the local CA to the command line, so that SSL connections to the test servers are verified. Nothing prevents anyone from running curl directly, for specific uses not covered by the `CurlClient` class.
119
120### mod_curltest
121
122The module source code is found in `testenv/mod_curltest`. It is compiled using the `apxs` command, commonly provided via the `apache2-dev` package. Compilation is quick and done once at the start of a test run.
123
124The module adds 2 "handlers" to the Apache server (right now). Handler are pieces of code that receive HTTP requests and generate the response. Those handlers are:
125
126* `curltest-echo`: hooked up on the path `/curltest/echo`. This one echoes a request and copies all data from the request body to the response body. Useful for simulating upload and checking that the data arrived as intended.
127* `curltest-tweak`: hooked up on the path `/curltest/tweak`. This handler is more of a Swiss army knife. It interprets parameters from the URL query string to drive its behavior.
128  * `status=nnn`: generate a response with HTTP status code `nnn`.
129  * `chunks=n`: generate `n` chunks of data in the response body, defaults to 3.
130  * `chunk_size=nnn`: each chunk should contain `nnn` bytes of data. Maximum is 16KB right now.
131  * `chunkd_delay=duration`: wait `duration` time between writing chunks
132  * `delay=duration`: wait `duration` time to send the response headers
133  * `body_error=(timeout|reset)`: produce an error after the first chunk in the response body
134  * `id=str`: add `str` in the response header `request-id`
135
136`duration` values are integers, optionally followed by a unit. Units are:
137
138  * `d`: days (probably not useful here)
139  * `h`: hours
140  * `mi`: minutes
141  * `s`: seconds (the default)
142  * `ms`: milliseconds
143
144As you can see, `mod_curltest`'s tweak handler allow to simulate many kinds of
145responses. An example of its use is `test_03_01` where responses are delayed
146using `chunk_delay`. This gives the response a defined duration and the test
147uses that to reload `httpd` in the middle of the first request. A graceful
148reload in httpd lets ongoing requests finish, but closes the connection
149afterwards and tears down the serving process. The following request then
150needs to open a new connection. This is verified by the test case.
151