From 190dad39b66306c6e760c07e53dda975d4ea4d6f Mon Sep 17 00:00:00 2001 From: Orion Kindel Date: Sun, 16 Jul 2023 03:08:02 -0400 Subject: [PATCH] feat: tests, updated submodules --- .gitignore | 1 + .gitmodules | 5 +- api | 2 +- db | 2 +- e2e/Cargo.lock | 4 +- e2e/Cargo.toml | 2 +- e2e/src/lib.rs | 124 +++++++++++++++++++++++++++-------------- e2e/src/user_signup.rs | 2 +- 8 files changed, 94 insertions(+), 48 deletions(-) diff --git a/.gitignore b/.gitignore index f07f2fa..83d8087 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ e2e/target +tmp diff --git a/.gitmodules b/.gitmodules index ca3e47e..bb7cf87 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,7 @@ url = git@git.orionkindel.com:dnim/db [submodule "api"] path = api - url = git@git.orionkindel.com:dnim/api + url = ../api + branch = main +[submodule "git@git.orionkindel.com:dnim/api"] + url = ../api diff --git a/api b/api index 568b248..46eaa49 160000 --- a/api +++ b/api @@ -1 +1 @@ -Subproject commit 568b248f3e82048865cd145088e118e3008278d5 +Subproject commit 46eaa4958691bb0b94fa985d5844a26eac29e93f diff --git a/db b/db index be07aca..202de79 160000 --- a/db +++ b/db @@ -1 +1 @@ -Subproject commit be07aca4c524820b299e7ec4f98d1400af33c067 +Subproject commit 202de7940069b5b6c39ded74b37313cccb5aa741 diff --git a/e2e/Cargo.lock b/e2e/Cargo.lock index d62c69a..e515e4e 100644 --- a/e2e/Cargo.lock +++ b/e2e/Cargo.lock @@ -945,9 +945,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toad" -version = "1.0.0-beta.4" +version = "1.0.0-beta.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7680b4a4868e2527ee0cb58b3850179f9ad9a44532b13fb9e4487a176091b71a" +checksum = "b305d4763b0236558486735374e796a028567a8d6f6a4c94c07096b73573ba0a" dependencies = [ "embedded-time", "log", diff --git a/e2e/Cargo.toml b/e2e/Cargo.toml index 8fd122b..43f155a 100644 --- a/e2e/Cargo.toml +++ b/e2e/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] postgres = {path = "../api/postgres/postgres"} -toad = "1.0.0-beta.4" +toad = "1.0.0-beta.6" toad-msg = "1.0.0-beta.2" nb = "1.1" simple_logger = "4.2" diff --git a/e2e/src/lib.rs b/e2e/src/lib.rs index eecc9ac..640aa45 100644 --- a/e2e/src/lib.rs +++ b/e2e/src/lib.rs @@ -8,11 +8,13 @@ mod __toad_aliases { mod user_signup; +use std::collections::HashMap; use std::fs::OpenOptions; use std::io::{Read, Write}; -use std::net::SocketAddr; +use std::net::{SocketAddr, UdpSocket}; use std::process::{Command, Stdio}; use std::sync::Once; +use std::thread::JoinHandle; use std::time::Duration; pub use __toad_aliases::Toad; @@ -21,35 +23,30 @@ pub fn run(script: S, init: R, mut fold_lines: F) -> R where S: AsRef, F: FnMut(R, &str) -> R { - let temppath = Command::new("mktemp").output().unwrap().stdout; - let temppath = String::from_utf8_lossy(&temppath); - let temppath = temppath.trim(); - - let mut child = Command::new("sh").args(["-c", script.as_ref()]) - .current_dir("../") - .stdout(OpenOptions::new().read(true) - .write(true) - .open(temppath) - .unwrap()) - .stderr(Stdio::piped()) - .spawn() - .unwrap(); + let mut child = Command::new("bash").args(["-c", script.as_ref()]) + .current_dir("../") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .unwrap(); let mut r: R = init; - let mut line_ix = 0usize; + let mut out = child.stdout.take().unwrap(); + let mut out_str = String::new(); + let mut seen = 0; macro_rules! do_fold { () => {{ - let out = std::fs::read_to_string(temppath).unwrap(); + out.read_to_string(&mut out_str).unwrap(); - #[allow(unused_assignments)] - while let Some(line) = out.split('\n').nth(line_ix) { - line_ix += 1; - if !line.trim().is_empty() { - r = fold_lines(r, line); - std::io::stdout().flush().unwrap(); - } - } + r = out_str.split('\n').skip(seen).fold(r, |mut r, line| { + if !line.trim().is_empty() { + r = fold_lines(r, line); + std::io::stdout().flush().unwrap(); + } + seen += 1; + r + }); }}; } @@ -75,21 +72,27 @@ pub fn run(script: S, init: R, mut fold_lines: F) -> R pub struct Fixture { pub toad: &'static Toad, pub api_addr: no_std_net::SocketAddr, + pub api_pid: usize, pub pg: postgres::Client, } +impl Drop for Fixture { + fn drop(&mut self) { + run(format!("kill {}", self.api_pid), (), |_, _| ()); + } +} + pub fn init() -> Fixture { - static mut SHARED: Option = None; + struct ApiThreadPorts { + used: Vec, + available: Vec, + } + + static mut SHARED: Option<(Toad, ApiThreadPorts)> = None; static INIT: Once = Once::new(); INIT.call_once(|| { - simple_logger::init().unwrap(); - - log::info!("[init] sync repos"); - run("git fetch --recurse-submodules 2>&1; git submodule update --init --recursive 2>&1", - (), - |_, _| print!(".")); - println!(); + simple_logger::init_with_level(log::Level::Info).unwrap(); log::info!("[init] build db"); run("cd db; docker compose up -d 2>&1; ./scripts/build.sh 2>&1", @@ -97,25 +100,64 @@ pub fn init() -> Fixture { |_, _| print!(".")); println!(); - log::info!("[init] start api"); - std::thread::spawn(|| { - run("cd api; cargo run", (), |_, line| println!("{line}")); - }); - - let toad = Toad::try_new("127.0.0.1:4445".parse::().unwrap(), + let toad = Toad::try_new("127.0.0.1:3999".parse::().unwrap(), Default::default()).unwrap(); + + let available_ports: Vec = + (4000..5000).filter(|p| UdpSocket::bind(format!("127.0.0.1:{p}")).is_ok()) + .collect(); + log::info!("[init] {} ports available for api threads", + available_ports.len()); + unsafe { - SHARED = Some(toad); + SHARED = Some((toad, + ApiThreadPorts { used: vec![], + available: available_ports })); } }); + while unsafe { SHARED.as_ref() }.is_none() { + std::thread::sleep(std::time::Duration::from_millis(500)); + } + + log::info!("[init] start api"); + let ports = &mut unsafe { SHARED.as_mut() }.unwrap().1; + let port = ports.available.first().unwrap(); + ports.used.push(*port); + + let env = HashMap::from([("POSTGRES_HOST", "127.0.0.1".to_string()), + ("POSTGRES_PORT", "5432".to_string()), + ("POSTGRES_USER", "postgres".to_string()), + ("POSTGRES_PASS", "password".to_string()), + ("API_ADDR", format!("127.0.0.1:{port}"))]); + + let env_sh = env.iter() + .fold(String::new(), |b, (k, v)| format!("{b} {k}=\"{v}\"")); + + let api_pid = run(format!("cd api; {env_sh} cargo run 1>../tmp/log.{port} 2>../tmp/log.{port} & echo $!; disown -h"), String::new(), |s, pid| format!("{s}{pid}")); + let api_pid = usize::from_str_radix(&api_pid.trim(), 10).unwrap(); + Fixture { - toad: unsafe {SHARED.as_ref()}.unwrap(), - api_addr: "127.0.0.1:4444".parse().unwrap(), + toad: &unsafe {SHARED.as_ref()}.unwrap().0, + api_addr: env.get("API_ADDR").unwrap().parse().unwrap(), + api_pid, pg: postgres::Client::connect("host=127.0.0.1 port=5432 dbname=dnim user=postgres password=password", postgres::NoTls).unwrap(), } } +#[test] +fn run_works() { + let s = run("echo foo; echo bar", String::new(), |b, a| { + format!("{b}\n{a}") + }); + assert_eq!(s, "\nfoo\nbar"); + + let s = run("nohup sleep 10 >/dev/null & echo $!", + String::new(), + |b, a| format!("{b}\n{a}")); + usize::from_str_radix(&s.trim().split('\n').nth(0).unwrap(), 10).unwrap(); +} + #[test] fn init_works() { init(); diff --git a/e2e/src/user_signup.rs b/e2e/src/user_signup.rs index 08f7c95..cb18c51 100644 --- a/e2e/src/user_signup.rs +++ b/e2e/src/user_signup.rs @@ -61,7 +61,7 @@ pub fn user_signup() { let get_signup = Addrd(get_signup, fx.api_addr); let rep = nb::block!({ - std::thread::sleep(std::time::Duration::from_micros(500)); + std::thread::sleep(std::time::Duration::from_millis(100)); fx.toad.send_req(&get_signup) }).unwrap();