chore(release): prepare public source release
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "await"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
readme.workspace = true
|
||||
publish.workspace = true
|
||||
description = "Wait for paths, ports, HTTP endpoints, or repeated commands with bounded polling."
|
||||
keywords.workspace = true
|
||||
categories.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "awaitcmd"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
common = { path = "../common", default-features = false }
|
||||
lexopt.workspace = true
|
||||
native-tls.workspace = true
|
||||
runtimekit = { path = "../runtimekit" }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd.workspace = true
|
||||
predicates.workspace = true
|
||||
tempfile.workspace = true
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
//! Binary entry point for `await`.
|
||||
#![allow(
|
||||
clippy::multiple_crate_versions,
|
||||
reason = "native-tls is already used elsewhere in the workspace and cargo deny remains the dependency audit gate"
|
||||
)]
|
||||
|
||||
fn main() {
|
||||
std::process::exit(awaitcmd::main_entry());
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
//! Integration tests for the `await` command.
|
||||
|
||||
use std::fs;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::TcpListener;
|
||||
use std::thread;
|
||||
|
||||
use assert_cmd::Command;
|
||||
use predicates::prelude::*;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn cargo_command() -> Command {
|
||||
Command::cargo_bin("await").expect("binary")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_args_prints_quick_help_card() {
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.assert()
|
||||
.code(2)
|
||||
.stdout(predicate::str::is_empty())
|
||||
.stderr(predicate::str::contains(
|
||||
"error: provide a subcommand: path, port, http, or run",
|
||||
))
|
||||
.stderr(predicate::str::contains("await - Mercury Toolbox"))
|
||||
.stderr(predicate::str::contains("Usage:"))
|
||||
.stderr(predicate::str::contains("await [OPTIONS] path <PATH>"))
|
||||
.stderr(predicate::str::contains("await [OPTIONS] port <TARGET>"))
|
||||
.stderr(predicate::str::contains(
|
||||
"Type 'await --help' for the full command reference.",
|
||||
));
|
||||
}
|
||||
|
||||
fn spawn_http_server(response: &'static [u8]) -> u16 {
|
||||
let listener = TcpListener::bind(("127.0.0.1", 0)).expect("listener");
|
||||
let port = listener.local_addr().expect("address").port();
|
||||
thread::spawn(move || {
|
||||
if let Ok((mut stream, _)) = listener.accept() {
|
||||
let mut buffer = [0_u8; 1024];
|
||||
let _ = stream.read(&mut buffer);
|
||||
let _ = stream.write_all(response);
|
||||
}
|
||||
});
|
||||
port
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn help_mentions_v3_modes() {
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--help")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("path <PATH>"))
|
||||
.stdout(predicate::str::contains("port <TARGET>"))
|
||||
.stdout(predicate::str::contains("http <URL>"))
|
||||
.stdout(predicate::str::contains("--state exists|missing"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_mode_supports_missing_state() {
|
||||
let temp = TempDir::new().expect("temp dir");
|
||||
let missing = temp.path().join("missing.flag");
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("path")
|
||||
.arg(missing)
|
||||
.arg("--json")
|
||||
.arg("--state")
|
||||
.arg("missing")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"ok\":true"))
|
||||
.stdout(predicate::str::contains("\"kind\":\"path\""))
|
||||
.stdout(predicate::str::contains("\"state\":\"missing\""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn port_mode_uses_tcp_scheme_target() {
|
||||
let listener = TcpListener::bind(("127.0.0.1", 0)).expect("listener");
|
||||
let address = listener.local_addr().expect("address");
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("--timeout")
|
||||
.arg("800ms")
|
||||
.arg("--interval")
|
||||
.arg("50ms")
|
||||
.arg("port")
|
||||
.arg(format!("tcp://127.0.0.1:{}", address.port()))
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"ok\":true"))
|
||||
.stdout(predicate::str::contains("\"kind\":\"port\""))
|
||||
.stdout(predicate::str::contains("\"target\":\"tcp://127.0.0.1:"));
|
||||
drop(listener);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_mode_supports_status_matching() {
|
||||
let port = spawn_http_server(b"HTTP/1.1 204 No Content\r\nContent-Length: 0\r\n\r\n");
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("--timeout")
|
||||
.arg("800ms")
|
||||
.arg("--interval")
|
||||
.arg("50ms")
|
||||
.arg("http")
|
||||
.arg(format!("http://127.0.0.1:{port}/health"))
|
||||
.arg("--status")
|
||||
.arg("204")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"ok\":true"))
|
||||
.stdout(predicate::str::contains("\"kind\":\"http\""))
|
||||
.stdout(predicate::str::contains("\"status_code\":204"));
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn run_mode_retries_until_exit_code_matches() {
|
||||
let temp = TempDir::new().expect("temp dir");
|
||||
let marker = temp.path().join("ready.flag");
|
||||
let script = temp.path().join("flip.ps1");
|
||||
fs::write(
|
||||
&script,
|
||||
format!(
|
||||
"if (Test-Path '{}') {{ exit 0 }}\nNew-Item -ItemType File -Path '{}' | Out-Null\nexit 9\n",
|
||||
marker.display(),
|
||||
marker.display()
|
||||
),
|
||||
)
|
||||
.expect("script");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("--timeout")
|
||||
.arg("20s")
|
||||
.arg("--interval")
|
||||
.arg("100ms")
|
||||
.arg("run")
|
||||
.arg("--shell")
|
||||
.arg("pwsh")
|
||||
.arg("--exit-code")
|
||||
.arg("0")
|
||||
.arg("--")
|
||||
.arg(script)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"ok\":true"))
|
||||
.stdout(predicate::str::contains("\"attempts\":2"))
|
||||
.stdout(predicate::str::contains("\"kind\":\"run\""))
|
||||
.stdout(predicate::str::contains("\"exit_code\":0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_mode_times_out_when_requested_state_never_arrives() {
|
||||
let temp = TempDir::new().expect("temp dir");
|
||||
let existing = temp.path().join("ready.flag");
|
||||
fs::write(&existing, "ready").expect("flag");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.args(["--timeout", "150ms", "--interval", "50ms", "path"])
|
||||
.arg(&existing)
|
||||
.arg("--state")
|
||||
.arg("missing")
|
||||
.assert()
|
||||
.code(1)
|
||||
.stdout(predicate::str::contains("timeout condition=path:missing:"))
|
||||
.stdout(predicate::str::contains("last=path:ok=false:exists=true"));
|
||||
}
|
||||
Reference in New Issue
Block a user