Skip to content

Commit

Permalink
feat(log): create unit tests (#39)
Browse files Browse the repository at this point in the history
Introduce unit tests for already existing code.
This advances progress on #33.
  • Loading branch information
marcluque committed Oct 23, 2022
1 parent 55265fe commit b91f7d9
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 51 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakStringLiterals: true

ColumnLimit: 111
ColumnLimit: 121

ContinuationIndentWidth: 4

Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ if (${TEST})
test/alu_8bit_sbc_test.c
test/cli_test.c
test/rom_test.c
test/mmu_test.c)
test/mmu_test.c
test/log_test.c)

set(TEST_SOURCES ${TEST_FILES} ${SRC_FILES})
list(REMOVE_ITEM TEST_SOURCES "src/main.c")
Expand Down
6 changes: 4 additions & 2 deletions src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ void log_set_lvl(LoggingLevel log_lvl) {

// minimum logging level cannot be higher than fatal
if (min_log_lvl > FATAL) {
min_log_lvl = WARNING;
LOG_WARNING("Provided logging level %d is higher than FATAL (%d).", min_log_lvl, FATAL);
min_log_lvl = FATAL;
}
Expand Down Expand Up @@ -72,11 +73,12 @@ void log_exit(char const *const file_path, int const line_number, char const *co
exit(EXIT_FAILURE);
}

void log_str(const LoggingLevel log_lvl, char const *const log_lvl_str, FILE *stream, char const *const msg,
...) {
void log_str(const LoggingLevel log_lvl, char const *const log_lvl_str, FILE *stream, char const *const msg, ...) {
if (log_lvl < min_log_lvl)
return;

// This is necessary because Criterion is not correctly redirecting stdout.
// Hence, we test the log messages by sending them through stderr (which works as intended)
#if defined(YOBEMAG_TEST)
stream = stderr;
#endif
Expand Down
86 changes: 39 additions & 47 deletions test/cli_test.c
Original file line number Diff line number Diff line change
@@ -1,142 +1,134 @@
#include <criterion/criterion.h>
#include <criterion/new/assert.h>
#include <criterion/logging.h>
#include <criterion/redirect.h>
#include <criterion/parameterized.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>

#include <stdio.h>
#include <stdint.h>

#include "cli.h"

#include "common/util.h"

Test(cli, cli_no_args, .exit_code = EXIT_FAILURE) {
Test(cli, cli_no_args, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag"};
int argc = 1;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_wrong_option, .exit_code = EXIT_FAILURE) {
Test(cli, cli_wrong_option, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-s", "0"};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_too_many_args, .exit_code = EXIT_FAILURE) {
Test(cli, cli_too_many_args, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-l", "4", "../build/yobemag.gb", "test_param"};
int argc = 5;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_no_rom_path, .exit_code = EXIT_FAILURE) {
Test(cli, cli_no_rom_path, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-l", "4"};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_no_log_lvl_no_path, .exit_code = EXIT_FAILURE) {
Test(cli, cli_no_log_lvl_no_path, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-l"};
int argc = 2;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_no_log_lvl, .exit_code = EXIT_FAILURE) {
Test(cli, cli_no_log_lvl, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-l", "../build/yobemag.gb"};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_not_finished, .exit_code = EXIT_FAILURE) {
Test(cli, cli_not_finished, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-l", "1abc"};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_gt_than_long_max, .exit_code = EXIT_FAILURE) {
int const n = snprintf(NULL, 0, "%li", LONG_MAX);
char buf[n + 2];
int c = snprintf(buf, n + 1, "%li", LONG_MAX);
buf[n] = '9';
Test(cli, cli_gt_than_long_max, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char buf[50];
snprintf(buf, 50, "%li9", LONG_MAX);

char *argv[] = {"./yobemag", "-l", buf};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_lt_than_long_min, .exit_code = EXIT_FAILURE) {
int const n = snprintf(NULL, 0, "%li", LONG_MIN);
char buf[n + 2];
int c = snprintf(buf, n + 1, "%li", LONG_MIN);
buf[n] = '9';
Test(cli, cli_lt_than_long_min, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char buf[50];
snprintf(buf, 50, "%li9", LONG_MIN);

char *argv[] = {"./yobemag", "-l", buf};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_gt_than_int_max, .exit_code = EXIT_FAILURE) {
int const n = snprintf(NULL, 0, "%li", LONG_MAX);
char buf[n + 2];
int c = snprintf(buf, n + 1, "%li", LONG_MAX);
Test(cli, cli_gt_than_int_max, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char buf[50];
snprintf(buf, 50, "%li9", LONG_MAX);

char *argv[] = {"./yobemag", "-l", buf};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_lt_than_int_min, .exit_code = EXIT_FAILURE) {
int const n = snprintf(NULL, 0, "%li", LONG_MIN);
char buf[n + 2];
int c = snprintf(buf, n + 1, "%li", LONG_MIN);
Test(cli, cli_lt_than_int_min, .exit_code = EXIT_FAILURE, .init = cr_redirect_stderr) {
char buf[50];
snprintf(buf, 50, "%li9", LONG_MIN);

char *argv[] = {"./yobemag", "-l", buf};
int argc = 3;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
}

Test(cli, cli_correct_with_log_lvl, .exit_code = EXIT_SUCCESS) {
Test(cli, cli_correct_with_log_lvl, .exit_code = EXIT_SUCCESS, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "-l", "2", "../build/yobemag.gb"};
int argc = 4;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);

uint8_t actual_log_lvl = cli_args.logging_level;
uint8_t expected_log_lvl = 2;
LoggingLevel actual_log_lvl = cli_args.logging_level;
LoggingLevel expected_log_lvl = 2;

char const *expected_rom_path = "../build/yobemag.gb";

cr_expect(eq(u8, actual_log_lvl, expected_log_lvl));
cr_expect(eq(int, actual_log_lvl, expected_log_lvl));
cr_assert_str_eq(cli_args.rom_path, expected_rom_path);
}

Test(cli, cli_correct_no_log_lvl, .exit_code = EXIT_SUCCESS) {
Test(cli, cli_correct_no_log_lvl, .exit_code = EXIT_SUCCESS, .init = cr_redirect_stderr) {
char *argv[] = {"./yobemag", "../build/yobemag.gb"};
int argc = 2;
int argc = sizeof(argv) / sizeof(char *);

CLIArguments cli_args;
cli_parse(&cli_args, argc, argv);
Expand Down
56 changes: 56 additions & 0 deletions test/log_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <criterion/criterion.h>
#include <criterion/new/assert.h>
#include <criterion/logging.h>
#include <criterion/redirect.h>
#include <string.h>

#include "log.h"

#define MAX_LOG_MSG_LENGTH (512)

Test(log, log_set_log_lvl, .init = cr_redirect_stderr) {
log_set_lvl(INFO);

log_teardown();

char buf[MAX_LOG_MSG_LENGTH] = {0};
FILE *f_stderr = cr_get_redirected_stderr();
while (fread(buf, 1, sizeof(buf), f_stderr) > 0) {};
fclose(f_stderr);

cr_assert_not_null(strstr(buf, "INFO"));
cr_assert_not_null(strstr(buf, "initialized"));
}

Test(log, log_respect_log_lvl, .init = cr_redirect_stderr) {
log_set_lvl(WARNING);

LOG_DEBUG("Debug message");
LOG_WARNING("Warning message");

log_teardown();

char buf[MAX_LOG_MSG_LENGTH] = {0};
FILE *f_stderr = cr_get_redirected_stderr();
while (fread(buf, 1, sizeof(buf), f_stderr) > 0) {};
fclose(f_stderr);

cr_assert_null(strstr(buf, "DEBUG"));
cr_assert_not_null(strstr(buf, "WARNING"));
}

Test(log, log_warn_about_clamping, .init = cr_redirect_stderr) {
log_set_lvl(DEBUG - 1);
log_set_lvl(FATAL + 1);

log_teardown();

char buf[MAX_LOG_MSG_LENGTH] = {0};
FILE *f_stderr = cr_get_redirected_stderr();
while (fread(buf, 1, sizeof(buf), f_stderr) > 0) {};
fclose(f_stderr);

cr_assert_not_null(strstr(buf, "lower"));
cr_assert_not_null(strstr(buf, "higher"));
cr_assert_not_null(strstr(buf, "WARNING"));
}

0 comments on commit b91f7d9

Please sign in to comment.