Table of Contents
- examples/ex_http_response.c
- Structures
- Functions
- Attributes
- Defines
- Functions Documentation
- function test_write
- function test_stream
- function test_status
- function test_range
- function test_headers
- function sink_write
- function producer_free
- function producer
- function process_args
- function main
- function head_is
- function expect_true
- function count_piece
- Attributes Documentation
- Macros Documentation
- Source code
examples/ex_http_response.c
Structures
| Name | |
|---|---|
| struct | sink an in-memory sink for n_http_response_write() |
| struct | producer_state what a test producer writes |
Functions
| Name | |
|---|---|
| void | test_write(void ) writing memory and file bodies, HEAD, partial and failing writes |
| void | test_stream(void ) streamed bodies: chunked framing, HTTP/1.0, HEAD, failures, ownership |
| void | test_status(void ) status codes and bodiless responses |
| void | test_range(void ) Range header parsing. |
| void | test_headers(void ) headers: validation, set/remove, framing |
| ssize_t | sink_write(void * ctx, const void * buf, size_t len) write function: accept at most s->chunk bytes |
| void | producer_free(void * user) free function of a producer's state |
| int | producer(void * user, N_HTTP_STREAM * out) producer: "data: N\n\n" pieces |
| int | process_args(int argc, char ** argv) read -V |
| int | main(int argc, char ** argv) run the checks |
| int | head_is(const N_HTTP_RESP * r, const char * want) text of the head of r, up to and excluding the Date line's value |
| void | expect_true(const char * what, int ok) count a failed check |
| void | count_piece(void * ctx) before_piece: count the calls |
Attributes
| Name | |
|---|---|
| int | piece_calls calls of count_piece() |
| int | log_level log level from -V |
| int | failures failed checks |
Defines
| Name | |
|---|---|
| RANGE(s, total) |
Functions Documentation
function test_write
static void test_write(
void
)
writing memory and file bodies, HEAD, partial and failing writes
function test_stream
static void test_stream(
void
)
streamed bodies: chunked framing, HTTP/1.0, HEAD, failures, ownership
function test_status
static void test_status(
void
)
status codes and bodiless responses
function test_range
static void test_range(
void
)
Range header parsing.
function test_headers
static void test_headers(
void
)
headers: validation, set/remove, framing
function sink_write
static ssize_t sink_write(
void * ctx,
const void * buf,
size_t len
)
write function: accept at most s->chunk bytes
Parameters:
- ctx the sink
- buf bytes
- len how many
Return: bytes taken, -1 to simulate a broken connection
function producer_free
static void producer_free(
void * user
)
free function of a producer's state
Parameters:
- user the producer_state
function producer
static int producer(
void * user,
N_HTTP_STREAM * out
)
producer: "data: N\n\n" pieces
Parameters:
- user the producer_state
- out the stream
Return: the state's ok
function process_args
static int process_args(
int argc,
char ** argv
)
read -V
Parameters:
- argc argument count
- argv arguments
Return: 0, or -1 on a bad argument
function main
int main(
int argc,
char ** argv
)
run the checks
Parameters:
- argc argument count
- argv arguments
Return: 0 when every check passes
function head_is
static int head_is(
const N_HTTP_RESP * r,
const char * want
)
text of the head of r, up to and excluding the Date line's value
Parameters:
- r the response
- want expected head, with the Date line removed
Return: non-zero when equal
function expect_true
static void expect_true(
const char * what,
int ok
)
count a failed check
Parameters:
- what the check
- ok its result
function count_piece
static void count_piece(
void * ctx
)
before_piece: count the calls
Parameters:
- ctx the sink (unused)
Attributes Documentation
variable piece_calls
static int piece_calls = 0;
calls of count_piece()
variable log_level
static int log_level = 3;
log level from -V
variable failures
static int failures = 0;
failed checks
Macros Documentation
define RANGE
#define RANGE(
s,
total
)
n_http_parse_range((s), strlen(s), (total), &a, &b)
Source code
/*
* Nilorea Library
* Copyright (C) 2005-2026 Castagnier Mickael
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "nilorea/n_common.h"
#include "nilorea/n_http_response.h"
#include "nilorea/n_log.h"
#include "nilorea/n_str.h"
static int log_level = LOG_ERR;
static int failures = 0;
static void expect_true(const char* what, int ok) {
if (!ok) {
n_log(LOG_ERR, "FAIL: %s", what);
failures++;
} else {
n_log(LOG_INFO, "ok: %s", what);
}
}
static int process_args(int argc, char** argv) {
int opt = 0;
while ((opt = getopt(argc, argv, "V:")) != -1) {
if (opt == 'V') {
log_level = atoi(optarg);
} else {
return -1;
}
}
return 0;
}
typedef struct {
N_STR* data;
size_t chunk;
long fail_at;
} sink;
static ssize_t sink_write(void* ctx, const void* buf, size_t len) {
sink* s = (sink*)ctx;
size_t n = len < s->chunk ? len : s->chunk;
if (s->fail_at >= 0 && s->data && (long)s->data->written >= s->fail_at)
return -1;
if (!nstrcat_ex(&s->data, (void*)buf, n, 1))
return -1;
return (ssize_t)n;
}
static int head_is(const N_HTTP_RESP* r, const char* want) {
N_STR* h = NULL;
char* date;
int res;
if (!n_http_response_head(r, &h))
return 0;
/* drop the Date line, which changes every second */
date = strstr(h->data, "Date: ");
if (date) {
char* end = strstr(date, "\r\n");
memmove(date, end + 2, strlen(end + 2) + 1);
h->written = strlen(h->data);
}
res = strcmp(h->data, want) == 0;
if (!res)
n_log(LOG_ERR, "head was:\n%s", h->data);
free_nstr(&h);
return res;
}
static void test_headers(void) {
N_HTTP_RESP* r = n_http_response_new(200);
N_STR* h = NULL;
expect_true("new", r != NULL);
if (!r)
return;
expect_true("add", n_http_response_add_header(r, "Content-Type", "text/html; charset=utf-8"));
expect_true("repeat allowed", n_http_response_add_header(r, "Set-Cookie", "a=1") && n_http_response_add_header(r, "Set-Cookie", "b=2"));
expect_true("value trimmed", n_http_response_add_header(r, "X-Trim", " v \t") && strcmp(n_http_response_get_header(r, "x-trim"), "v") == 0);
expect_true("CRLF in a value refused (response splitting)", !n_http_response_add_header(r, "Location", "/a\r\nSet-Cookie: evil=1"));
expect_true("LF in a value refused", !n_http_response_add_header(r, "Location", "/a\nb"));
expect_true("NUL-free control byte refused", !n_http_response_add_header(r, "X-A", "a\x01"));
expect_true("DEL refused", !n_http_response_add_header(r, "X-A", "a\x7f"));
expect_true("tab and UTF-8 accepted", n_http_response_add_header(r, "X-B", "a\tcaf\xc3\xa9"));
{
/* found by fuzzing: an empty value used to make the whole head fail */
N_HTTP_RESP* e = n_http_response_new(200);
expect_true("empty value accepted and serialized", n_http_response_add_header(e, "X-Empty", " ") &&
head_is(e, "HTTP/1.1 200 OK\r\nX-Empty: \r\nContent-Length: 0\r\nConnection: close\r\n\r\n"));
n_http_response_free(&e);
}
expect_true("bad name refused", !n_http_response_add_header(r, "X A", "v") && !n_http_response_add_header(r, "", "v") && !n_http_response_add_header(r, "X:A", "v"));
expect_true("Content-Length is the builder's", !n_http_response_add_header(r, "content-length", "5"));
expect_true("Transfer-Encoding is the builder's", !n_http_response_add_header(r, "Transfer-Encoding", "chunked"));
expect_true("Connection is the builder's", !n_http_response_add_header(r, "Connection", "keep-alive"));
expect_true("NULL value refused", !n_http_response_add_header(r, "X-C", NULL));
expect_true("set replaces every older one", n_http_response_set_header(r, "set-cookie", "c=3") && strcmp(n_http_response_get_header(r, "Set-Cookie"), "c=3") == 0);
expect_true("refused set keeps the old value", !n_http_response_set_header(r, "Content-Type", "x\r\n") && strcmp(n_http_response_get_header(r, "content-type"), "text/html; charset=utf-8") == 0);
expect_true("remove", n_http_response_remove_header(r, "X-B") == 1 && n_http_response_get_header(r, "X-B") == NULL);
expect_true("body", n_http_response_append(r, "hello", 5) && n_http_response_append(r, " world", 6));
expect_true("default: HTTP/1.1, close",
head_is(r,
"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nX-Trim: v\r\nset-cookie: c=3\r\n"
"Content-Length: 11\r\nConnection: close\r\n\r\n"));
n_http_response_set_connection(r, 1, 1, 0);
expect_true("HTTP/1.1 keep-alive sends no Connection",
head_is(r,
"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nX-Trim: v\r\nset-cookie: c=3\r\n"
"Content-Length: 11\r\n\r\n"));
n_http_response_set_connection(r, 1, 0, 0);
expect_true("HTTP/1.0 keep-alive says so",
head_is(r,
"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nX-Trim: v\r\nset-cookie: c=3\r\n"
"Content-Length: 11\r\nConnection: keep-alive\r\n\r\n"));
expect_true("bad version refused", !n_http_response_set_connection(r, 1, 2, 0));
expect_true("Date added", n_http_response_head(r, &h) && strstr(h->data, "\r\nDate: ") != NULL && strstr(h->data, " GMT\r\n") != NULL);
free_nstr(&h);
expect_true("caller's Date kept", n_http_response_set_header(r, "Date", "Thu, 01 Jan 1970 00:00:00 GMT") && n_http_response_head(r, &h) &&
strstr(h->data, "Date: Thu, 01 Jan 1970 00:00:00 GMT\r\n") != NULL && strstr(h->data + 20, "Date:") == strstr(h->data, "Date:"));
free_nstr(&h);
{
int i, full = 1;
N_HTTP_RESP* m = n_http_response_new(200);
for (i = 0; i < N_HTTP_RESPONSE_HEADERS_MAX; i++)
full = full && n_http_response_add_header(m, "X-N", "v");
expect_true("header cap reached", full && !n_http_response_add_header(m, "X-N", "v"));
n_http_response_free(&m);
}
n_http_response_free(&r);
expect_true("free sets NULL", r == NULL);
}
static void test_status(void) {
N_HTTP_RESP* r;
expect_true("reasons", strcmp(n_http_status_reason(404), "Not Found") == 0 && strcmp(n_http_status_reason(429), "Too Many Requests") == 0 &&
strcmp(n_http_status_reason(413), "Content Too Large") == 0 && strcmp(n_http_status_reason(299), "Success") == 0 &&
strcmp(n_http_status_reason(99), "") == 0 && strcmp(n_http_status_reason(600), "") == 0);
expect_true("status out of range refused", n_http_response_new(99) == NULL && n_http_response_new(600) == NULL);
r = n_http_response_new(304);
n_http_response_add_header(r, "ETag", "\"abc\"");
n_http_response_append(r, "ignored", 7);
n_http_response_set_connection(r, 1, 1, 0);
expect_true("304: no Content-Length", head_is(r, "HTTP/1.1 304 Not Modified\r\nETag: \"abc\"\r\n\r\n"));
expect_true("304: body length 0", n_http_response_body_length(r) == 0);
{
sink s = {NULL, 1000, -1};
expect_true("304: no body written", n_http_response_write(r, sink_write, &s) && s.data && strstr(s.data->data, "ignored") == NULL);
free_nstr(&s.data);
}
expect_true("set_status", n_http_response_set_status(r, 204) && !n_http_response_set_status(r, 1000));
expect_true("204: no Content-Length", head_is(r, "HTTP/1.1 204 No Content\r\nETag: \"abc\"\r\n\r\n"));
n_http_response_set_status(r, 302);
n_http_response_set_header(r, "Location", "/x/");
expect_true("302 with its body length", head_is(r, "HTTP/1.1 302 Found\r\nETag: \"abc\"\r\nLocation: /x/\r\nContent-Length: 7\r\n\r\n"));
n_http_response_free(&r);
r = n_http_response_new(404);
expect_true("empty body: Content-Length 0", head_is(r, "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"));
n_http_response_free(&r);
}
static void test_write(void) {
N_HTTP_RESP* r = n_http_response_new(200);
char path[] = "ex_http_response_XXXXXX";
int fd;
char data[200000];
size_t i;
n_http_response_append(r, "0123456789", 10);
{
sink s = {NULL, 7, -1};
expect_true("memory body written in 7-byte pieces", n_http_response_write(r, sink_write, &s) && s.data);
expect_true("ends with the body", s.data && s.data->written > 10 && memcmp(s.data->data + s.data->written - 14, "\r\n\r\n0123456789", 14) == 0);
free_nstr(&s.data);
}
n_http_response_set_connection(r, 0, 1, 1);
{
sink s = {NULL, 1000, -1};
expect_true("HEAD writes the head only, with the full length",
n_http_response_write(r, sink_write, &s) && s.data && strstr(s.data->data, "Content-Length: 10\r\n") &&
memcmp(s.data->data + s.data->written - 4, "\r\n\r\n", 4) == 0);
free_nstr(&s.data);
}
n_http_response_set_connection(r, 0, 1, 0);
{
sink s = {NULL, 3, 20};
expect_true("a failing write fails the response", n_http_response_write(r, sink_write, &s) == FALSE);
free_nstr(&s.data);
}
/* a file body: 200000 bytes, streamed in chunks, then a middle range */
for (i = 0; i < sizeof(data); i++)
data[i] = (char)('a' + i % 26);
fd = mkstemp(path);
expect_true("temp file", fd >= 0);
if (fd >= 0) {
int fd2;
expect_true("temp file written", write(fd, data, sizeof(data)) == (ssize_t)sizeof(data));
close(fd);
fd2 = open(path, O_RDONLY);
expect_true("file body", n_http_response_file(r, fd2, 0, (long long)sizeof(data)));
expect_true("file body length", n_http_response_body_length(r) == (long long)sizeof(data));
{
sink s = {NULL, 4093, -1};
expect_true("file body written", n_http_response_write(r, sink_write, &s) && s.data);
expect_true("file body bytes", s.data && s.data->written > sizeof(data) && memcmp(s.data->data + s.data->written - sizeof(data), data, sizeof(data)) == 0);
free_nstr(&s.data);
}
fd2 = open(path, O_RDONLY);
expect_true("file range", n_http_response_file(r, fd2, 100001, 26));
{
sink s = {NULL, 1000, -1};
expect_true("file range written", n_http_response_write(r, sink_write, &s) && s.data && strstr(s.data->data, "Content-Length: 26\r\n"));
expect_true("file range bytes", s.data && memcmp(s.data->data + s.data->written - 26, data + 100001, 26) == 0);
free_nstr(&s.data);
}
fd2 = open(path, O_RDONLY);
n_http_response_file(r, fd2, (long long)sizeof(data) - 5, 10);
{
sink s = {NULL, 1000, -1};
expect_true("file shorter than declared fails", n_http_response_write(r, sink_write, &s) == FALSE);
free_nstr(&s.data);
}
expect_true("bad file arguments refused", !n_http_response_file(r, -1, 0, 1) && !n_http_response_file(r, open(path, O_RDONLY), -1, 1));
expect_true("memory body replaces the file", n_http_response_append(r, "x", 1) && n_http_response_body_length(r) == 1);
unlink(path);
}
n_http_response_free(&r);
expect_true("NULL arguments", n_http_response_write(NULL, sink_write, NULL) == FALSE && n_http_response_head(NULL, NULL) == FALSE &&
n_http_response_body_length(NULL) == -1 && n_http_response_append(NULL, "a", 1) == FALSE);
n_http_response_free(NULL);
}
typedef struct {
int pieces;
int ok;
int freed;
int seen;
} producer_state;
static int piece_calls = 0;
static int producer(void* user, N_HTTP_STREAM* out) {
producer_state* p = (producer_state*)user;
char piece[32];
for (int i = 0; i < p->pieces; i++) {
snprintf(piece, sizeof(piece), "data: %d\n\n", i);
if (!n_http_stream_write(out, piece, strlen(piece)))
return FALSE;
p->seen++;
}
expect_true("an empty piece writes nothing", n_http_stream_write(out, "", 0));
return p->ok;
}
static void producer_free(void* user) {
((producer_state*)user)->freed = 1;
}
static void count_piece(void* ctx) {
(void)ctx;
piece_calls++;
}
static void test_stream(void) {
producer_state st = {3, TRUE, 0, 0};
N_HTTP_RESP* r = n_http_response_new(200);
n_http_response_set_header(r, "Content-Type", "text/event-stream");
expect_true("stream body", n_http_response_stream(r, producer, &st, producer_free));
expect_true("no declared length", n_http_response_body_length(r) == -1);
n_http_response_set_connection(r, 1, 1, 0);
expect_true("chunked head", head_is(r, "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nTransfer-Encoding: chunked\r\n\r\n"));
{
sink s = {NULL, 5, -1};
static const char want[] = "\r\n\r\n9\r\ndata: 0\n\n\r\n9\r\ndata: 1\n\n\r\n9\r\ndata: 2\n\n\r\n0\r\n\r\n";
expect_true("streamed in chunks", n_http_response_write_ex(r, sink_write, &s, count_piece) && s.data && st.seen == 3);
expect_true("before_piece before each piece and the last chunk", piece_calls == 4);
expect_true("chunk framing and the last chunk",
s.data && s.data->written > sizeof(want) - 1 && memcmp(s.data->data + s.data->written - (sizeof(want) - 1), want, sizeof(want) - 1) == 0);
free_nstr(&s.data);
}
/* HTTP/1.0: raw bytes, the connection closes after them */
st.seen = 0;
n_http_response_set_connection(r, 1, 0, 0);
expect_true("HTTP/1.0 head closes", head_is(r, "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\nConnection: close\r\n\r\n"));
{
sink s = {NULL, 1000, -1};
expect_true("HTTP/1.0 raw body", n_http_response_write(r, sink_write, &s) && s.data &&
memcmp(s.data->data + s.data->written - 27, "data: 0\n\ndata: 1\n\ndata: 2\n\n", 27) == 0);
free_nstr(&s.data);
}
/* HEAD: the producer does not run */
st.seen = 0;
n_http_response_set_connection(r, 1, 1, 1);
{
sink s = {NULL, 1000, -1};
expect_true("HEAD skips the producer", n_http_response_write(r, sink_write, &s) && st.seen == 0);
free_nstr(&s.data);
}
/* a broken connection stops the producer; a producer giving up fails the response */
n_http_response_set_connection(r, 1, 1, 0);
st.seen = 0;
{
sink s = {NULL, 1000, 70};
st.pieces = 100;
expect_true("a failing write stops the producer", n_http_response_write(r, sink_write, &s) == FALSE && st.seen < 100);
free_nstr(&s.data);
}
st.pieces = 1;
st.ok = FALSE;
{
sink s = {NULL, 1000, -1};
expect_true("a producer giving up fails the response", n_http_response_write(r, sink_write, &s) == FALSE);
free_nstr(&s.data);
}
expect_true("not freed while in use", st.freed == 0);
expect_true("a memory body replaces the stream and frees its state", n_http_response_append(r, "x", 1) && st.freed == 1 && n_http_response_body_length(r) == 1);
st.freed = 0;
expect_true("stream again", n_http_response_stream(r, producer, &st, producer_free));
n_http_response_free(&r);
expect_true("freed with the response", st.freed == 1);
st.freed = 0;
expect_true("bad arguments refused, state freed", !n_http_response_stream(NULL, producer, &st, producer_free) && st.freed == 1);
expect_true("NULL stream", n_http_stream_write(NULL, "a", 1) == FALSE);
}
static void test_range(void) {
long long a = -1, b = -1;
#define RANGE(s, total) n_http_parse_range((s), strlen(s), (total), &a, &b)
expect_true("a-b", RANGE("bytes=0-99", 1000) == N_HTTP_RANGE_OK && a == 0 && b == 99);
expect_true("a-", RANGE("bytes=900-", 1000) == N_HTTP_RANGE_OK && a == 900 && b == 999);
expect_true("suffix", RANGE("bytes=-100", 1000) == N_HTTP_RANGE_OK && a == 900 && b == 999);
expect_true("suffix longer than the body", RANGE("bytes=-5000", 1000) == N_HTTP_RANGE_OK && a == 0 && b == 999);
expect_true("end clamped", RANGE("bytes=990-5000", 1000) == N_HTTP_RANGE_OK && a == 990 && b == 999);
expect_true("start past the end", RANGE("bytes=1000-", 1000) == N_HTTP_RANGE_UNSATISFIABLE);
expect_true("empty suffix", RANGE("bytes=-0", 1000) == N_HTTP_RANGE_UNSATISFIABLE);
expect_true("empty body", RANGE("bytes=0-", 0) == N_HTTP_RANGE_UNSATISFIABLE);
expect_true("several ranges: whole body", RANGE("bytes=0-1,5-6", 1000) == N_HTTP_RANGE_NONE);
expect_true("other unit: whole body", RANGE("items=0-1", 1000) == N_HTTP_RANGE_NONE);
expect_true("reversed: whole body", RANGE("bytes=50-10", 1000) == N_HTTP_RANGE_NONE);
expect_true("garbage: whole body", RANGE("bytes=a-b", 1000) == N_HTTP_RANGE_NONE && RANGE("bytes=-", 1000) == N_HTTP_RANGE_NONE &&
RANGE("bytes=", 1000) == N_HTTP_RANGE_NONE && RANGE("bytes= 1-2", 1000) == N_HTTP_RANGE_NONE);
expect_true("huge number: whole body", RANGE("bytes=99999999999999999999-", 1000) == N_HTTP_RANGE_NONE);
expect_true("NULL: whole body", n_http_parse_range(NULL, 0, 10, &a, &b) == N_HTTP_RANGE_NONE);
#undef RANGE
}
int main(int argc, char** argv) {
if (process_args(argc, argv) != 0) {
fprintf(stderr, "usage: %s [-V LOG_LEVEL]\n", argv[0]);
return 1;
}
set_log_level(log_level);
test_headers();
test_status();
test_write();
test_stream();
test_range();
if (failures) {
n_log(LOG_ERR, "ex_http_response: %d failure(s)", failures);
return 1;
}
n_log(LOG_NOTICE, "ex_http_response: all checks passed");
return 0;
}
Modules
- AABB3D
- ACCEPT_POOL
- ALLEGRO4
- ALLEGRO5
- ANIM_LIB
- ASTAR
- ATLAS_LIB
- AVRO
- CLOCK_SYNC
- COMMONS
- CONFIGFILE
- CYPHER_BASE64
- CYPHER_VIGENERE
- DEAD_RECKONING
- ENUMS
- EXCEPTIONS
- GAME_ENV
- GIT
- GUI
- HASH_TABLE
- ISOMETRIC_ENGINE
- LIST
- LOG
- LOGNODUP
- LZ4
- NETWORKING
- NETWORK_MSG
- N_COOKIES
- N_DIFF
- N_DIGEST
- N_DISK_CACHE
- N_DNS
- N_ECC
- N_ENTROPY
- N_FILES
- N_FLUIDS
- N_GUI_COLOR
- N_GUI_COLORWHEEL
- N_GUI_CURVE
- N_GUI_GRID
- N_GUI_POPUP
- N_HEX
- N_HTTP3
- N_HTTP_COOKIE
- N_HTTP_FORM
- N_HTTP_MIME
- N_HTTP_REQ
- N_HTTP_RESP
- N_HTTP_ROUTER
- N_HTTP_SERVER
- N_ICC
- N_JSON
- N_KAFKA
- N_LINALG
- N_MODULE
- N_OPENSSL_COMPAT
- N_PRETTY
- N_PTH
- N_QUERY
- N_RANDOM
- N_SHA256
- N_STR
- N_TIFF
- N_TIME
- N_USER
- N_X509
- N_ZIP
- PARTICLES
- PCRE
- PHYSICS
- SIGNALS
- STACK
- THREADS
- TRAJECTORY
- TREE
- ZLIB