diff --git a/.github/workflows/backend_build_and_test.yml b/.github/workflows/backend_build_and_test.yml new file mode 100644 index 0000000..bfdd07d --- /dev/null +++ b/.github/workflows/backend_build_and_test.yml @@ -0,0 +1,81 @@ +name: "Backend: Build and Test" + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + BACKEND_SERVER_HOSTNAME: 'http://localhost:8080' + +jobs: + build_debug: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend + steps: + - uses: actions/checkout@v4 + - name: build release with tests + run: make -B INCLUDE_TESTS=1 + - name: run tests + run: ./build/server --run-tests + + build_release: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend + steps: + - uses: actions/checkout@v4 + - name: build release with tests + run: make -B RELEASE=1 INCLUDE_TESTS=1 + - name: run tests + run: ./build/server --run-tests + + test_debug: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend + steps: + - uses: actions/checkout@v4 + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.x + - name: cache dependencies + run: deno cache --check test/test.ts + - name: build release with tests + run: make -B + - name: setup database + run: make drop_database + - name: test + timeout-minutes: 1 + run: | + ./build/server & + sleep 1 + deno test --allow-env --allow-net test/test.ts + + test_release: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend + steps: + - uses: actions/checkout@v4 + - uses: denoland/setup-deno@v2 + with: + deno-version: v2.x + - name: cache dependencies + run: deno cache --check test/test.ts + - name: build release with tests + run: make -B RELEASE=1 + - name: setup database + run: make drop_database + - name: test + timeout-minutes: 1 + run: | + ./build/server & + sleep 1 + deno test --allow-env --allow-net test/test.ts diff --git a/backend/Makefile b/backend/Makefile index 65f328b..5abda50 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -36,13 +36,16 @@ else endif -ifeq ($(RUN_TESTS),1) - C_FLAGS += -DRUN_TESTS +ifeq ($(INCLUDE_TESTS),1) + C_FLAGS += -DINCLUDE_TESTS endif PUBLIC_DIR_PATH=$(shell readlink -f ./public) C_FLAGS += -DPUBLIC_DIR_PATH='"$(PUBLIC_DIR_PATH)"' +DB_FILEPATH=database.db +C_FLAGS += -DDB_FILEPATH='"$(DB_FILEPATH)"' + HEADERS = $(shell find src/ -name *.h) C_FILES = $(shell find src/ -name *.c) O_FILES = $(patsubst src/%.c,build/%.o,$(C_FILES)) @@ -64,5 +67,5 @@ clean: rm -rf build/ drop_database: - rm -rf database.db && sqlite3 database.db < prepare.sql + rm -rf $(DB_FILEPATH) && sqlite3 $(DB_FILEPATH) < prepare.sql diff --git a/backend/compile_flags.txt b/backend/compile_flags.txt index 365d678..3a79155 100644 --- a/backend/compile_flags.txt +++ b/backend/compile_flags.txt @@ -8,5 +8,7 @@ -pedantic-errors -Wno-unused-parameter -Wno-unused-function +-DINCLUDE_TESTS -DPUBLIC_DIR_PATH="./public" +-DDB_FILEPATH="database.db" diff --git a/backend/src/collections/kv_map.h b/backend/src/collections/kv_map.h index a64b57a..fb6663a 100644 --- a/backend/src/collections/kv_map.h +++ b/backend/src/collections/kv_map.h @@ -106,19 +106,19 @@ return &found->value; \ } -#ifdef RUN_TESTS +#ifdef INCLUDE_TESTS #include "../utils/panic.h" -DEFINE_KV_MAP(int, int, IntMap, int_map) +DEFINE_KV_MAP(int, int, TestIntMap, test_int_map) static inline void test_collections_kv_map(void) { - IntMap map; - int_map_construct(&map); + TestIntMap map; + test_int_map_construct(&map); - int_map_set(&map, 1, 10); - int_map_set(&map, 3, 30); - int_map_set(&map, 5, 50); + test_int_map_set(&map, 1, 10); + test_int_map_set(&map, 3, 30); + test_int_map_set(&map, 5, 50); int data[][2] = { { 0, 0 }, @@ -131,28 +131,28 @@ static inline void test_collections_kv_map(void) }; for (size_t i = 0; i < sizeof(data) / sizeof(data[0]); ++i) { - int idx - = (int)int_map_internal_insert_idx(&map, 0, map.size, data[i][0]); + int idx = (int)test_int_map_internal_insert_idx( + &map, 0, map.size, data[i][0]); if (idx != data[i][1]) { PANIC("wrong insert index, expected %d, got %d", data[i][1], idx); } } - int* val = int_map_get(&map, 3); + int* val = test_int_map_get(&map, 3); if (!val || *val != 30) { PANIC("failed to find value"); } - val = int_map_get(&map, 4); + val = test_int_map_get(&map, 4); if (val != NULL) { PANIC("found wrong value"); } - const int* const_val = int_map_get_const(&map, 5); + const int* const_val = test_int_map_get_const(&map, 5); if (!const_val || *const_val != 50) { PANIC("failed to find value"); } - int_map_destroy(&map); + test_int_map_destroy(&map); } #endif diff --git a/backend/src/db/db_sqlite.c b/backend/src/db/db_sqlite.c index 5440617..5c72fb3 100644 --- a/backend/src/db/db_sqlite.c +++ b/backend/src/db/db_sqlite.c @@ -27,36 +27,17 @@ static inline char* get_str_safe(sqlite3_stmt* stmt, int col) #define GET_INT(COL) sqlite3_column_int64(stmt, COL) #define GET_STR(COL) get_str_safe(stmt, COL) -Db* db_sqlite_new(void) -{ - Db* db = malloc(sizeof(Db)); - - sqlite3* connection; - int res = sqlite3_open("database.db", &connection); - if (res != SQLITE_OK) { - fprintf(stderr, "error: could not open sqlite 'database.db'\n"); - return NULL; - } - sqlite3_close(connection); - - return db; -} - -void db_sqlite_free(Db* db) -{ - // sqlite3_close(db->connection); - free(db); -} - static inline DbRes connect(sqlite3** connection) { - int res = sqlite3_open_v2("database.db", + const char* filepath = DB_FILEPATH; + int res = sqlite3_open_v2(filepath, connection, SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX, NULL); if (res != SQLITE_OK) { fprintf(stderr, - "error: could not open sqlite 'database.db'\n %s\n", + "error: could not open sqlite '%s'\n %s\n", + filepath, sqlite3_errmsg(*connection)); return DbRes_Error; } @@ -80,6 +61,26 @@ static inline void disconnect(sqlite3* connection) disconnect(connection); \ } +Db* db_sqlite_new(void) +{ + Db* db = malloc(sizeof(Db)); + + sqlite3* connection; + if (connect(&connection) != DbRes_Ok) { + return NULL; + } + disconnect(connection); + + return db; +} + +void db_sqlite_free(Db* db) +{ + // No need to disconnect. + + free(db); +} + DbRes db_user_insert(Db* db, const User* user) { static_assert(sizeof(User) == 40, "model has changed"); diff --git a/backend/src/main.c b/backend/src/main.c index 11c942a..7154c49 100644 --- a/backend/src/main.c +++ b/backend/src/main.c @@ -1,3 +1,4 @@ +#include "collections/kv_map.h" #include "controllers/controllers.h" #include "db/db_sqlite.h" #include "http/http.h" @@ -8,17 +9,24 @@ #include #include -void test(void); +typedef struct { + bool run_tests; +} Args; + +static inline Args parse_args(int argc, char** argv); +static inline void run_tests(void); HttpServer* server; -int main(void) +int main(int argc, char** argv) { srand((unsigned int)time(NULL)); -#ifdef RUN_TESTS - test(); -#endif + Args args = parse_args(argc, argv); + + if (args.run_tests) { + run_tests(); + } Db* db = db_sqlite_new(); @@ -81,13 +89,30 @@ int main(void) db_sqlite_free(db); } -#ifdef RUN_TESTS -void test(void) +static inline Args parse_args(int argc, char** argv) { + Args args = { + .run_tests = false, + }; + for (int i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--run-tests") == 0) { + args.run_tests = true; + } + } + return args; +} + +static inline void run_tests(void) +{ +#ifdef INCLUDE_TESTS test_util_str(); test_collections_kv_map(); printf("\n\x1b[1;97m ALL TESTS \x1b[1;92mPASSED" " \x1b[1;97mSUCCESSFULLY 💅\x1b[0m\n\n"); exit(0); -} +#else + fprintf(stderr, + "warning: tests not build." + " '--run-tests' passed without building with INCLUDE_TESTS=1\n"); #endif +} diff --git a/backend/src/utils/str.c b/backend/src/utils/str.c index ff6c859..34cdd7b 100644 --- a/backend/src/utils/str.c +++ b/backend/src/utils/str.c @@ -313,7 +313,7 @@ char* str_random(size_t length) return string; } -#ifdef RUN_TESTS +#ifdef INCLUDE_TESTS void test_util_str(void) { { diff --git a/backend/src/utils/str.h b/backend/src/utils/str.h index 8007b79..9c8ce08 100644 --- a/backend/src/utils/str.h +++ b/backend/src/utils/str.h @@ -47,6 +47,6 @@ uint64_t str_fast_hash(const char* input); char* str_random(size_t length); -#ifdef RUN_TESTS +#ifdef INCLUDE_TESTS void test_util_str(void); #endif diff --git a/backend/test/test.ts b/backend/test/test.ts index a939eae..d06d7bd 100644 --- a/backend/test/test.ts +++ b/backend/test/test.ts @@ -1,7 +1,6 @@ import { assertEquals, assertMatch, assertNotEquals } from "jsr:@std/assert"; -const url = `http://127.0.0.1:8080`; -// const url = `http://10.135.51.114:8080`; +const url = Deno.env.get("BACKEND_SERVER_HOSTNAME") ?? `http://127.0.0.1:8080`; const name = "Maksim"; const email = `mash.skp_${Math.floor(Math.random() * 100000)}@edu.mercantec.dk`;