add backend action

This commit is contained in:
sfja 2025-03-21 23:00:29 +01:00
parent 6a4f965536
commit f79adeaef3
9 changed files with 162 additions and 51 deletions

View File

@ -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

View File

@ -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

View File

@ -8,5 +8,7 @@
-pedantic-errors
-Wno-unused-parameter
-Wno-unused-function
-DINCLUDE_TESTS
-DPUBLIC_DIR_PATH="./public"
-DDB_FILEPATH="database.db"

View File

@ -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

View File

@ -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");

View File

@ -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 <string.h>
#include <time.h>
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
}

View File

@ -313,7 +313,7 @@ char* str_random(size_t length)
return string;
}
#ifdef RUN_TESTS
#ifdef INCLUDE_TESTS
void test_util_str(void)
{
{

View File

@ -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

View File

@ -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`;