Add tests for some utils
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,6 +3,8 @@
|
||||
!src/**
|
||||
!doc
|
||||
!doc/**
|
||||
!test
|
||||
!test/**
|
||||
!Makefile
|
||||
!.gitignore
|
||||
!README.md
|
||||
|
10
Makefile
10
Makefile
@ -5,7 +5,7 @@ LIBS=-lssl -lcrypto -lmagic -lz -lmaxminddb -lbrotlienc
|
||||
|
||||
DEBIAN_OPTS=-D CACHE_MAGIC_FILE="\"/usr/share/file/magic.mgc\"" -D PHP_FPM_SOCKET="\"/var/run/php/php7.4-fpm.sock\""
|
||||
|
||||
.PHONY: all prod debug default permit clean
|
||||
.PHONY: all prod debug default permit clean test
|
||||
all: prod
|
||||
default: bin bin/lib bin/libsesimos.so bin/sesimos
|
||||
prod: CFLAGS += -O3
|
||||
@ -14,6 +14,10 @@ debug: default
|
||||
debian: CFLAGS += $(DEBIAN_OPTS)
|
||||
debian: prod
|
||||
|
||||
test: CFLAGS += -include test/mock_*.h
|
||||
test: bin bin/test
|
||||
bin/test
|
||||
|
||||
|
||||
bin:
|
||||
mkdir -p bin
|
||||
@ -22,6 +26,10 @@ bin/lib:
|
||||
mkdir -p bin/lib
|
||||
|
||||
|
||||
bin/test: test/mock_*.c test/test_*.c src/lib/utils.c src/lib/sock.c
|
||||
$(CC) -o $@ $(CFLAGS) $^ -lcriterion
|
||||
|
||||
|
||||
bin/%.o: src/%.c
|
||||
$(CC) -c -o $@ $(CFLAGS) $<
|
||||
|
||||
|
@ -179,8 +179,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
int change_proto = strncmp(uri.uri, "/.well-known/", 13) != 0 && !client->enc;
|
||||
if (strcmp(uri.uri, buf0) != 0 || change_proto) {
|
||||
res.status = http_get_status(308);
|
||||
size = sizeof(buf0);
|
||||
url_encode(uri.uri, buf0, &size);
|
||||
size = url_encode(uri.uri, strlen(uri.uri), buf0, sizeof(buf0));
|
||||
if (change_proto) {
|
||||
p_len = snprintf(buf1, sizeof(buf1), "https://%s%s", host, buf0);
|
||||
if (p_len < 0 || p_len >= sizeof(buf1)) {
|
||||
|
@ -15,69 +15,77 @@
|
||||
|
||||
char *log_prefix;
|
||||
|
||||
static const char base64_encode_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const int base64_mod_table[3] = {0, 2, 1};
|
||||
|
||||
|
||||
char *format_duration(unsigned long micros, char *buf) {
|
||||
if (micros < 10000) {
|
||||
sprintf(buf, "%.1f ms", (double) micros / 1000);
|
||||
} else if (micros < 1000000) {
|
||||
sprintf(buf, "%li ms", micros / 1000);
|
||||
} else if (micros < 60000000) {
|
||||
} else if (micros < 1000000 - 1000) {
|
||||
sprintf(buf, "%.0f ms", (double) micros / 1000);
|
||||
} else if (micros < 60000000 - 1000000) {
|
||||
sprintf(buf, "%.1f s", (double) micros / 1000000);
|
||||
} else if (micros < 6000000000) {
|
||||
sprintf(buf, "%.1f min", (double) micros / 1000000 / 60);
|
||||
} else {
|
||||
sprintf(buf, "%li min", micros / 1000000 / 60);
|
||||
sprintf(buf, "%.0f min", (double) micros / 1000000 / 60);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int url_encode_component(const char *str, char *enc, long *size) {
|
||||
char *ptr = enc;
|
||||
char ch;
|
||||
memset(enc, 0, *size);
|
||||
for (int i = 0; i < strlen(str); i++, ptr++) {
|
||||
if ((ptr - enc) >= *size) {
|
||||
return -1;
|
||||
int url_encode_component(const void *in, size_t size_in, char *out, size_t size_out) {
|
||||
int size = 0;
|
||||
|
||||
// Encode control characters
|
||||
for (int i = 0; i < size_in; i++) {
|
||||
unsigned char ch = ((unsigned char *) in)[i];
|
||||
if (ch == ' ') {
|
||||
ch = '+';
|
||||
} else if (
|
||||
ch <= 0x20 || ch >= 0x7F ||
|
||||
!((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') ||
|
||||
ch == '-' || ch == '_' || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\'' ||
|
||||
ch == '(' || ch == ')')
|
||||
) {
|
||||
size += 3;
|
||||
if (size < size_out) sprintf(out + size - 3, "%%%02X", ch);
|
||||
ch = 0;
|
||||
}
|
||||
ch = str[i];
|
||||
if (ch == ':' || ch == '/' || ch == '?' || ch == '#' || ch == '[' || ch == ']' || ch == '@' || ch == '!' ||
|
||||
ch == '$' || ch == '&' || ch == '\'' || ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
|
||||
ch == ';' || ch == '=' || ch < ' ' || ch > '~') {
|
||||
if ((ptr - enc + 2) >= *size) {
|
||||
return -1;
|
||||
}
|
||||
sprintf(ptr, "%%%02X", ch);
|
||||
ptr += 2;
|
||||
} else if (ch == ' ') {
|
||||
ptr[0] = '+';
|
||||
} else {
|
||||
ptr[0] = ch;
|
||||
|
||||
if (ch != 0) {
|
||||
size++;
|
||||
if (size < size_out) out[size - 1] = (char) ch;
|
||||
}
|
||||
}
|
||||
*size = ptr - enc;
|
||||
return 0;
|
||||
|
||||
// Set terminating null byte
|
||||
if (size_out > 0) out[size < size_out ? size : size_out - 1] = 0;
|
||||
|
||||
// Return theoretical size
|
||||
return size;
|
||||
}
|
||||
|
||||
int url_encode(const char *str, char *enc, long *size) {
|
||||
char *ptr = enc;
|
||||
unsigned char ch;
|
||||
memset(enc, 0, *size);
|
||||
for (int i = 0; i < strlen(str); i++, ptr++) {
|
||||
if ((ptr - enc) >= *size) {
|
||||
return -1;
|
||||
}
|
||||
ch = str[i];
|
||||
if (ch > 0x7F || ch == ' ') {
|
||||
if ((ptr - enc + 2) >= *size) {
|
||||
return -1;
|
||||
}
|
||||
sprintf(ptr, "%%%02X", ch);
|
||||
ptr += 2;
|
||||
int url_encode(const void *in, size_t size_in, char *out, size_t size_out) {
|
||||
int size = 0;
|
||||
|
||||
// Encode control characters
|
||||
for (int i = 0; i < size_in; i++) {
|
||||
unsigned char ch = ((unsigned char *) in)[i];
|
||||
if (ch <= 0x20 || ch >= 0x7F) {
|
||||
size += 3;
|
||||
if (size < size_out) sprintf(out + size - 3, "%%%02X", ch);
|
||||
} else {
|
||||
ptr[0] = (char) ch;
|
||||
size++;
|
||||
if (size < size_out) out[size - 1] = (char) ch;
|
||||
}
|
||||
}
|
||||
*size = ptr - enc;
|
||||
return 0;
|
||||
|
||||
// Set terminating null byte
|
||||
if (size_out > 0) out[size < size_out ? size : size_out - 1] = 0;
|
||||
|
||||
// Return theoretical size
|
||||
return size;
|
||||
}
|
||||
|
||||
int url_decode(const char *str, char *dec, long *size) {
|
||||
|
@ -21,9 +21,6 @@
|
||||
|
||||
extern char *log_prefix;
|
||||
|
||||
static const char base64_encode_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const int base64_mod_table[3] = {0, 2, 1};
|
||||
|
||||
|
||||
#define out_1(fmt) fprintf(stdout, "%s" fmt "\n", log_prefix)
|
||||
#define out_2(fmt, args...) fprintf(stdout, "%s" fmt "\n", log_prefix, args)
|
||||
@ -37,9 +34,9 @@ static const int base64_mod_table[3] = {0, 2, 1};
|
||||
|
||||
char *format_duration(unsigned long micros, char *buf);
|
||||
|
||||
int url_encode_component(const char *str, char *enc, long *size);
|
||||
int url_encode_component(const void *in, size_t size_in, char *out, size_t size_out);
|
||||
|
||||
int url_encode(const char *str, char *enc, long *size);
|
||||
int url_encode(const void *in, size_t size_in, char *out, size_t size_out);
|
||||
|
||||
int url_decode(const char *str, char *dec, long *size);
|
||||
|
||||
|
28
test/mock_socket.c
Normal file
28
test/mock_socket.c
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mock_socket.h"
|
||||
|
||||
int mock_socket_send_mode;
|
||||
|
||||
static int sockets[256] = {0};
|
||||
static int n_sockets = 0;
|
||||
|
||||
int mock_socket(int domain, int type, int protocol) {
|
||||
printf("SOCKET\n");
|
||||
return (n_sockets++) + 100;
|
||||
}
|
||||
|
||||
ssize_t mock_send(int fd, const void *buf, size_t n, int flags) {
|
||||
printf("SEND\n");
|
||||
if (mock_socket_send_mode == MOCK_SOCKET_MODE_EINTR) {
|
||||
errno = EINTR;
|
||||
return rand() % ((ssize_t) n) - 1;
|
||||
} else if (mock_socket_send_mode == MOCK_SOCKET_MODE_CLOSED) {
|
||||
errno = 0; // TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (ssize_t) n;
|
||||
}
|
20
test/mock_socket.h
Normal file
20
test/mock_socket.h
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
#ifndef SESIMOS_MOCK_SOCKET_H
|
||||
#define SESIMOS_MOCK_SOCKET_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MOCK_SOCKET_MODE_SUCCESS 0
|
||||
#define MOCK_SOCKET_MODE_EINTR 1
|
||||
#define MOCK_SOCKET_MODE_CLOSED 2
|
||||
|
||||
#define socket(args...) mock_socket(args)
|
||||
#define send(args...) mock_send(args)
|
||||
|
||||
extern int mock_socket_send_mode;
|
||||
|
||||
int mock_socket(int domain, int type, int protocol);
|
||||
|
||||
ssize_t mock_send(int fd, const void *buf, size_t n, int flags);
|
||||
|
||||
#endif //SESIMOS_MOCK_SOCKET_H
|
33
test/mock_ssl.c
Normal file
33
test/mock_ssl.c
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
|
||||
int SSL_write(SSL *ssl, const void *buf, int num) {
|
||||
return num;
|
||||
}
|
||||
|
||||
int SSL_read(SSL *ssl, void *buf, int num) {
|
||||
return num;
|
||||
}
|
||||
|
||||
int SSL_peek(SSL *ssl, void *buf, int num) {
|
||||
return num;
|
||||
}
|
||||
|
||||
int SSL_get_error(const SSL *s, int ret_code) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ERR_reason_error_string(unsigned long e) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int SSL_shutdown(SSL *s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SSL_free(SSL *ssl) {}
|
||||
|
||||
unsigned long ERR_get_error(void) {
|
||||
return 0;
|
||||
}
|
15
test/test_sock.c
Normal file
15
test/test_sock.c
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
#include <criterion/criterion.h>
|
||||
#include "mock_socket.h"
|
||||
#include "../src/lib/sock.h"
|
||||
|
||||
|
||||
Test(sock, sock_send_1) {
|
||||
int fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
sock s;
|
||||
s.enc = 0;
|
||||
s.socket = fd;
|
||||
|
||||
long ret = sock_send(&s, "Hello", 5, 0);
|
||||
cr_assert_eq(ret, 5);
|
||||
}
|
86
test/test_utils.c
Normal file
86
test/test_utils.c
Normal file
@ -0,0 +1,86 @@
|
||||
|
||||
#include <criterion/criterion.h>
|
||||
#include <criterion/parameterized.h>
|
||||
|
||||
#include "../src/lib/utils.h"
|
||||
|
||||
struct url_encode_t {
|
||||
long in_size;
|
||||
char in[256];
|
||||
long exp_size;
|
||||
char exp[256];
|
||||
};
|
||||
|
||||
struct format_duration_t {
|
||||
unsigned long micros;
|
||||
char exp[16];
|
||||
};
|
||||
|
||||
ParameterizedTestParameters(utils, url_encode) {
|
||||
static struct url_encode_t params[] = {
|
||||
{0, "", 0, ""},
|
||||
{9, "Test Text", 11, "Test%20Text"},
|
||||
{21, "Text\0with\0null\0bytes\0", 29, "Text%00with%00null%00bytes%00"},
|
||||
{59, "Text&with+some/strange_symbols-or#something?I%don't|know...", 59, "Text&with+some/strange_symbols-or#something?I%don't|know..."},
|
||||
{33, "Data\x12With\x13Some" "\xFF" "Control" "\xFE" "Characters", 41, "Data%12With%13Some%FFControl%FECharacters"}
|
||||
};
|
||||
return cr_make_param_array(struct url_encode_t, params, sizeof(params) / sizeof(struct url_encode_t));
|
||||
}
|
||||
|
||||
ParameterizedTest(struct url_encode_t *param, utils, url_encode) {
|
||||
char out[256];
|
||||
cr_assert_eq(url_encode(param->in, param->in_size, out, sizeof(out)), param->exp_size);
|
||||
cr_assert_arr_eq(out, param->exp, param->exp_size + 1);
|
||||
}
|
||||
|
||||
Test(utils, url_encode_bytes) {
|
||||
char out[4];
|
||||
char exp[4];
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
unsigned char ch = i;
|
||||
if (ch <= 0x20 || ch >= 0x7F) {
|
||||
cr_assert_eq(url_encode(&ch, 1, out, sizeof(out)), 3);
|
||||
sprintf(exp, "%%%02X", ch);
|
||||
cr_assert_str_eq(out, exp);
|
||||
} else {
|
||||
cr_assert_eq(url_encode(&ch, 1, out, sizeof(out)), 1);
|
||||
sprintf(exp, "%c", ch);
|
||||
cr_assert_str_eq(out, exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Test(utils, url_encode_invalid) {
|
||||
cr_assert_eq(url_encode("Hello", 5, NULL, 0), 5);
|
||||
}
|
||||
|
||||
ParameterizedTestParameters(utils, format_duration) {
|
||||
static struct format_duration_t params[] = {
|
||||
{0, "0.0 ms"},
|
||||
{1, "0.0 ms"},
|
||||
{90, "0.1 ms"},
|
||||
{100, "0.1 ms"},
|
||||
{110, "0.1 ms"},
|
||||
{900, "0.9 ms"},
|
||||
{1000, "1.0 ms"},
|
||||
{9000, "9.0 ms"},
|
||||
{9899, "9.9 ms"},
|
||||
{9999, "10.0 ms"},
|
||||
{10000, "10 ms"},
|
||||
{11999, "12 ms"},
|
||||
{999999, "1.0 s"},
|
||||
{1000000, "1.0 s"},
|
||||
{3000000, "3.0 s"},
|
||||
{1000000 * 60, "1.0 min"},
|
||||
{1000000 * 60 * 30L - 30000000, "29.5 min"},
|
||||
{1000000 * 60 * 60L, "60.0 min"},
|
||||
{1000000 * 60 * 120L, "120 min"},
|
||||
};
|
||||
return cr_make_param_array(struct format_duration_t, params, sizeof(params) / sizeof(struct format_duration_t));
|
||||
}
|
||||
|
||||
ParameterizedTest(struct format_duration_t *param, utils, format_duration) {
|
||||
char buf[16];
|
||||
cr_assert_str_eq(format_duration(param->micros, buf), param->exp);
|
||||
}
|
Reference in New Issue
Block a user