master ohmu/fastfetch-openbsd / tests / networking.c
ohmu  ·  2026-10-15
 1#include "common/networking.h"
 2
 3#include <stdio.h>
 4#include <stdlib.h>
 5#include <string.h>
 6
 7static void verify(bool expression, const char* expressionStr, int lineNo) {
 8    if (expression) {
 9        return;
10    }
11
12    fprintf(stderr, "[%d] %s\n", lineNo, expressionStr);
13    exit(1);
14}
15
16#define VERIFY(expression) verify((expression), #expression, __LINE__)
17
18static FFNetworkingTransferEncoding parse(const char* value) {
19    return ffNetworkingParseTransferEncoding(value, (uint32_t) strlen(value));
20}
21
22int main(void) {
23    {
24        VERIFY(parse("chunked") == FF_NETWORKING_TE_CHUNKED);
25        VERIFY(parse("Chunked") == FF_NETWORKING_TE_CHUNKED);
26        VERIFY(parse("  chunked  ") == FF_NETWORKING_TE_CHUNKED);
27        VERIFY(parse("chunked\t") == FF_NETWORKING_TE_CHUNKED);
28
29        // A coding chain leaves the payload encoded, so only a lone `chunked` is decodable
30        VERIFY(parse("gzip, chunked") == FF_NETWORKING_TE_UNSUPPORTED);
31        VERIFY(parse("gzip,chunked") == FF_NETWORKING_TE_UNSUPPORTED);
32        VERIFY(parse("chunked, gzip") == FF_NETWORKING_TE_UNSUPPORTED);
33        VERIFY(parse("gzip") == FF_NETWORKING_TE_UNSUPPORTED);
34        VERIFY(parse("x-chunked") == FF_NETWORKING_TE_UNSUPPORTED);
35        VERIFY(parse("chunkedx") == FF_NETWORKING_TE_UNSUPPORTED);
36
37        VERIFY(parse("") == FF_NETWORKING_TE_NONE);
38        VERIFY(parse(" , ") == FF_NETWORKING_TE_NONE);
39    }
40
41    {
42        // The lookup is restricted to the header block, so a body that happens to contain a
43        // `Transfer-Encoding:` line can never be mistaken for a header
44        const char* response = "HTTP/1.1 200 OK\r\nContent-Length: 4\r\n\r\nTransfer-Encoding: chunked\r\n";
45        uint32_t headerEnd = (uint32_t) (strstr(response, "\r\n\r\n") - response);
46        uint32_t valueLen = 0;
47
48        VERIFY(ffNetworkingFindHeader(response, headerEnd, "Transfer-Encoding:", &valueLen) == nullptr);
49
50        const char* clHeader = ffNetworkingFindHeader(response, headerEnd, "Content-Length:", &valueLen);
51        VERIFY(clHeader != nullptr && valueLen == 1 && *clHeader == '4');
52    }
53
54    {
55        uint32_t consumed = 0;
56        const char* complete = "5\r\nhello\r\n0\r\n\r\n";
57        VERIFY(ffNetworkingChunkedComplete(complete, (uint32_t) strlen(complete), &consumed) == 1);
58        VERIFY(consumed == strlen(complete));
59
60        const char* withTrailer = "5\r\nhello\r\n0\r\nX-Foo: bar\r\n\r\n";
61        VERIFY(ffNetworkingChunkedComplete(withTrailer, (uint32_t) strlen(withTrailer), &consumed) == 1);
62        VERIFY(consumed == strlen(withTrailer));
63
64        const char* partial = "5\r\nhel";
65        VERIFY(ffNetworkingChunkedComplete(partial, (uint32_t) strlen(partial), &consumed) == 0);
66
67        const char* malformed = "5\r\nhelloXX0\r\n\r\n";
68        VERIFY(ffNetworkingChunkedComplete(malformed, (uint32_t) strlen(malformed), &consumed) == -1);
69    }
70
71    {
72        // Decoding replaces the framing header with a matching Content-Length
73        FFstrbuf response = ffStrbufCreateS("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n");
74        uint32_t headerEnd = (uint32_t) (strstr(response.chars, "\r\n\r\n") - response.chars);
75
76        VERIFY(ffNetworkingDecodeChunked(&response, &headerEnd));
77        VERIFY(headerEnd == (uint32_t) (strstr(response.chars, "\r\n\r\n") - response.chars));
78        VERIFY(ffStrbufContainS(&response, "Content-Length: 5"));
79        VERIFY(!ffStrbufContainS(&response, "Transfer-Encoding"));
80        VERIFY(ffStrbufEndsWithS(&response, "hello"));
81
82        ffStrbufDestroy(&response);
83    }
84
85    puts("All networking tests passed!");
86    return 0;
87}