WIP
test / test (push) Failing after 18s Details

This commit is contained in:
Luca Bilke 2024-07-02 23:18:02 +02:00
parent 62cd2f8f42
commit e6fa834473
No known key found for this signature in database
GPG Key ID: C9E851809C1A5BDE
9 changed files with 128 additions and 75 deletions

View File

@ -10,8 +10,9 @@ gleam shell # Run an Erlang shell
## TODO ## TODO
- [X] Handle link GET - [x] Handle link GET
- [X] Handle link POST - [x] Handle link POST
- [ ] Handle file POST - [ ] Handle file POST
- [ ] Handle file GET - [ ] Handle file GET
- [ ] Web Frontend - [ ] Web Frontend
- [ ] fix config loading from env

View File

@ -69,25 +69,15 @@ pub fn load_config_from_env() -> Config {
postgres_pool_size: 15, postgres_pool_size: 15,
) )
Config( Config(
port: "PORT" port: get_int_or("PORT", defaults.port),
|> get_int_or(defaults.port), max_bytes: get_int_or("MAX_BYTES", defaults.max_bytes),
max_bytes: "MAX_BYTES" url_root: get_string_or("URL_ROOT", defaults.url_root),
|> get_int_or(defaults.max_bytes), secret_key_base: get_string_or("SECRET_KEY_BASE", defaults.secret_key_base),
url_root: "URL_ROOT" postgres_host: get_string_or("PG_HOST", defaults.postgres_host),
|> get_string_or(defaults.url_root), postgres_db: get_string_or("PG_DB", defaults.postgres_db),
secret_key_base: "SECRET_KEY_BASE" postgres_user: get_string_or("PG_USER", defaults.postgres_user),
|> get_string_or(defaults.secret_key_base), postgres_password: get_string_or("PG_PASSWORD", defaults.postgres_password),
postgres_host: "POSTGRES_HOST" postgres_pool_size: get_int_or("PG_POOL_SIZE", defaults.postgres_pool_size),
|> get_string_or(defaults.postgres_host), postgres_port: get_int_or("PG_PORT", defaults.postgres_port),
postgres_db: "POSTGRES_DB"
|> get_string_or(defaults.postgres_db),
postgres_user: "POSTGRES_USER"
|> get_string_or(defaults.postgres_user),
postgres_password: "POSTGRES_PASSWORD"
|> get_string_or(defaults.postgres_password),
postgres_pool_size: "POSTGRES_POOL_SIZE"
|> get_int_or(defaults.postgres_pool_size),
postgres_port: "POSTGRES_PORT"
|> get_int_or(defaults.postgres_port),
) )
} }

View File

@ -11,10 +11,10 @@ import ids/cuid
import wisp.{type Request, type Response} import wisp.{type Request, type Response}
const schema = " const schema = "
CREATE TABLE IF NOT EXISTS \"File\" ( CREATE TABLE IF NOT EXISTS \"file\" (
Cuid CHAR(25) PRIMARY KEY, cuid CHAR(25) PRIMARY KEY,
Md5Hash CHAR(32) md5hash CHAR(32),
FileName TEXT fileName TEXT
); );
" "
@ -29,7 +29,7 @@ pub fn prepare_database(ctx: Context) -> Result(Nil, pgo.QueryError) {
pub fn store(file: File, ctx: Context) -> Result(String, Nil) { pub fn store(file: File, ctx: Context) -> Result(String, Nil) {
let sql = let sql =
"INSERT INTO \"File\" (Cuid, Md5Hash) VALUES ($1, $2) RETURNING Cuid;" "INSERT INTO \"file\" (cuid, md5hash) VALUES ($1, $2) RETURNING cuid;"
case case
pgo.execute( pgo.execute(
sql, sql,
@ -45,7 +45,7 @@ pub fn store(file: File, ctx: Context) -> Result(String, Nil) {
} }
pub fn retrieve(cuid: String, ctx: Context) -> Result(File, Nil) { pub fn retrieve(cuid: String, ctx: Context) -> Result(File, Nil) {
let sql = "SELECT Cuid,Md5Hash,FileName FROM \"File\" WHERE Cuid = $1;" let sql = "SELECT cuid,md5hash,filename FROM \"file\" WHERE cuid = $1;"
case case
pgo.execute( pgo.execute(
sql, sql,

View File

@ -10,9 +10,9 @@ import ids/cuid
import wisp.{type Request, type Response} import wisp.{type Request, type Response}
const schema = " const schema = "
CREATE TABLE IF NOT EXISTS \"Link\" ( CREATE TABLE IF NOT EXISTS \"link\" (
Cuid CHAR(25) PRIMARY KEY, cuid CHAR(25) PRIMARY KEY,
TargetURL TEXT targeturl TEXT
); );
" "
@ -27,7 +27,7 @@ pub fn prepare_database(ctx: Context) -> Result(Nil, pgo.QueryError) {
pub fn store(link: Link, ctx: Context) -> Result(String, Nil) { pub fn store(link: Link, ctx: Context) -> Result(String, Nil) {
let sql = let sql =
"INSERT INTO \"Link\" (Cuid, TargetURL) VALUES ($1, $2) RETURNING Cuid;" "INSERT INTO \"link\" (cuid, targeturl) VALUES ($1, $2) RETURNING cuid;"
case case
pgo.execute( pgo.execute(
sql, sql,
@ -43,7 +43,7 @@ pub fn store(link: Link, ctx: Context) -> Result(String, Nil) {
} }
pub fn retrieve(cuid: String, ctx: Context) -> Result(Link, Nil) { pub fn retrieve(cuid: String, ctx: Context) -> Result(Link, Nil) {
let sql = "SELECT Cuid,TargetURL FROM \"Link\" WHERE Cuid = $1;" let sql = "SELECT cuid,targeturl FROM \"link\" WHERE cuid = $1;"
case case
pgo.execute( pgo.execute(
sql, sql,

View File

@ -1,10 +1,11 @@
import app/config.{type Context, Config, Context} import app/config.{type Context, Config, Context}
import app/web/file import app/web/file
import gleam/dynamic import gleam/dynamic
import gleam/option.{None, Some} import gleam/option.{Some}
import gleam/pgo import gleam/pgo.{type Returned}
import gleam/string import gleam/string
import gleeunit/should import gleeunit/should
import ids/cuid
const test_config = Config( const test_config = Config(
port: 8080, port: 8080,
@ -20,6 +21,7 @@ const test_config = Config(
) )
fn with_context(testcase: fn(Context) -> t) -> t { fn with_context(testcase: fn(Context) -> t) -> t {
let assert Ok(cuid) = cuid.start()
let ctx = let ctx =
Context( Context(
db: pgo.Config( db: pgo.Config(
@ -33,6 +35,7 @@ fn with_context(testcase: fn(Context) -> t) -> t {
) )
|> pgo.connect, |> pgo.connect,
config: test_config, config: test_config,
cuid: cuid,
) )
case file.prepare_database(ctx) { case file.prepare_database(ctx) {
@ -44,25 +47,41 @@ fn with_context(testcase: fn(Context) -> t) -> t {
ret ret
} }
Error(e) -> { Error(e) -> {
e |> string.inspect |> panic panic as string.inspect(e)
} }
} }
} }
pub fn null_test() { fn cleanup() {
use ctx <- with_context() use ctx <- with_context()
let assert Ok(_) =
pgo.execute("DROP TABLE file;", ctx.db, [], dynamic.dynamic)
}
pub fn prepare_database_test() {
use ctx <- with_context()
let res =
pgo.execute( pgo.execute(
"select $1", "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'file';",
ctx.db, ctx.db,
[pgo.null()], [],
dynamic.element(0, dynamic.optional(dynamic.int)), dynamic.tuple2(dynamic.string, dynamic.string),
) )
|> should.equal(Ok(pgo.Returned(count: 1, rows: [None])))
res
|> should.be_ok
|> fn(x: Returned(#(String, String))) { x.rows }
|> should.equal([
#("cuid", "character"),
#("md5hash", "character"),
#("filename", "text"),
])
cleanup()
} }
pub fn hash_to_path_test() { pub fn hash_to_path_test() {
"f7b478961451483b8c251c788750d5ef" "f7b478961451483b8c251c788750d5ef"
|> file.hash_to_path |> file.hash_to_path
|> should.equal(["f7", "b4", "78961451483b8c251c788750d5ef"]) |> should.equal("/f7/b4/78961451483b8c251c788750d5ef")
} }

View File

@ -1,13 +1,12 @@
import app/config.{type Context, Config, Context} import app/config.{type Context, Config, Context}
import app/web/link.{Link} import app/web/link.{Link}
import gleam/dynamic import gleam/dynamic
import gleam/option.{None, Some} import gleam/option.{Some}
import gleam/pgo import gleam/pgo.{type Returned}
import gleam/result
import gleam/string import gleam/string
import gleam/uri import gleam/uri
import gleeunit/should import gleeunit/should
import ids/nanoid import ids/cuid
const test_config = Config( const test_config = Config(
port: 8080, port: 8080,
@ -23,6 +22,7 @@ const test_config = Config(
) )
fn with_context(testcase: fn(Context) -> t) -> t { fn with_context(testcase: fn(Context) -> t) -> t {
let assert Ok(cuid) = cuid.start()
let ctx = let ctx =
Context( Context(
db: pgo.Config( db: pgo.Config(
@ -36,6 +36,7 @@ fn with_context(testcase: fn(Context) -> t) -> t {
) )
|> pgo.connect, |> pgo.connect,
config: test_config, config: test_config,
cuid: cuid,
) )
case link.prepare_database(ctx) { case link.prepare_database(ctx) {
@ -52,39 +53,42 @@ fn with_context(testcase: fn(Context) -> t) -> t {
} }
} }
pub fn null_test() { fn cleanup() {
use ctx <- with_context() use ctx <- with_context()
let assert Ok(_) =
pgo.execute("DROP TABLE link;", ctx.db, [], dynamic.dynamic)
}
pub fn prepare_database_test() {
use ctx <- with_context()
let res =
pgo.execute( pgo.execute(
"select $1", "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'link';",
ctx.db, ctx.db,
[pgo.null()], [],
dynamic.element(0, dynamic.optional(dynamic.int)), dynamic.tuple2(dynamic.string, dynamic.string),
) )
|> should.equal(Ok(pgo.Returned(count: 1, rows: [None])))
res
|> should.be_ok
|> fn(x: Returned(#(String, String))) { x.rows }
|> should.equal([#("cuid", "character"), #("targeturl", "text")])
cleanup()
} }
pub fn generate_url_test() { pub fn store_retreive_test() {
use ctx <- with_context()
let test_id = Ok("testid_generate_url")
link.generate_url(test_id, ctx)
|> should.equal(uri.parse("http://localhost:8080/l/testid_generate_url"))
}
pub fn store_link_test() {
use ctx <- with_context() use ctx <- with_context()
let assert Ok(test_url) = uri.parse("http://example.com/") let assert Ok(test_url) = uri.parse("http://example.com/")
let test_id = nanoid.generate() let test_id = cuid.generate(ctx.cuid)
let stored_nano_id = let cuid =
Link(test_id, test_url) Link(test_id, test_url)
|> link.store(ctx) |> link.store(ctx)
|> result.try_recover(fn(e) { e |> string.inspect |> Ok }) |> should.be_ok
|> result.unwrap("Undefined Error")
stored_nano_id |> should.equal(test_id) cuid |> should.equal(test_id)
let assert Ok(stored_link) = stored_nano_id |> link.retrieve(ctx) let assert Ok(stored_link) = cuid |> link.retrieve(ctx)
stored_link.target_url |> should.equal(test_url) stored_link.target_url |> should.equal(test_url)
} }

View File

@ -2,8 +2,26 @@ services:
db: db:
image: postgres:latest image: postgres:latest
environment: environment:
- POSTGRES_USER=dumptruck POSTGRES_USER: dumptruck
- POSTGRES_PASSWORD=dumptruck POSTGRES_PASSWORD: dumptruck
- POSTGRES_DB=dumptruck POSTGRES_DB: dumptruck
ports: ports:
- "5432:5432" - "5432:5432"
frontend:
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: "test@example.com"
PGADMIN_DEFAULT_PASSWORD: "test"
PGADMIN_LISTEN_PORT: "80"
PGADMIN_CONFIG_SERVER_MODE: "False"
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False"
depends_on:
- "db"
volumes:
- read_only: true
source: "servers.json"
target: "/pgadmin4/servers.json"
type: bind
ports:
- "8080:80"

15
test/servers.json Normal file
View File

@ -0,0 +1,15 @@
{
"Servers": {
"1": {
"Group": "Servers",
"Name": "Docker",
"Host": "db",
"Port": 5432,
"MaintenanceDB": "dumptruck",
"Username": "dumptruck",
"Password": "dumptruck",
"SSLMode": "prefer",
"Favorite": true
}
}
}

6
testenv Normal file
View File

@ -0,0 +1,6 @@
#!/bin/sh
export URL_ROOT="http://localhost:8080"
export PG_HOST="localhost"
export PG_DB="dumptruck"
export PG_USER="dumptruck"
export PG_PASSWORD="dumptruck"