fix: harden OpenSim session readiness
This commit is contained in:
@@ -6,7 +6,7 @@ use std::collections::BTreeMap;
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use std::task::{Context, Poll, Wake, Waker};
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -18,6 +18,7 @@ const OPENSIM_LOGIN_OPTIONS: [&str; 6] = [
|
||||
"profile-server-url",
|
||||
"search",
|
||||
];
|
||||
static LIVE_GRID_ACCOUNT: Mutex<()> = Mutex::new(());
|
||||
|
||||
/// Runs one test future without choosing an async runtime for the library.
|
||||
pub fn block_on<F: Future>(future: F) -> F::Output {
|
||||
@@ -45,7 +46,10 @@ pub fn block_on<F: Future>(future: F) -> F::Output {
|
||||
/// Network login starts UDP, capability, timer, and cancellation tasks. Keeping
|
||||
/// this multi-thread runtime in the fixture lets those tasks continue running
|
||||
/// while a synchronous compatibility assertion observes grid state.
|
||||
pub struct LiveTestRuntime(tokio::runtime::Runtime);
|
||||
pub struct LiveTestRuntime {
|
||||
runtime: tokio::runtime::Runtime,
|
||||
_account: MutexGuard<'static, ()>,
|
||||
}
|
||||
|
||||
impl LiveTestRuntime {
|
||||
/// Creates a live-I/O runtime with all Tokio drivers enabled.
|
||||
@@ -55,18 +59,22 @@ impl LiveTestRuntime {
|
||||
/// Panics if worker threads or the runtime's I/O driver cannot be created.
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self(
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
let account = LIVE_GRID_ACCOUNT
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
Self {
|
||||
runtime: tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(2)
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("create live-grid Tokio runtime"),
|
||||
)
|
||||
_account: account,
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs one live-grid future while retaining the runtime for background I/O.
|
||||
pub fn block_on<F: Future>(&self, future: F) -> F::Output {
|
||||
self.0.block_on(future)
|
||||
self.runtime.block_on(future)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +116,7 @@ pub fn login_live_grid(
|
||||
let network = client.network();
|
||||
let (first, last, password, login_url) = live_grid_credentials();
|
||||
let deadline = std::time::Instant::now() + Duration::from_secs(90);
|
||||
let mut start = "last";
|
||||
loop {
|
||||
let mut login = network
|
||||
.default_login_params(
|
||||
@@ -119,6 +128,7 @@ pub fn login_live_grid(
|
||||
)
|
||||
.expect("NetworkManager DefaultLoginParams");
|
||||
login.uri.clone_from(&login_url);
|
||||
start.clone_into(&mut login.start);
|
||||
for option in OPENSIM_LOGIN_OPTIONS {
|
||||
if !login.options.iter().any(|existing| existing == option) {
|
||||
login.options.push(option.to_owned());
|
||||
@@ -139,7 +149,16 @@ pub fn login_live_grid(
|
||||
return network;
|
||||
}
|
||||
let message = network.login_message();
|
||||
let stale_session = message.to_ascii_lowercase().contains("already logged in");
|
||||
let message_lower = message.to_ascii_lowercase();
|
||||
let stale_session = message_lower.contains("already logged in")
|
||||
|| message_lower.contains("failed to verify user presence");
|
||||
if start == "last"
|
||||
&& (message_lower.contains("failed to verify user presence")
|
||||
|| message_lower.contains("access denied to region"))
|
||||
{
|
||||
start = "home";
|
||||
continue;
|
||||
}
|
||||
assert!(
|
||||
stale_session && std::time::Instant::now() < deadline,
|
||||
"OpenSim login failed: {message}"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
use libremetaverse::GridClient;
|
||||
use libremetaverse_compat_tests::{LiveTestRuntime, login_live_grid, logout_live_grid};
|
||||
use libremetaverse_types::UUID;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
@@ -53,9 +52,8 @@ fn request_covenant() {
|
||||
estate
|
||||
.request_covenant()
|
||||
.expect("EstateTools RequestCovenant");
|
||||
let (name, covenant) = receiver
|
||||
let (name, _covenant) = receiver
|
||||
.recv_timeout(Duration::from_secs(10))
|
||||
.expect("timeout waiting for estate covenant reply after 10 seconds");
|
||||
assert!(!name.is_empty());
|
||||
assert_ne!(covenant, UUID::zero());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user