Some checks failed
Native code generation / deterministic (push) Failing after 2m12s
Imaging and meshing gate / native (push) Failing after 5m40s
JPEG 2000 feature / linux (push) Successful in 2m50s
Native Rust workspace compile / compile (push) Failing after 56s
Skia feature / linux (push) Successful in 31m24s
219 lines
8.1 KiB
Rust
219 lines
8.1 KiB
Rust
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
use std::process::{Command, Output, Stdio};
|
|
use std::sync::atomic::{AtomicU64, Ordering};
|
|
|
|
const CLIENT: &str = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
|
|
const AVATAR: &str = "11111111-2222-3333-4444-555555555555";
|
|
const BOT: &str = "22222222-3333-4444-5555-666666666666";
|
|
const GROUP: &str = "33333333-4444-5555-6666-777777777777";
|
|
const MEMBER: &str = "44444444-5555-6666-7777-888888888888";
|
|
const ROLE: &str = "55555555-6666-7777-8888-999999999999";
|
|
const CLASSIFIED: &str = "66666666-7777-8888-9999-aaaaaaaaaaaa";
|
|
const LAND: &str = "77777777-8888-9999-aaaa-bbbbbbbbbbbb";
|
|
const SIM: &str = "88888888-9999-aaaa-bbbb-cccccccccccc";
|
|
const OBJECT: &str = "99999999-aaaa-bbbb-cccc-dddddddddddd";
|
|
const DANCE1: &str = "b68a3d7c-de9e-fc87-eec8-543d787e5b0d";
|
|
|
|
static TEMP_ID: AtomicU64 = AtomicU64::new(0);
|
|
|
|
struct TestDir(PathBuf);
|
|
impl TestDir {
|
|
fn new() -> Self {
|
|
let id = TEMP_ID.fetch_add(1, Ordering::Relaxed);
|
|
let path = std::env::temp_dir().join(format!(
|
|
"metacrate-test-client-services-{}-{id}",
|
|
std::process::id()
|
|
));
|
|
fs::create_dir(&path).expect("create test directory");
|
|
Self(path)
|
|
}
|
|
fn write(&self, contents: &str) -> PathBuf {
|
|
let path = self.0.join("session.tsv");
|
|
fs::write(&path, contents).expect("write script");
|
|
path
|
|
}
|
|
}
|
|
impl Drop for TestDir {
|
|
fn drop(&mut self) {
|
|
let _ = fs::remove_dir_all(&self.0);
|
|
}
|
|
}
|
|
fn path_text(path: &Path) -> &str {
|
|
path.to_str().expect("UTF-8 test path")
|
|
}
|
|
fn run(args: &[&str]) -> Output {
|
|
Command::new(env!("CARGO_BIN_EXE_test-client"))
|
|
.args(args)
|
|
.stdin(Stdio::null())
|
|
.stdout(Stdio::piped())
|
|
.stderr(Stdio::piped())
|
|
.output()
|
|
.expect("run test-client")
|
|
}
|
|
|
|
#[test]
|
|
#[allow(clippy::too_many_lines)]
|
|
fn full_offline_session_exercises_every_remaining_service_and_voice_command() {
|
|
let directory = TestDir::new();
|
|
let script = directory.write(&format!(
|
|
"!client\t{CLIENT}\tAlice\tBot\n\
|
|
!service-avatar\t{CLIENT}\t{AVATAR}\tActive Resident\tBuilders\t128\t129\t25\t10\ttrue\n\
|
|
!service-avatar\t{CLIENT}\t{BOT}\tQuiet Bot\tNone\t130\t131\t25\t11\tfalse\n\
|
|
!service-friend\t{CLIENT}\t{AVATAR}\tActive Resident\ttrue\t4294967298000\t128\t129\t25\n\
|
|
!service-group\t{CLIENT}\t{GROUP}\tBuilders Guild\n\
|
|
!service-group-result\t{CLIENT}\t{GROUP}\tBuilders Guild\t42\n\
|
|
!service-group-member\t{CLIENT}\t{GROUP}\t{MEMBER}\n\
|
|
!service-group-role\t{CLIENT}\t{GROUP}\t{ROLE}\tOfficer\tArchitect\n\
|
|
!service-person\t{CLIENT}\t{AVATAR}\tActive\tResident\ttrue\n\
|
|
!service-classified\t{CLIENT}\t{CLASSIFIED}\tBuilder Services\t25\n\
|
|
!service-event\t{CLIENT}\t7\tBuilding Class\tToday\n\
|
|
!service-event-info\t{CLIENT}\t7\tBuilding Class\tTest Region\t1000\t2000\t25\n\
|
|
!service-land\t{CLIENT}\t{LAND}\tBuilder Parcel\t1024\t500\n\
|
|
!service-place\t{CLIENT}\tBuilder Plaza\tTest Region\t128\t128\t25\n\
|
|
!service-sim\t{CLIENT}\tTest Region\t{SIM}\t4294967298000\t0.98\n\
|
|
!service-utilization\t{CLIENT}\ttrue\n\
|
|
!service-utilization-row\t{CLIENT}\tpacket\tAgentUpdate\t2\t3\t2048\t4096\n\
|
|
!service-utilization-row\t{CLIENT}\tcapability\tEventQueueGet\t1\t4\t512\t8192\n\
|
|
who\n\
|
|
bots\n\
|
|
friends\n\
|
|
mapfriend {AVATAR}\n\
|
|
key2name {AVATAR}\n\
|
|
key2name {GROUP}\n\
|
|
searchclassifieds Builder\n\
|
|
searchevents Building\n\
|
|
searchgroups Builders\n\
|
|
searchland mainland 1000 512\n\
|
|
searchpeople Active\n\
|
|
searchplaces Builder\n\
|
|
showevent 7\n\
|
|
groups\n\
|
|
groupmembers Builders Guild\n\
|
|
grouproles Builders Guild\n\
|
|
play list\n\
|
|
play show\n\
|
|
dilation\n\
|
|
netstats\n\
|
|
regioninfo\n\
|
|
stats\n\
|
|
uptime\n\
|
|
cloneprofile {AVATAR} --confirm\n\
|
|
sendgeneric test-method alpha beta --confirm\n\
|
|
play DANCE1 --confirm\n\
|
|
touch {OBJECT} --confirm\n\
|
|
activategroup Builders Guild --confirm\n\
|
|
invitegroup {AVATAR} {GROUP} {ROLE} --confirm\n\
|
|
joingroup Builders Guild --confirm\n\
|
|
leavegroup Builders Guild --confirm\n\
|
|
voiceparcel\n\
|
|
voiceaccount\n\
|
|
quit\n"
|
|
));
|
|
let output = run(&[
|
|
"--allow-live-mutations",
|
|
"--allow-spending",
|
|
"--fake-script",
|
|
path_text(&script),
|
|
]);
|
|
let stdout = String::from_utf8(output.stdout).expect("UTF-8 stdout");
|
|
let stderr = String::from_utf8(output.stderr).expect("UTF-8 stderr");
|
|
assert!(
|
|
output.status.success(),
|
|
"stdout:\n{stdout}\nstderr:\n{stderr}"
|
|
);
|
|
assert!(stderr.is_empty(), "{stderr}");
|
|
for expected in [
|
|
"Active Resident (Group: Builders",
|
|
"Quiet Bot (Group: None",
|
|
"Is Probably a bot",
|
|
"has 1 friends:",
|
|
"Found Friend 11111111-2222-3333-4444-555555555555",
|
|
"Avatar: Active Resident",
|
|
"Group: Builders Guild",
|
|
"returned 1 classified ads",
|
|
"matched 1 Events",
|
|
"matched 1 Groups",
|
|
"1 results",
|
|
"matched 1 People",
|
|
"returned 1 results",
|
|
"<redacted-url> Region/232/208/0",
|
|
"got 1 groups",
|
|
"MemberCount 1",
|
|
"RoleCount 1",
|
|
"AFRAID",
|
|
DANCE1,
|
|
"Dilation is 0.98",
|
|
"Capabilities Totals",
|
|
"Packet Totals",
|
|
"UUID: 88888888-9999-aaaa-bbbb-cccccccccccc",
|
|
"Packets in the queue:",
|
|
"I am Alice Bot, Up Since:",
|
|
"Synchronized our profile",
|
|
"Sent generic message with method test-method",
|
|
"Touched object",
|
|
"Active group is now Builders Guild",
|
|
"invited",
|
|
"Joined the group Builders Guild",
|
|
"has left the group Builders Guild",
|
|
"Parcel voice info: region-name-present=true, parcel-local-id=42, channel=<redacted>",
|
|
"Voice account provisioned: credentials=<redacted>",
|
|
"CALL profile-clone",
|
|
"CALL generic-message",
|
|
"CALL animation-start",
|
|
"CALL object-touch",
|
|
"CALL group-activate",
|
|
"CALL group-invite",
|
|
"CALL group-join",
|
|
"CALL group-leave",
|
|
"CALL voice-parcel-info",
|
|
"CALL voice-provision-account credentials=<redacted>",
|
|
] {
|
|
assert!(stdout.contains(expected), "missing {expected:?}:\n{stdout}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn social_mutations_require_startup_and_per_command_confirmation() {
|
|
let directory = TestDir::new();
|
|
let script = directory.write(&format!(
|
|
"!client\t{CLIENT}\tAlice\tBot\nplay {DANCE1} --confirm\nquit\n"
|
|
));
|
|
let output = run(&["--fake-script", path_text(&script)]);
|
|
let stdout = String::from_utf8(output.stdout).expect("UTF-8 stdout");
|
|
assert!(output.status.success());
|
|
assert!(stdout.contains("Live mutations are disabled"), "{stdout}");
|
|
assert!(!stdout.contains("CALL animation-start"), "{stdout}");
|
|
|
|
let script = directory.write(&format!(
|
|
"!client\t{CLIENT}\tAlice\tBot\ntouch {OBJECT}\nquit\n"
|
|
));
|
|
let output = run(&[
|
|
"--allow-live-mutations",
|
|
"--fake-script",
|
|
path_text(&script),
|
|
]);
|
|
let stdout = String::from_utf8(output.stdout).expect("UTF-8 stdout");
|
|
assert!(output.status.success());
|
|
assert!(stdout.contains("append --confirm"), "{stdout}");
|
|
assert!(!stdout.contains("CALL object-touch"), "{stdout}");
|
|
|
|
let script = directory.write(&format!(
|
|
"!client\t{CLIENT}\tAlice\tBot\njoingroup uuid {GROUP} --confirm\nquit\n"
|
|
));
|
|
let output = run(&[
|
|
"--allow-live-mutations",
|
|
"--fake-script",
|
|
path_text(&script),
|
|
]);
|
|
let stdout = String::from_utf8(output.stdout).expect("UTF-8 stdout");
|
|
assert!(output.status.success());
|
|
assert!(stdout.contains("restart with --allow-spending"), "{stdout}");
|
|
assert!(!stdout.contains("CALL group-join"), "{stdout}");
|
|
}
|
|
|
|
#[test]
|
|
fn command_inventory_has_no_pending_source_commands() {
|
|
assert!(libremetaverse_programs::test_client::pending_test_client_commands().is_empty());
|
|
}
|