Add tests for some utils
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,6 +3,8 @@
|
|||||||
!src/**
|
!src/**
|
||||||
!doc
|
!doc
|
||||||
!doc/**
|
!doc/**
|
||||||
|
!test
|
||||||
|
!test/**
|
||||||
!Makefile
|
!Makefile
|
||||||
!.gitignore
|
!.gitignore
|
||||||
!README.md
|
!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\""
|
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
|
all: prod
|
||||||
default: bin bin/lib bin/libsesimos.so bin/sesimos
|
default: bin bin/lib bin/libsesimos.so bin/sesimos
|
||||||
prod: CFLAGS += -O3
|
prod: CFLAGS += -O3
|
||||||
@ -14,6 +14,10 @@ debug: default
|
|||||||
debian: CFLAGS += $(DEBIAN_OPTS)
|
debian: CFLAGS += $(DEBIAN_OPTS)
|
||||||
debian: prod
|
debian: prod
|
||||||
|
|
||||||
|
test: CFLAGS += -include test/mock_*.h
|
||||||
|
test: bin bin/test
|
||||||
|
bin/test
|
||||||
|
|
||||||
|
|
||||||
bin:
|
bin:
|
||||||
mkdir -p bin
|
mkdir -p bin
|
||||||
@ -22,6 +26,10 @@ bin/lib:
|
|||||||
mkdir -p 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
|
bin/%.o: src/%.c
|
||||||
$(CC) -c -o $@ $(CFLAGS) $<
|
$(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;
|
int change_proto = strncmp(uri.uri, "/.well-known/", 13) != 0 && !client->enc;
|
||||||
if (strcmp(uri.uri, buf0) != 0 || change_proto) {
|
if (strcmp(uri.uri, buf0) != 0 || change_proto) {
|
||||||
res.status = http_get_status(308);
|
res.status = http_get_status(308);
|
||||||
size = sizeof(buf0);
|
size = url_encode(uri.uri, strlen(uri.uri), buf0, sizeof(buf0));
|
||||||
url_encode(uri.uri, buf0, &size);
|
|
||||||
if (change_proto) {
|
if (change_proto) {
|
||||||
p_len = snprintf(buf1, sizeof(buf1), "https://%s%s", host, buf0);
|
p_len = snprintf(buf1, sizeof(buf1), "https://%s%s", host, buf0);
|
||||||
if (p_len < 0 || p_len >= sizeof(buf1)) {
|
if (p_len < 0 || p_len >= sizeof(buf1)) {
|
||||||
|
@ -15,69 +15,77 @@
|
|||||||
|
|
||||||
char *log_prefix;
|
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) {
|
char *format_duration(unsigned long micros, char *buf) {
|
||||||
if (micros < 10000) {
|
if (micros < 10000) {
|
||||||
sprintf(buf, "%.1f ms", (double) micros / 1000);
|
sprintf(buf, "%.1f ms", (double) micros / 1000);
|
||||||
} else if (micros < 1000000) {
|
} else if (micros < 1000000 - 1000) {
|
||||||
sprintf(buf, "%li ms", micros / 1000);
|
sprintf(buf, "%.0f ms", (double) micros / 1000);
|
||||||
} else if (micros < 60000000) {
|
} else if (micros < 60000000 - 1000000) {
|
||||||
sprintf(buf, "%.1f s", (double) micros / 1000000);
|
sprintf(buf, "%.1f s", (double) micros / 1000000);
|
||||||
} else if (micros < 6000000000) {
|
} else if (micros < 6000000000) {
|
||||||
sprintf(buf, "%.1f min", (double) micros / 1000000 / 60);
|
sprintf(buf, "%.1f min", (double) micros / 1000000 / 60);
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%li min", micros / 1000000 / 60);
|
sprintf(buf, "%.0f min", (double) micros / 1000000 / 60);
|
||||||
}
|
}
|
||||||
return buf;
|
return 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) {
|
||||||
char *ptr = enc;
|
int size = 0;
|
||||||
char ch;
|
|
||||||
memset(enc, 0, *size);
|
// Encode control characters
|
||||||
for (int i = 0; i < strlen(str); i++, ptr++) {
|
for (int i = 0; i < size_in; i++) {
|
||||||
if ((ptr - enc) >= *size) {
|
unsigned char ch = ((unsigned char *) in)[i];
|
||||||
return -1;
|
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 == '!' ||
|
if (ch != 0) {
|
||||||
ch == '$' || ch == '&' || ch == '\'' || ch == '(' || ch == ')' || ch == '*' || ch == '+' || ch == ',' ||
|
size++;
|
||||||
ch == ';' || ch == '=' || ch < ' ' || ch > '~') {
|
if (size < size_out) out[size - 1] = (char) ch;
|
||||||
if ((ptr - enc + 2) >= *size) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sprintf(ptr, "%%%02X", ch);
|
|
||||||
ptr += 2;
|
|
||||||
} else if (ch == ' ') {
|
|
||||||
ptr[0] = '+';
|
|
||||||
} else {
|
|
||||||
ptr[0] = 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) {
|
int url_encode(const void *in, size_t size_in, char *out, size_t size_out) {
|
||||||
char *ptr = enc;
|
int size = 0;
|
||||||
unsigned char ch;
|
|
||||||
memset(enc, 0, *size);
|
// Encode control characters
|
||||||
for (int i = 0; i < strlen(str); i++, ptr++) {
|
for (int i = 0; i < size_in; i++) {
|
||||||
if ((ptr - enc) >= *size) {
|
unsigned char ch = ((unsigned char *) in)[i];
|
||||||
return -1;
|
if (ch <= 0x20 || ch >= 0x7F) {
|
||||||
}
|
size += 3;
|
||||||
ch = str[i];
|
if (size < size_out) sprintf(out + size - 3, "%%%02X", ch);
|
||||||
if (ch > 0x7F || ch == ' ') {
|
|
||||||
if ((ptr - enc + 2) >= *size) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sprintf(ptr, "%%%02X", ch);
|
|
||||||
ptr += 2;
|
|
||||||
} else {
|
} 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) {
|
int url_decode(const char *str, char *dec, long *size) {
|
||||||
|
@ -21,9 +21,6 @@
|
|||||||
|
|
||||||
extern char *log_prefix;
|
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_1(fmt) fprintf(stdout, "%s" fmt "\n", log_prefix)
|
||||||
#define out_2(fmt, args...) fprintf(stdout, "%s" fmt "\n", log_prefix, args)
|
#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);
|
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);
|
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