Tests, examples and run lines use placeholder credentials (#332)
Test fixtures pass "player"/"secret"; the run lines in `.cargo/config.toml`, the protocol examples and the auth and world binaries show placeholders; the SRP probe example takes --user and --pass instead of defaulting them. Built on macOS. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d8f4f31ea1
commit
0fe1ea87b9
+1
-1
@@ -1,5 +1,5 @@
|
||||
# `cargo play` — the run loop. Same optimization as `--release`, plus incremental compilation (see
|
||||
# `[profile.play]` in the workspace Cargo.toml for why it is a separate profile and not a flip of
|
||||
# `release`). Env vars still prefix it: `WOW_USER=one WOW_PASS=pone cargo play`.
|
||||
# `release`). Env vars still prefix it: `WOW_USER=<account> WOW_PASS=<password> cargo play`.
|
||||
[alias]
|
||||
play = "run --profile play -p benilla"
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
//! lighting model (`Light.dbc` sampled against the server clock) with a sky dome, sun/moon discs, and
|
||||
//! distance fog; a faithful `EffectGlow` bloom on top.
|
||||
//!
|
||||
//! In parallel a background thread ([`net`]) logs in (`$WOW_USER`/`$WOW_PASS`/`$WOW_HOST`, default
|
||||
//! `one`/`pone`/`localhost`), enters the world, and streams object updates. NPCs and GameObjects
|
||||
//! In parallel a background thread ([`net`]) logs in (`$WOW_USER`/`$WOW_PASS`/`$WOW_HOST`, host
|
||||
//! default `localhost`), enters the world, and streams object updates. NPCs and GameObjects
|
||||
//! render as their real models (resolved from the display id via the creature/GameObject catalogs); other
|
||||
//! players stay cyan cubes, and our own avatar is blue until we take third-person control of it.
|
||||
//! **The world is loaded when a character enters it, and released when they leave** — the glue
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//!
|
||||
//! This module owns the **credential policy** — the 0193 §3 mirror for the IO thread's pre-logon
|
||||
//! park: the env fast path (`WOW_USER` and `WOW_PASS` both set auto-submits
|
||||
//! with the old `one`/`pone` defaults, so every probe/smoke invocation keeps working), the
|
||||
//! with the old default account, so every probe/smoke invocation keeps working), the
|
||||
//! pending-credentials resubmit (paced at the flat 3 s, app-side — the IO thread never sleeps),
|
||||
//! and the director's typed submit. A *refused* code (bad password) clears the intent and shows
|
||||
//! the authored `AUTH_*` dialog — never an auto-retry against a refusal.
|
||||
@@ -1230,7 +1230,8 @@ mod tests {
|
||||
#[test]
|
||||
fn a_lost_session_clears_the_credentials_and_shows_the_dialog() {
|
||||
let (mut app, _requests) = policy_app();
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds = Some(("one".into(), "pone".into()));
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds =
|
||||
Some(("player".into(), "secret".into()));
|
||||
app.world_mut().write_message(DisconnectedMessage {
|
||||
reason: "disconnected: world stream closed: failed to fill whole buffer".into(),
|
||||
end: benilla_protocol::SessionEnd::Lost,
|
||||
@@ -1258,7 +1259,8 @@ mod tests {
|
||||
#[test]
|
||||
fn a_logout_teardown_still_relists_at_once() {
|
||||
let (mut app, _requests) = policy_app();
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds = Some(("one".into(), "pone".into()));
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds =
|
||||
Some(("player".into(), "secret".into()));
|
||||
app.world_mut().write_message(DisconnectedMessage {
|
||||
reason: "logged out".into(),
|
||||
end: benilla_protocol::SessionEnd::LoggedOut,
|
||||
@@ -1331,7 +1333,7 @@ mod tests {
|
||||
fn an_unattended_run_still_reconnects_on_its_own() {
|
||||
let (mut app, _requests) = policy_app();
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds =
|
||||
Some(("probe1".into(), "pprobe1".into()));
|
||||
Some(("probe1".into(), "secret".into()));
|
||||
app.world_mut().write_message(DisconnectedMessage {
|
||||
reason: "disconnected: connection reset".into(),
|
||||
end: benilla_protocol::SessionEnd::Lost,
|
||||
@@ -1363,13 +1365,13 @@ mod tests {
|
||||
// Credentials pending with the retry due: the policy's silent submit tick.
|
||||
{
|
||||
let mut intent = app.world_mut().resource_mut::<LoginIntent>();
|
||||
intent.creds = Some(("one".into(), "pone".into()));
|
||||
intent.creds = Some(("player".into(), "secret".into()));
|
||||
intent.retry_at = Some(0.0);
|
||||
}
|
||||
app.update();
|
||||
|
||||
let sent = requests.try_recv().expect("the policy submitted");
|
||||
assert_eq!(sent.user, "one");
|
||||
assert_eq!(sent.user, "player");
|
||||
assert_eq!(
|
||||
sent.host, "logon.example.org:3725",
|
||||
"the attempt dials what the realmlist says, not a value latched at spawn",
|
||||
@@ -1444,7 +1446,8 @@ mod tests {
|
||||
|
||||
// The status dialog's Cancel: the attempt is abandoned and the credentials forgotten, so
|
||||
// nothing resubmits behind the player's back.
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds = Some(("one".into(), "pone".into()));
|
||||
app.world_mut().resource_mut::<LoginIntent>().creds =
|
||||
Some(("player".into(), "secret".into()));
|
||||
app.world_mut().resource_mut::<LoginIntent>().in_flight = true;
|
||||
app.world_mut()
|
||||
.resource_mut::<GlueDialog>()
|
||||
@@ -1581,8 +1584,8 @@ mod tests {
|
||||
|
||||
// 1 · The director's actual launch line, verbatim from `.cargo/config.toml`'s example.
|
||||
// Nothing here says anybody is absent, so nothing may end the run — typed or not.
|
||||
let _user = crate::local_state::test_env::EnvGuard::set("WOW_USER", "one");
|
||||
let _pass = crate::local_state::test_env::EnvGuard::set("WOW_PASS", "pone");
|
||||
let _user = crate::local_state::test_env::EnvGuard::set("WOW_USER", "player");
|
||||
let _pass = crate::local_state::test_env::EnvGuard::set("WOW_PASS", "secret");
|
||||
let _char = crate::local_state::test_env::EnvGuard::set("WOW_CHAR", "One");
|
||||
let _decl = crate::local_state::test_env::EnvGuard::unset("WOW_UNATTENDED");
|
||||
let _cap = crate::local_state::test_env::EnvGuard::unset("WOW_CAPTURE");
|
||||
@@ -1659,13 +1662,13 @@ mod tests {
|
||||
fn the_login_press_asks_for_the_account_before_the_password() {
|
||||
let mut form = LoginForm::default();
|
||||
assert_eq!(login_press(&form), LoginPress::NeedAccount);
|
||||
form.account.set_text("one");
|
||||
form.account.set_text("player");
|
||||
assert_eq!(login_press(&form), LoginPress::NeedPassword);
|
||||
form.password.set_text("pone");
|
||||
form.password.set_text("secret");
|
||||
assert_eq!(login_press(&form), LoginPress::Submit);
|
||||
// And a password-only form still asks for the account, not the password.
|
||||
let mut only_pass = LoginForm::default();
|
||||
only_pass.password.set_text("pone");
|
||||
only_pass.password.set_text("secret");
|
||||
assert_eq!(login_press(&only_pass), LoginPress::NeedAccount);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,10 +98,10 @@ mod tests {
|
||||
#[test]
|
||||
fn the_smoke_spec_splits_three_ways() {
|
||||
assert_eq!(
|
||||
smoke_spec("probe1:pprobe1:Probeone"),
|
||||
("probe1", "pprobe1", Some("Probeone"))
|
||||
smoke_spec("probe1:secret:Probeone"),
|
||||
("probe1", "secret", Some("Probeone"))
|
||||
);
|
||||
assert_eq!(smoke_spec("probe1:pprobe1"), ("probe1", "pprobe1", None));
|
||||
assert_eq!(smoke_spec("probe1:secret"), ("probe1", "secret", None));
|
||||
// A trailing colon names no body; a password may not itself contain one (the client caps
|
||||
// both fields at 16 letters and vmangos accounts have none).
|
||||
assert_eq!(smoke_spec("one:pass:"), ("one", "pass", None));
|
||||
|
||||
@@ -2978,7 +2978,7 @@ mod tests {
|
||||
///
|
||||
/// 1262 was built and verified in August and then quietly stopped working, with none of its
|
||||
/// code touched: the verdict asked the *environment* whether anybody was here, and on
|
||||
/// 2026-08-29 the director's launch line became `WOW_USER=one WOW_PASS=pone cargo play` — the
|
||||
/// 2026-08-29 the director's launch line became `WOW_USER=… WOW_PASS=… cargo play` — the
|
||||
/// example line in our own `.cargo/config.toml`. From that moment every session they played
|
||||
/// was "a probe", so a kick meant reconnect, and the account ping-ponged exactly as B252
|
||||
/// reported. Nothing about the fix was wrong; the fact under it was. 1769 made the claim a
|
||||
@@ -2997,8 +2997,8 @@ mod tests {
|
||||
|
||||
// The director's launch line, verbatim. Credentials in the environment, nobody declared
|
||||
// absent — this is a person playing, and a lost session is over.
|
||||
let _user = EnvGuard::set("WOW_USER", "one");
|
||||
let _pass = EnvGuard::set("WOW_PASS", "pone");
|
||||
let _user = EnvGuard::set("WOW_USER", "player");
|
||||
let _pass = EnvGuard::set("WOW_PASS", "secret");
|
||||
let _char = EnvGuard::set("WOW_CHAR", "One");
|
||||
let _decl = EnvGuard::unset("WOW_UNATTENDED");
|
||||
let _cap = EnvGuard::unset("WOW_CAPTURE");
|
||||
|
||||
@@ -96,7 +96,7 @@ pub(crate) fn env_login() -> bool {
|
||||
///
|
||||
/// **This is the fact [`env_login`] was mistaken for, twice.** Env credentials mean "log in without
|
||||
/// typing"; they say nothing about the room — and the director plays with
|
||||
/// `WOW_USER=one WOW_PASS=pone cargo play`, which is the example line in `.cargo/config.toml`. So
|
||||
/// `WOW_USER=… WOW_PASS=… cargo play`, the example line in `.cargo/config.toml`. So
|
||||
/// every session they played read as "a harness": a typed password's refusal killed the process
|
||||
/// (fixed on 2026-08-28 by asking `announced` — direct evidence — instead of the environment) and,
|
||||
/// the half that fix left standing, a kick sent the client racing to take the account back instead
|
||||
@@ -451,11 +451,11 @@ mod tests {
|
||||
let _c = EnvGuard::unset("WOW_CHAR");
|
||||
assert!(!env_login() && !unattended());
|
||||
}
|
||||
// `WOW_USER=one WOW_PASS=pone cargo play` — `.cargo/config.toml`'s own example, and the
|
||||
// `WOW_USER=… WOW_PASS=… cargo play`, `.cargo/config.toml`'s example, and the
|
||||
// director's launch line since 2026-08-29. Log them in without typing, yes. Decide things
|
||||
// on their behalf, no.
|
||||
let _u = EnvGuard::set("WOW_USER", "one");
|
||||
let _p = EnvGuard::set("WOW_PASS", "pone");
|
||||
let _u = EnvGuard::set("WOW_USER", "player");
|
||||
let _p = EnvGuard::set("WOW_PASS", "secret");
|
||||
assert!(env_login(), "the fast path still submits for them");
|
||||
assert!(
|
||||
!unattended(),
|
||||
@@ -471,19 +471,19 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn the_fast_path_is_the_declared_account_or_refused() {
|
||||
let id = parse_identity("WOW_USER=probe4\nWOW_PASS=pprobe4\nWOW_CHAR=Probefour\n").unwrap();
|
||||
let id = parse_identity("WOW_USER=probe4\nWOW_PASS=secret\nWOW_CHAR=Probefour\n").unwrap();
|
||||
// Our own account: the whole point of the declaration.
|
||||
assert!(guard_for(Some(&id), "probe4").is_ok());
|
||||
assert!(guard_for(Some(&id), "PROBE4").is_ok()); // vmangos accounts are case-insensitive
|
||||
|
||||
// Anyone else's account — a player's, another checkout's probe — kicks a live session.
|
||||
let player = guard_for(Some(&id), "one").unwrap_err();
|
||||
let player = guard_for(Some(&id), "player").unwrap_err();
|
||||
assert!(player.contains("probe4") && player.contains("kicks"));
|
||||
// The override hint belongs to the caller that can act on it, not to the reason.
|
||||
assert!(!player.contains("WOW_ALLOW_ACCOUNT"));
|
||||
assert!(guard_for(Some(&id), "probe7").is_err());
|
||||
// No declaration, no standing.
|
||||
assert!(guard_for(None, "one").is_ok());
|
||||
assert!(guard_for(None, "player").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//! --reload-templates make the server re-read the premade tables before dressing
|
||||
//! --host <h> default `localhost`
|
||||
//!
|
||||
//! … -- one pone One --wipe --level 60 --tier phase6-bis --home --spread a
|
||||
//! … -- <account> <password> <Character> --wipe --level 60 --tier phase6-bis --home --spread a
|
||||
//! ```
|
||||
//!
|
||||
//! Without `--wipe` it skips classes the account already has. Creating needs no GM level;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! whenever a value has one; cmangos does the same (`Sha1Hash::UpdateBigNumbers`).
|
||||
//!
|
||||
//! ```text
|
||||
//! cargo run --release -p benilla-protocol --example srp_encoding_probe -- --user one --pass pone
|
||||
//! cargo run --release -p benilla-protocol --example srp_encoding_probe -- --user U --pass P
|
||||
//! ```
|
||||
//!
|
||||
//! `--stress N` runs N ordinary fixed-width handshakes and reports the failure rate, waiting out
|
||||
@@ -342,8 +342,8 @@ fn matrix(host: &str, user: &str, pass: &str, enc: Enc, title: &str) {
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut host = "localhost".to_string();
|
||||
let mut user = "one".to_string();
|
||||
let mut pass = "pone".to_string();
|
||||
let mut user = String::new();
|
||||
let mut pass = String::new();
|
||||
let mut stress = 0u32;
|
||||
let mut logons = 0u32;
|
||||
let mut args = std::env::args().skip(1);
|
||||
@@ -357,6 +357,9 @@ fn main() -> Result<()> {
|
||||
other => return Err(anyhow!("unknown argument {other}")),
|
||||
}
|
||||
}
|
||||
if user.is_empty() || pass.is_empty() {
|
||||
return Err(anyhow!("--user and --pass are required"));
|
||||
}
|
||||
|
||||
// `--logon N` runs the shipped `logon` N times; every handshake must succeed, or its
|
||||
// ephemeral guarantee is not holding.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! `benilla-auth`: SRP6 logon against a vanilla realmd, printing the realm list.
|
||||
//!
|
||||
//! Example: `cargo run --bin benilla-auth -- one pone localhost`
|
||||
//! Example: `cargo run --bin benilla-auth -- <account> <password> localhost`
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! `benilla-world`: logs in to realmd, enters the world server as a character, and tallies the
|
||||
//! updates it pushes; the `--<probe>` flags live-verify one wire each.
|
||||
//!
|
||||
//! Example: `cargo run -p benilla-protocol --bin benilla-world -- one pone localhost`
|
||||
//! Example: `cargo run -p benilla-protocol --bin benilla-world -- <account> <password> localhost`
|
||||
//!
|
||||
//! An account with no character gets a Human Warrior (`--create <name>`). The world address
|
||||
//! defaults to the realm list's (`--world` overrides).
|
||||
|
||||
Reference in New Issue
Block a user