106 lines
5.1 KiB
Markdown
106 lines
5.1 KiB
Markdown
# tester42 — official 42 webserv testers
|
|
|
|
Binaries attached to the intra evaluation scale, plus the fixtures they require.
|
|
All of them are Go programs, not stripped, so their expectations can be read out of the
|
|
binaries directly — `strings`, `nm`, and `go tool objdump`, which still shows the original
|
|
source file and line numbers. Nothing below is guesswork, and the whole sequence has also
|
|
been executed once against a probe stub.
|
|
|
|
## Layout and provenance
|
|
|
|
```
|
|
official/ tester, cgi_tester ← downloaded from intra. THE ONLY TRUSTED ONES.
|
|
YoupiBanane/ the fixture tree the tester requires (contents dictated by the tester
|
|
itself — see its printed instructions below, so it is reconstructable)
|
|
```
|
|
|
|
Both official binaries are **Linux ELF x86-64** and cannot run on macOS. They run in the
|
|
project's Linux container, which is also the platform the school VMs use.
|
|
|
|
## What the tester requires (verbatim from the binary)
|
|
|
|
```
|
|
- Download the cgi_test executable on the host
|
|
- Create a directory YoupiBanane with:
|
|
- A file name youpi.bad_extension
|
|
- A file name youpi.bla
|
|
- A sub directory called nop
|
|
- A file name youpi.bad_extension in nop
|
|
- A file name other.pouic in nop
|
|
- A sub directory called Yeah
|
|
- A file name not_happy.bad_extension in Yeah
|
|
- / must answer to GET request ONLY
|
|
- /directory/ must answer to GET request and the root of it would be the repository
|
|
YoupiBanane and if no file are requested, it should search for youpi.bad_extension files
|
|
- /post_body must answer anything to POST request with a maxBody of 100
|
|
- Any file with .bla as extension must answer to POST request by calling the cgi_test executable
|
|
```
|
|
|
|
## Test cases found in the binary
|
|
|
|
The complete executed order has now been verified against a passing probe stub.
|
|
|
|
| Area | Evidence in binary |
|
|
|---|---|
|
|
| `Test GET` | `GET on /directory/nop`, `directory/Yeah/not_happy.bad_extension`, `directory/nop/other.pouic` |
|
|
| 404 paths | `directory/oulalala`, `directory/nop/other.pouac` |
|
|
| `Test HEAD` | `HEAD /` is exercised and must return `405`; general HEAD support is not tested |
|
|
| `Test POST` | `/post_body` with `maxBody 100` |
|
|
| CGI | `Post on /directory/youpi.bla with size 100000000` (100 MB body into CGI), `bad cgi returned body content` |
|
|
| Concurrency | `Test multiple workers(%d) doing multiple times(%d)`, `client disconnected` |
|
|
|
|
`FATAL ERROR ON LAST TEST:` is the message printed when a case fails.
|
|
|
|
## CGI environment the cgi_tester reads
|
|
|
|
```
|
|
REQUEST_METHOD SERVER_PROTOCOL CONTENT_LENGTH CONTENT_TYPE
|
|
QUERY_STRING PATH_INFO HTTP_HOST HTTP_<any request header>
|
|
```
|
|
|
|
The binary vendors Go's `net/http/cgi`, so the contract is that package's, not folklore.
|
|
Three of these are failure modes rather than niceties:
|
|
|
|
- **`SERVER_PROTOCOL` is mandatory.** `RequestFromMap` calls `http.ParseHTTPVersion` on it and
|
|
aborts with `cgi: invalid SERVER_PROTOCOL version` if it is missing. The CGI never runs.
|
|
- **`PATH_INFO` must equal the request path**, with `SCRIPT_NAME` left empty. The handler
|
|
compares `os.Getenv("PATH_INFO")` against `r.URL.Path` and answers `500 PATH_INFO incorrect`
|
|
otherwise. Splitting them the way RFC 3875 prescribes **fails this tester**.
|
|
- **Arbitrary headers must be exported as `HTTP_*`** (uppercase, dashes to underscores). One
|
|
test reads `X-SECRET-HEADER-FOR-TEST`, so `HTTP_X_SECRET_HEADER_FOR_TEST` has to be there.
|
|
- `CONTENT_LENGTH` must be exact — including for the 100 MB POST. Wrong value gives
|
|
`cgi: bad CONTENT_LENGTH in environment`; a missing one makes the CGI read zero bytes,
|
|
because `Request()` wraps stdin in `io.LimitReader(os.Stdin, r.ContentLength)`.
|
|
- `CONTENT_TYPE` arrives as `test/file`. Not a real MIME type — forward it verbatim.
|
|
|
|
Its output starts with a `Status: NNN Text` header, which the server must turn into the HTTP
|
|
status line rather than forward. No `Content-Length` is emitted: EOF ends the body.
|
|
|
|
## Scope implications
|
|
|
|
Passing this tester requires more than the subject text asks for:
|
|
|
|
- **location matched by extension** (`*.bla`), not only by path prefix, and taking precedence
|
|
over the prefix match so that `POST /directory/youpi.bla` reaches the CGI while
|
|
`GET` on the same path serves the file
|
|
- **`alias` semantics** distinct from `root`: `/directory/` maps onto `YoupiBanane`, which has
|
|
no `directory/` subtree, so plain `root` cannot express it
|
|
- **per-location body limit** (`/post_body`, 100 bytes), enforced on the **decoded** body —
|
|
every POST the tester sends is chunked, so there is no `Content-Length` to check
|
|
- a 100 MB request body streamed into a CGI without buffering it all in memory
|
|
|
|
Nested `location` blocks are *not* required by this binary; they are kept in the config
|
|
grammar because the grammar is expensive to change later, not because a test needs them.
|
|
|
|
This official binary does **not** execute PUT or DELETE. DELETE and uploads remain mandatory
|
|
because the subject and evaluation checklist require them; they need project-owned tests.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
# inside the Linux container, from the directory that contains YoupiBanane
|
|
./official/tester http://localhost:8000
|
|
```
|
|
|
|
The config must point the `.bla` CGI at `official/cgi_tester`.
|