add tests + ci
Some checks failed
CI/CD Pipeline / test (push) Failing after 11s

This commit is contained in:
Philipp Hofer 2025-04-11 18:46:52 +02:00
parent 0228cec056
commit d17f9cf7a4
7 changed files with 258 additions and 19 deletions

View File

@ -0,0 +1,25 @@
name: CI/CD Pipeline
on: push
env:
CARGO_TARGET: x86_64-unknown-linux-musl
jobs:
test:
runs-on: ubuntu-latest
container: git.hofer.link/philipp/ci-images:rust-latest
steps:
- uses: actions/checkout@v3
- name: Run Test DB Script
run: ./test_db.sh
- name: Cache Cargo dependencies
uses: Swatinem/rust-cache@v2
- name: Build
run: |
cargo build
- name: Backend tests
run: cargo test --verbose

173
Cargo.lock generated
View File

@ -47,12 +47,28 @@ dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
[[package]]
name = "arc-swap"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]]
name = "assert-json-diff"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "async-trait"
version = "0.1.88"
@ -73,6 +89,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "auto-future"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c1e7e457ea78e524f48639f551fd79703ac3f2237f5ecccdf4708f8a75ad373"
[[package]]
name = "autocfg"
version = "1.4.0"
@ -133,6 +155,36 @@ dependencies = [
"tracing",
]
[[package]]
name = "axum-test"
version = "17.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eb1dfb84bd48bad8e4aa1acb82ed24c2bb5e855b659959b4e03b4dca118fcac"
dependencies = [
"anyhow",
"assert-json-diff",
"auto-future",
"axum",
"bytes",
"bytesize",
"cookie",
"http",
"http-body-util",
"hyper",
"hyper-util",
"mime",
"pretty_assertions",
"reserve-port",
"rust-multipart-rfc7578_2",
"serde",
"serde_json",
"serde_urlencoded",
"smallvec",
"tokio",
"tower",
"url",
]
[[package]]
name = "backtrace"
version = "0.3.74"
@ -221,6 +273,12 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "bytesize"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba"
[[package]]
name = "cc"
version = "1.2.18"
@ -372,6 +430,12 @@ dependencies = [
"serde",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "digest"
version = "0.10.7"
@ -781,6 +845,7 @@ dependencies = [
"pin-project-lite",
"smallvec",
"tokio",
"want",
]
[[package]]
@ -790,13 +855,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"hyper",
"libc",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
]
[[package]]
@ -1167,7 +1236,7 @@ dependencies = [
"num-integer",
"num-iter",
"num-traits",
"rand",
"rand 0.8.5",
"smallvec",
"zeroize",
]
@ -1321,6 +1390,16 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "pretty_assertions"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "proc-macro2"
version = "1.0.94"
@ -1364,8 +1443,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
"zerocopy",
]
[[package]]
@ -1375,7 +1465,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
@ -1387,6 +1487,15 @@ dependencies = [
"getrandom 0.2.15",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.5.11"
@ -1425,6 +1534,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "reserve-port"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3747658ee2585ecf5607fa9887c92eff61b362ff5253dbf797dfeb73d33d78"
dependencies = [
"thiserror",
]
[[package]]
name = "ring"
version = "0.17.14"
@ -1452,7 +1570,7 @@ dependencies = [
"num-traits",
"pkcs1",
"pkcs8",
"rand_core",
"rand_core 0.6.4",
"signature",
"spki",
"subtle",
@ -1513,6 +1631,21 @@ dependencies = [
"triomphe",
]
[[package]]
name = "rust-multipart-rfc7578_2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c839d037155ebc06a571e305af66ff9fd9063a6e662447051737e1ac75beea41"
dependencies = [
"bytes",
"futures-core",
"futures-util",
"http",
"mime",
"rand 0.9.0",
"thiserror",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@ -1710,7 +1843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"digest",
"rand_core",
"rand_core 0.6.4",
]
[[package]]
@ -1885,7 +2018,7 @@ dependencies = [
"memchr",
"once_cell",
"percent-encoding",
"rand",
"rand 0.8.5",
"rsa",
"serde",
"sha1",
@ -1924,7 +2057,7 @@ dependencies = [
"md-5",
"memchr",
"once_cell",
"rand",
"rand 0.8.5",
"serde",
"serde_json",
"sha2",
@ -1971,6 +2104,7 @@ name = "stationslauf"
version = "0.1.0"
dependencies = [
"axum",
"axum-test",
"chrono",
"dotenv",
"maud",
@ -2262,7 +2396,7 @@ dependencies = [
"futures",
"http",
"parking_lot",
"rand",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
@ -2326,6 +2460,12 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "try-lock"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "typenum"
version = "1.18.0"
@ -2416,6 +2556,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -2760,6 +2909,12 @@ version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yoke"
version = "0.7.5"

View File

@ -14,3 +14,6 @@ tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] }
tower-sessions = "0.14"
tracing = "0.1"
rust-i18n = "3"
[dev-dependencies]
axum-test = "17.3"

View File

@ -1,4 +1,4 @@
CREATE TABLE station (
CREATE TABLE IF NOT EXISTS station (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
notes TEXT,
@ -9,12 +9,12 @@ CREATE TABLE station (
lng REAL
);
CREATE TABLE route (
CREATE TABLE IF NOT EXISTS route (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE -- e.g. 'wiwö'
);
CREATE TABLE route_station (
CREATE TABLE IF NOT EXISTS route_station (
route_id INTEGER NOT NULL,
station_id INTEGER NOT NULL,
pos INTEGER NOT NULL,
@ -23,7 +23,7 @@ CREATE TABLE route_station (
FOREIGN KEY (station_id) REFERENCES station(id)
);
CREATE TABLE team (
CREATE TABLE IF NOT EXISTS team (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
notes TEXT,
@ -34,7 +34,7 @@ CREATE TABLE team (
FOREIGN KEY (route_id) REFERENCES route(id)
);
CREATE TABLE rating (
CREATE TABLE IF NOT EXISTS rating (
team_id INTEGER NOT NULL,
station_id INTEGER NOT NULL,
points INTEGER,

View File

@ -65,7 +65,7 @@ impl Station {
Some(station)
}
async fn create(db: &SqlitePool, name: &str) -> Result<(), String> {
pub(crate) async fn create(db: &SqlitePool, name: &str) -> Result<(), String> {
sqlx::query!("INSERT INTO station(name) VALUES (?)", name)
.execute(db)
.await

View File

@ -1,6 +1,19 @@
#[macro_use]
extern crate rust_i18n;
#[cfg(test)]
#[macro_export]
macro_rules! testdb {
() => {{
let pool = SqlitePool::connect(":memory:").await.unwrap();
sqlx::query_file!("./migration.sql")
.execute(&pool)
.await
.unwrap();
pool
}};
}
i18n!("locales", fallback = "de-AT");
use admin::station::Station;
@ -114,14 +127,13 @@ impl FromRef<AppState> for Arc<SqlitePool> {
}
}
/// Starts the main application.
pub async fn start(listener: TcpListener, db: SqlitePool) {
fn router(db: SqlitePool) -> Router {
let session_store = MemoryStore::default();
let session_layer = SessionManagerLayer::new(session_store);
let state = AppState { db: Arc::new(db) };
let app = Router::new()
Router::new()
.nest("/s/{id}/{code}", station::routes()) // TODO: maybe switch to "/"
.nest("/admin", admin::routes())
.route("/pico.css", get(serve_pico_css))
@ -130,7 +142,12 @@ pub async fn start(listener: TcpListener, db: SqlitePool) {
.route("/leaflet.js", get(serve_leaflet_js))
.route("/marker.png", get(serve_marker_png))
.with_state(state)
.layer(session_layer);
.layer(session_layer)
}
/// Starts the main application.
pub async fn start(listener: TcpListener, db: SqlitePool) {
let app = router(db);
axum::serve(listener, app).await.unwrap();
}

View File

@ -304,3 +304,42 @@ pub(super) fn routes() -> Router<AppState> {
.route("/team-finished/{team_id}", get(team_finished))
.route("/remove-left/{team_id}", get(remove_left))
}
#[cfg(test)]
mod test {
use crate::{router, testdb, Station};
use sqlx::SqlitePool;
use axum_test::TestServer;
#[sqlx::test]
async fn test_wrong_station() {
let pool = testdb!();
Station::create(&pool, "Teststation").await.unwrap();
let server = TestServer::new(router(pool)).unwrap();
let response = server.get("/s/1/wrong-pw").await;
response.assert_text_contains(
"Falscher Quick-Einlogg-Link. Bitte nochmal scannen oder neu eingeben.",
);
}
#[sqlx::test]
async fn test_correct_station() {
let pool = testdb!();
Station::create(&pool, "42-Station").await.unwrap();
let stations = Station::all(&pool).await;
let station = stations.last().unwrap();
let server = TestServer::new(router(pool)).unwrap();
let response = server.get(&format!("/s/1/{}", station.pw)).await;
response.assert_text_contains("42-Station");
}
}