Tests and fixes for url_encode
This commit is contained in:
7
Makefile
7
Makefile
@@ -49,5 +49,12 @@ output/noh.o: src/noh.h | output
|
|||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
test: output/test
|
||||||
|
output/test: test/test_path.c $(SHARED_LIB_FILES) | output
|
||||||
|
gcc $(CFLAGS) -I./src -o output/test test/test_path.c $(SHARED_LIBS)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
output:
|
output:
|
||||||
mkdir -p output
|
mkdir -p output
|
||||||
|
|
||||||
|
|||||||
6
build.sh
6
build.sh
@@ -14,6 +14,12 @@ elif [ $1 = "run" ]; then
|
|||||||
make server
|
make server
|
||||||
./output/server 5000 ./library "Testing library"
|
./output/server 5000 ./library "Testing library"
|
||||||
|
|
||||||
|
elif [ $1 = "test" ]; then
|
||||||
|
echo "Running tests"
|
||||||
|
|
||||||
|
make test
|
||||||
|
./output/test
|
||||||
|
|
||||||
elif [ $1 = "debug" ]; then
|
elif [ $1 = "debug" ]; then
|
||||||
echo "Debugging"
|
echo "Debugging"
|
||||||
|
|
||||||
|
|||||||
47
src/noh.h
47
src/noh.h
@@ -156,9 +156,21 @@ typedef enum {
|
|||||||
NOH_ERROR,
|
NOH_ERROR,
|
||||||
} Noh_Log_Level;
|
} Noh_Log_Level;
|
||||||
|
|
||||||
|
// Options that can alter the behavior of noh_log.
|
||||||
|
typedef struct {
|
||||||
|
// Whether to write a line feed at the end of a log message. Default is true.
|
||||||
|
bool write_lf;
|
||||||
|
|
||||||
|
// Whether to write a line feed at the end of a log message. Default is true.
|
||||||
|
bool write_prefix;
|
||||||
|
} Noh_Log_Options;
|
||||||
|
|
||||||
// Writes a formatted log message to stderr with the provided log level.
|
// Writes a formatted log message to stderr with the provided log level.
|
||||||
void noh_log(Noh_Log_Level level, const char *fmt, ...);
|
void noh_log(Noh_Log_Level level, const char *fmt, ...);
|
||||||
|
|
||||||
|
// Returns a pointer to the noh_log options.
|
||||||
|
Noh_Log_Options *noh_log_get_opts();
|
||||||
|
|
||||||
///////////////////////// Dynamic array /////////////////////////
|
///////////////////////// Dynamic array /////////////////////////
|
||||||
|
|
||||||
#define NOH_DA_INIT_CAP 256
|
#define NOH_DA_INIT_CAP 256
|
||||||
@@ -609,27 +621,36 @@ void noh_time_add(struct timespec *time, int seconds, long milliseconds) {
|
|||||||
|
|
||||||
///////////////////////// Logging /////////////////////////
|
///////////////////////// Logging /////////////////////////
|
||||||
|
|
||||||
|
Noh_Log_Options *noh_log_get_opts() {
|
||||||
|
static Noh_Log_Options opts = { .write_lf = true, .write_prefix = true, };
|
||||||
|
return &opts;
|
||||||
|
}
|
||||||
|
|
||||||
void noh_log(Noh_Log_Level level, const char *fmt, ...)
|
void noh_log(Noh_Log_Level level, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
switch (level) {
|
Noh_Log_Options *opts = noh_log_get_opts();
|
||||||
case NOH_INFO:
|
|
||||||
fprintf(stderr, "[INFO] ");
|
if (opts->write_prefix) {
|
||||||
break;
|
switch (level) {
|
||||||
case NOH_WARNING:
|
case NOH_INFO:
|
||||||
fprintf(stderr, "[WARNING] ");
|
fprintf(stderr, "[INFO] ");
|
||||||
break;
|
break;
|
||||||
case NOH_ERROR:
|
case NOH_WARNING:
|
||||||
fprintf(stderr, "[ERROR] ");
|
fprintf(stderr, "[WARNING] ");
|
||||||
break;
|
break;
|
||||||
default:
|
case NOH_ERROR:
|
||||||
noh_assert(false && "Invalid log level");
|
fprintf(stderr, "[ERROR] ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
noh_assert(false && "Invalid log level");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vfprintf(stderr, fmt, args);
|
vfprintf(stderr, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
fprintf(stderr, "\n");
|
if (opts->write_lf) fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////// Arena /////////////////////////
|
///////////////////////// Arena /////////////////////////
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
static inline bool byte_is_url_safe(char c) {
|
static inline bool byte_is_url_safe(char c) {
|
||||||
return (c >= 'A' && c <= 'Z')
|
return (c >= 'A' && c <= 'Z')
|
||||||
|| (c >= 'a' && c <= 'z')
|
|| (c >= 'a' && c <= 'z')
|
||||||
|| (c >= '0' && c <+ '9')
|
|| (c >= '0' && c <= '9')
|
||||||
|| (c >= '(' && c <= '*')
|
|| (c >= '(' && c <= '*')
|
||||||
|| c == '!' || c == '-'
|
|| c == '!' || c == '-'
|
||||||
|| c == '.' || c == '_';
|
|| c == '.' || c == '_';
|
||||||
@@ -15,12 +15,12 @@ static bool needs_encoding(Noh_String string, int *unsafe_count) {
|
|||||||
*unsafe_count = 0;
|
*unsafe_count = 0;
|
||||||
bool safe = true ;
|
bool safe = true ;
|
||||||
for (size_t i = 0; i < string.count; i++) {
|
for (size_t i = 0; i < string.count; i++) {
|
||||||
bool needs_encode = byte_is_url_safe(string.elems[i]);
|
bool needs_encode = !byte_is_url_safe(string.elems[i]);
|
||||||
if (needs_encode || string.elems[i] == ' ') safe = false;
|
if (needs_encode || string.elems[i] == ' ') safe = false;
|
||||||
if (needs_encode) (*unsafe_count)++;
|
if (needs_encode) (*unsafe_count)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return safe;
|
return !safe;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char to_char_lower(int value) {
|
static inline char to_char_lower(int value) {
|
||||||
@@ -55,6 +55,8 @@ void url_encode(Noh_String *string) {
|
|||||||
noh_da_append(&result, '%');
|
noh_da_append(&result, '%');
|
||||||
noh_da_append(&result, to_char_lower(cur >> 4));
|
noh_da_append(&result, to_char_lower(cur >> 4));
|
||||||
noh_da_append(&result, to_char_lower(cur));
|
noh_da_append(&result, to_char_lower(cur));
|
||||||
|
} else {
|
||||||
|
noh_da_append(&result, cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
test/test_path.c
Normal file
52
test/test_path.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "path.h"
|
||||||
|
#include "noh.h"
|
||||||
|
|
||||||
|
void check_string(size_t *good, size_t *bad, const char* input, const char *expected) {
|
||||||
|
Noh_String test = noh_string_from_cstr(input);
|
||||||
|
Noh_String_View expected_sv = noh_sv_from_cstr(expected);
|
||||||
|
|
||||||
|
Noh_Log_Options *opts = noh_log_get_opts();
|
||||||
|
|
||||||
|
opts->write_lf = false;
|
||||||
|
noh_log(NOH_INFO, "Testing: \"%s\"...", input);
|
||||||
|
opts->write_lf = true;
|
||||||
|
opts->write_prefix = false;
|
||||||
|
|
||||||
|
url_encode(&test);
|
||||||
|
bool correct = noh_sv_eq(noh_sv_from_string(test), expected_sv);
|
||||||
|
|
||||||
|
if (!correct) {
|
||||||
|
noh_log(NOH_ERROR, " Incorrect.");
|
||||||
|
opts->write_prefix = true;
|
||||||
|
noh_log(NOH_ERROR, "Expected: "Nsv_Fmt, Nsv_Arg(expected_sv));
|
||||||
|
noh_log(NOH_ERROR, "Got : "Nsv_Fmt, Nsv_Arg(test));
|
||||||
|
(*bad)++;
|
||||||
|
} else {
|
||||||
|
noh_log(NOH_INFO, " Ok.");
|
||||||
|
opts->write_prefix = true;
|
||||||
|
(*good)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
size_t good = 0;
|
||||||
|
size_t bad = 0;
|
||||||
|
|
||||||
|
check_string(&good, &bad,
|
||||||
|
"abcdefghijklmnopqrstuvwxyz1023456789ABCDEFGHIJKLMNOPQRSTUVWXYZ()*!-._",
|
||||||
|
"abcdefghijklmnopqrstuvwxyz1023456789ABCDEFGHIJKLMNOPQRSTUVWXYZ()*!-._");
|
||||||
|
|
||||||
|
check_string(&good, &bad,
|
||||||
|
"~!@#$%^&*()_+-=",
|
||||||
|
"%7e!%40%23%24%25%5e%26*()_%2b-%3d");
|
||||||
|
|
||||||
|
if (bad == 0) {
|
||||||
|
noh_log(NOH_INFO, "%zu/%zu tests passed.", good, good);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
noh_log(NOH_ERROR, "%zu/%zu tests passed. %zu failures.", good, good + bad, bad);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user