some simple server tests (#1096)
* some simple server tests * fmt * logging in server test * log server errors * fix postgres uri * postgres ports * localhost again? * Rebase fixes --------- Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
This commit is contained in:
parent
c0449955e3
commit
c10ba684e0
6 changed files with 178 additions and 8 deletions
2
.github/workflows/nix.yml
vendored
2
.github/workflows/nix.yml
vendored
|
@ -19,7 +19,7 @@ jobs:
|
||||||
- name: Run nix flake check
|
- name: Run nix flake check
|
||||||
run: nix flake check --print-build-logs
|
run: nix flake check --print-build-logs
|
||||||
|
|
||||||
build:
|
build-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
12
.github/workflows/rust.yml
vendored
12
.github/workflows/rust.yml
vendored
|
@ -44,6 +44,16 @@ jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: atuin
|
||||||
|
POSTGRES_PASSWORD: pass
|
||||||
|
POSTGRES_DB: atuin
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
@ -62,6 +72,8 @@ jobs:
|
||||||
|
|
||||||
- name: Run cargo test
|
- name: Run cargo test
|
||||||
run: cargo test --all-features --workspace
|
run: cargo test --all-features --workspace
|
||||||
|
env:
|
||||||
|
ATUIN_DB_URI: postgres://atuin:pass@localhost:5432/atuin
|
||||||
|
|
||||||
- name: Run cargo check (all features)
|
- name: Run cargo check (all features)
|
||||||
run: cargo check --all-features --workspace
|
run: cargo check --all-features --workspace
|
||||||
|
|
33
Cargo.lock
generated
33
Cargo.lock
generated
|
@ -111,7 +111,9 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tiny-bip39",
|
"tiny-bip39",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"tracing-tree",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
@ -2947,6 +2949,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2965,6 +2979,19 @@ dependencies = [
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-tree"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92d6b63348fad3ae0439b8bebf8d38fb5bda0b115d7a8a7e6f165f12790c58c3"
|
||||||
|
dependencies = [
|
||||||
|
"is-terminal",
|
||||||
|
"nu-ansi-term",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try-lock"
|
name = "try-lock"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -3070,6 +3097,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
use std::net::{IpAddr, SocketAddr};
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
net::{IpAddr, SocketAddr, TcpListener},
|
||||||
|
};
|
||||||
|
|
||||||
use atuin_server_database::Database;
|
use atuin_server_database::Database;
|
||||||
use axum::Server;
|
use axum::Server;
|
||||||
|
@ -16,10 +19,15 @@ use tokio::signal;
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
async fn shutdown_signal() {
|
async fn shutdown_signal() {
|
||||||
signal::unix::signal(signal::unix::SignalKind::terminate())
|
let mut term = signal::unix::signal(signal::unix::SignalKind::terminate())
|
||||||
.expect("failed to register signal handler")
|
.expect("failed to register signal handler");
|
||||||
.recv()
|
let mut interrupt = signal::unix::signal(signal::unix::SignalKind::interrupt())
|
||||||
.await;
|
.expect("failed to register signal handler");
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
_ = term.recv() => {},
|
||||||
|
_ = interrupt.recv() => {},
|
||||||
|
};
|
||||||
eprintln!("Shutting down gracefully...");
|
eprintln!("Shutting down gracefully...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,16 +46,29 @@ pub async fn launch<Db: Database>(
|
||||||
port: u16,
|
port: u16,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let host = host.parse::<IpAddr>()?;
|
let host = host.parse::<IpAddr>()?;
|
||||||
|
launch_with_listener::<Db>(
|
||||||
|
settings,
|
||||||
|
TcpListener::bind(SocketAddr::new(host, port)).context("could not connect to socket")?,
|
||||||
|
shutdown_signal(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn launch_with_listener<Db: Database>(
|
||||||
|
settings: Settings<Db::Settings>,
|
||||||
|
listener: TcpListener,
|
||||||
|
shutdown: impl Future<Output = ()>,
|
||||||
|
) -> Result<()> {
|
||||||
let db = Db::new(&settings.db_settings)
|
let db = Db::new(&settings.db_settings)
|
||||||
.await
|
.await
|
||||||
.wrap_err_with(|| format!("failed to connect to db: {:?}", settings.db_settings))?;
|
.wrap_err_with(|| format!("failed to connect to db: {:?}", settings.db_settings))?;
|
||||||
|
|
||||||
let r = router::router(db, settings);
|
let r = router::router(db, settings);
|
||||||
|
|
||||||
Server::bind(&SocketAddr::new(host, port))
|
Server::from_tcp(listener)
|
||||||
|
.context("could not launch server")?
|
||||||
.serve(r.into_make_service())
|
.serve(r.into_make_service())
|
||||||
.with_graceful_shutdown(shutdown_signal())
|
.with_graceful_shutdown(shutdown)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -71,9 +71,14 @@ futures-util = "0.3"
|
||||||
fuzzy-matcher = "0.3.7"
|
fuzzy-matcher = "0.3.7"
|
||||||
colored = "2.0.4"
|
colored = "2.0.4"
|
||||||
ratatui = "0.21"
|
ratatui = "0.21"
|
||||||
|
tracing = "0.1"
|
||||||
|
|
||||||
|
|
||||||
[dependencies.tracing-subscriber]
|
[dependencies.tracing-subscriber]
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["ansi", "fmt", "registry", "env-filter"]
|
features = ["ansi", "fmt", "registry", "env-filter"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tracing-tree = "0.2"
|
||||||
|
|
99
atuin/tests/sync.rs
Normal file
99
atuin/tests/sync.rs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
use std::{env, net::TcpListener, time::Duration};
|
||||||
|
|
||||||
|
use atuin_client::api_client;
|
||||||
|
use atuin_common::utils::uuid_v7;
|
||||||
|
use atuin_server::{launch_with_listener, Settings as ServerSettings};
|
||||||
|
use atuin_server_postgres::{Postgres, PostgresSettings};
|
||||||
|
use futures_util::TryFutureExt;
|
||||||
|
use tokio::{sync::oneshot, task::JoinHandle};
|
||||||
|
use tracing::{dispatcher, Dispatch};
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
|
||||||
|
|
||||||
|
async fn start_server(path: &str) -> (String, oneshot::Sender<()>, JoinHandle<()>) {
|
||||||
|
let formatting_layer = tracing_tree::HierarchicalLayer::default()
|
||||||
|
.with_writer(tracing_subscriber::fmt::TestWriter::new())
|
||||||
|
.with_indent_lines(true)
|
||||||
|
.with_ansi(true)
|
||||||
|
.with_targets(true)
|
||||||
|
.with_indent_amount(2);
|
||||||
|
|
||||||
|
let dispatch: Dispatch = tracing_subscriber::registry()
|
||||||
|
.with(formatting_layer)
|
||||||
|
.with(EnvFilter::new("atuin_server=debug,info"))
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let db_uri = env::var("ATUIN_DB_URI")
|
||||||
|
.unwrap_or_else(|_| "postgres://atuin:pass@localhost:5432/atuin".to_owned());
|
||||||
|
|
||||||
|
let server_settings = ServerSettings {
|
||||||
|
host: "127.0.0.1".to_owned(),
|
||||||
|
port: 0,
|
||||||
|
path: path.to_owned(),
|
||||||
|
open_registration: true,
|
||||||
|
max_history_length: 8192,
|
||||||
|
max_record_size: 1024 * 1024 * 1024,
|
||||||
|
page_size: 1100,
|
||||||
|
register_webhook_url: None,
|
||||||
|
register_webhook_username: String::new(),
|
||||||
|
db_settings: PostgresSettings { db_uri },
|
||||||
|
};
|
||||||
|
|
||||||
|
let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel();
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
let addr = listener.local_addr().unwrap();
|
||||||
|
let server = tokio::spawn(async move {
|
||||||
|
let _tracing_guard = dispatcher::set_default(&dispatch);
|
||||||
|
|
||||||
|
if let Err(e) = launch_with_listener::<Postgres>(
|
||||||
|
server_settings,
|
||||||
|
listener,
|
||||||
|
shutdown_rx.unwrap_or_else(|_| ()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
tracing::error!(error=?e, "server error");
|
||||||
|
panic!("error running server: {e:?}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// let the server come online
|
||||||
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
||||||
|
|
||||||
|
(format!("http://{addr}{path}"), shutdown_tx, server)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn registration() {
|
||||||
|
let path = format!("/{}", uuid_v7().as_simple());
|
||||||
|
let (address, shutdown, server) = start_server(&path).await;
|
||||||
|
dbg!(&address);
|
||||||
|
|
||||||
|
let username = uuid_v7().as_simple().to_string();
|
||||||
|
let email = format!("{}@example.com", uuid_v7().as_simple());
|
||||||
|
let password = uuid_v7().as_simple().to_string();
|
||||||
|
|
||||||
|
// registration works
|
||||||
|
let registration_response = api_client::register(&address, &username, &email, &password)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let client = api_client::Client::new(&address, ®istration_response.session).unwrap();
|
||||||
|
|
||||||
|
// the session token works
|
||||||
|
let status = client.status().await.unwrap();
|
||||||
|
assert_eq!(status.username, username);
|
||||||
|
|
||||||
|
// login works
|
||||||
|
let login_response = api_client::login(
|
||||||
|
&address,
|
||||||
|
atuin_common::api::LoginRequest { username, password },
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// currently we return the same session token
|
||||||
|
assert_eq!(registration_response.session, login_response.session);
|
||||||
|
|
||||||
|
shutdown.send(()).unwrap();
|
||||||
|
server.await.unwrap();
|
||||||
|
}
|
Loading…
Reference in a new issue