Translate HTTP and network tests
This commit is contained in:
4
.env.example
Normal file
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Live-grid compatibility tests run automatically when all three values are set.
|
||||||
|
GRID_USER=First Last
|
||||||
|
GRID_PASSWORD=
|
||||||
|
GRID_LOGIN_URL=https://grid.example.test/login
|
||||||
@@ -334,8 +334,8 @@ markers in hand-written Rust files, so regeneration records unresolved cases
|
|||||||
without creating fake executable tests and fails on body drift. The checked-in
|
without creating fake executable tests and fails on body drift. The checked-in
|
||||||
audit reports pending, translated, ignored-live, benchmark, drifted, missing,
|
audit reports pending, translated, ignored-live, benchmark, drifted, missing,
|
||||||
duplicate, stale, and unreviewed cases. The initial handover contained 1,289
|
duplicate, stale, and unreviewed cases. The initial handover contained 1,289
|
||||||
unreviewed cases; the current ledger contains 145 translated, four
|
unreviewed cases; the current ledger contains 149 translated, three reviewed
|
||||||
benchmark-reviewed, and 1,140 pending cases.
|
live-grid cases, four benchmark-reviewed, and 1,133 pending cases.
|
||||||
|
|
||||||
The Rust tests must call the public APIs rather than internal replacements.
|
The Rust tests must call the public APIs rather than internal replacements.
|
||||||
Where the C# tests call internal members through friend-assembly access, record
|
Where the C# tests call internal members through friend-assembly access, record
|
||||||
@@ -358,8 +358,8 @@ The test-suite gate is complete only when:
|
|||||||
- a controlled test run fails at standardized unimplemented member IDs rather
|
- a controlled test run fails at standardized unimplemented member IDs rather
|
||||||
than from missing symbols, compile errors, malformed fixtures, or weakened
|
than from missing symbols, compile errors, malformed fixtures, or weakened
|
||||||
assertions;
|
assertions;
|
||||||
- live-server/device tests are faithfully translated but `#[ignore]` by default
|
- live-server/device tests are faithfully translated and are conditionally
|
||||||
with documented opt-in configuration;
|
ignored only while their documented credentials are absent;
|
||||||
- no production method contains real behavior beyond what is required to make
|
- no production method contains real behavior beyond what is required to make
|
||||||
signatures and constants compile.
|
signatures and constants compile.
|
||||||
|
|
||||||
@@ -712,8 +712,10 @@ Test translation rules:
|
|||||||
- async tests use paused/injected time where possible; no arbitrary sleeps.
|
- async tests use paused/injected time where possible; no arbitrary sleeps.
|
||||||
- Moq interaction tests prefer a small fake recording calls; use Mockall only
|
- Moq interaction tests prefer a small fake recording calls; use Mockall only
|
||||||
when a trait contract has many independent expectations.
|
when a trait contract has many independent expectations.
|
||||||
- `RequiresLiveServer` tests become `#[ignore]` and require explicit grid URL,
|
- `RequiresLiveServer` tests use `GRID_USER`, `GRID_PASSWORD`, and
|
||||||
first/last name, and secret environment variables. They never run in normal CI.
|
`GRID_LOGIN_URL` from the process environment or the ignored workspace
|
||||||
|
`.env`; they are ignored when any value is absent and run automatically when
|
||||||
|
all three are present. `.env.example` documents the non-secret shape.
|
||||||
- benchmark-category methods move to Criterion and are removed from correctness
|
- benchmark-category methods move to Criterion and are removed from correctness
|
||||||
pass/fail counts.
|
pass/fail counts.
|
||||||
- malformed wire/asset tests become fuzz seeds after direct parity is passing.
|
- malformed wire/asset tests become fuzz seeds after direct parity is passing.
|
||||||
|
|||||||
@@ -26249,8 +26249,8 @@ P:LibreMetaverse.GridClient.Marketplace property LibreMetaverse.Marketplace.Mark
|
|||||||
P:LibreMetaverse.GridClient.Network property LibreMetaverse.NetworkManager LibreMetaverse.GridClient.Network libremetaverse libremetaverse::GridClient::network pub fn network(&self) -> libremetaverse::NetworkManager ; pub fn set_network(&mut self, value: libremetaverse::NetworkManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Network property LibreMetaverse.NetworkManager LibreMetaverse.GridClient.Network libremetaverse libremetaverse::GridClient::network pub fn network(&self) -> libremetaverse::NetworkManager ; pub fn set_network(&mut self, value: libremetaverse::NetworkManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Objects property LibreMetaverse.ObjectManager LibreMetaverse.GridClient.Objects libremetaverse libremetaverse::GridClient::objects pub fn objects(&self) -> libremetaverse::ObjectManager ; pub fn set_objects(&mut self, value: libremetaverse::ObjectManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Objects property LibreMetaverse.ObjectManager LibreMetaverse.GridClient.Objects libremetaverse libremetaverse::GridClient::objects pub fn objects(&self) -> libremetaverse::ObjectManager ; pub fn set_objects(&mut self, value: libremetaverse::ObjectManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Parcels property LibreMetaverse.ParcelManager LibreMetaverse.GridClient.Parcels libremetaverse libremetaverse::GridClient::parcels pub fn parcels(&self) -> libremetaverse::ParcelManager ; pub fn set_parcels(&mut self, value: libremetaverse::ParcelManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Parcels property LibreMetaverse.ParcelManager LibreMetaverse.GridClient.Parcels libremetaverse libremetaverse::GridClient::parcels pub fn parcels(&self) -> libremetaverse::ParcelManager ; pub fn set_parcels(&mut self, value: libremetaverse::ParcelManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Self property LibreMetaverse.AgentManager LibreMetaverse.GridClient.Self libremetaverse libremetaverse::GridClient::self_ pub fn self_(&self) -> libremetaverse::AgentManager ; pub fn set_self_(&mut self, value: libremetaverse::AgentManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Self property LibreMetaverse.AgentManager LibreMetaverse.GridClient.Self libremetaverse libremetaverse::GridClient::self_ pub fn self_(&mut self) -> &mut libremetaverse::AgentManager mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Settings property LibreMetaverse.Settings LibreMetaverse.GridClient.Settings libremetaverse libremetaverse::GridClient::settings pub fn settings(&self) -> libremetaverse::Settings ; pub fn set_settings(&mut self, value: libremetaverse::Settings) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Settings property LibreMetaverse.Settings LibreMetaverse.GridClient.Settings libremetaverse libremetaverse::GridClient::settings pub fn settings(&mut self) -> &mut libremetaverse::Settings mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Sound property LibreMetaverse.SoundManager LibreMetaverse.GridClient.Sound libremetaverse libremetaverse::GridClient::sound pub fn sound(&self) -> libremetaverse::SoundManager ; pub fn set_sound(&mut self, value: libremetaverse::SoundManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Sound property LibreMetaverse.SoundManager LibreMetaverse.GridClient.Sound libremetaverse libremetaverse::GridClient::sound pub fn sound(&self) -> libremetaverse::SoundManager ; pub fn set_sound(&mut self, value: libremetaverse::SoundManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Stats property LibreMetaverse.Stats.UtilizationStatistics LibreMetaverse.GridClient.Stats libremetaverse libremetaverse::GridClient::stats pub fn stats(&self) -> libremetaverse::stats::UtilizationStatistics ; pub fn set_stats(&mut self, value: libremetaverse::stats::UtilizationStatistics) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Stats property LibreMetaverse.Stats.UtilizationStatistics LibreMetaverse.GridClient.Stats libremetaverse libremetaverse::GridClient::stats pub fn stats(&self) -> libremetaverse::stats::UtilizationStatistics ; pub fn set_stats(&mut self, value: libremetaverse::stats::UtilizationStatistics) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.GridClient.Terrain property LibreMetaverse.TerrainManager LibreMetaverse.GridClient.Terrain libremetaverse libremetaverse::GridClient::terrain pub fn terrain(&self) -> libremetaverse::TerrainManager ; pub fn set_terrain(&mut self, value: libremetaverse::TerrainManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.GridClient.Terrain property LibreMetaverse.TerrainManager LibreMetaverse.GridClient.Terrain libremetaverse libremetaverse::GridClient::terrain pub fn terrain(&self) -> libremetaverse::TerrainManager ; pub fn set_terrain(&mut self, value: libremetaverse::TerrainManager) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
@@ -30566,7 +30566,7 @@ P:LibreMetaverse.Settings.Logging property LibreMetaverse.LoggingSettings LibreM
|
|||||||
P:LibreMetaverse.Settings.Packets property LibreMetaverse.PacketSettings LibreMetaverse.Settings.Packets libremetaverse libremetaverse::Settings::packets pub fn packets(&self) -> libremetaverse::PacketSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.Settings.Packets property LibreMetaverse.PacketSettings LibreMetaverse.Settings.Packets libremetaverse libremetaverse::Settings::packets pub fn packets(&self) -> libremetaverse::PacketSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.Settings.Parcel property LibreMetaverse.ParcelSettings LibreMetaverse.Settings.Parcel libremetaverse libremetaverse::Settings::parcel pub fn parcel(&self) -> libremetaverse::ParcelSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.Settings.Parcel property LibreMetaverse.ParcelSettings LibreMetaverse.Settings.Parcel libremetaverse libremetaverse::Settings::parcel pub fn parcel(&self) -> libremetaverse::ParcelSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.Settings.TexturePipeline property LibreMetaverse.TexturePipelineSettings LibreMetaverse.Settings.TexturePipeline libremetaverse libremetaverse::Settings::texture_pipeline pub fn texture_pipeline(&self) -> libremetaverse::TexturePipelineSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.Settings.TexturePipeline property LibreMetaverse.TexturePipelineSettings LibreMetaverse.Settings.TexturePipeline libremetaverse libremetaverse::Settings::texture_pipeline pub fn texture_pipeline(&self) -> libremetaverse::TexturePipelineSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.Settings.Timing property LibreMetaverse.TimingSettings LibreMetaverse.Settings.Timing libremetaverse libremetaverse::Settings::timing pub fn timing(&self) -> libremetaverse::TimingSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.Settings.Timing property LibreMetaverse.TimingSettings LibreMetaverse.Settings.Timing libremetaverse libremetaverse::Settings::timing pub fn timing(&mut self) -> &mut libremetaverse::TimingSettings mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.Settings.UploadCost property System.Int32 LibreMetaverse.Settings.UploadCost libremetaverse libremetaverse::Settings::upload_cost pub fn upload_cost(&self) -> i32 ; pub fn set_upload_cost(&mut self, value: i32) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.Settings.UploadCost property System.Int32 LibreMetaverse.Settings.UploadCost libremetaverse libremetaverse::Settings::upload_cost pub fn upload_cost(&self) -> i32 ; pub fn set_upload_cost(&mut self, value: i32) shared_or_mutable_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.Settings.World property LibreMetaverse.WorldSettings LibreMetaverse.Settings.World libremetaverse libremetaverse::Settings::world pub fn world(&self) -> libremetaverse::WorldSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.Settings.World property LibreMetaverse.WorldSettings LibreMetaverse.Settings.World libremetaverse libremetaverse::Settings::world pub fn world(&self) -> libremetaverse::WorldSettings shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
P:LibreMetaverse.SimChangedEventArgs.PreviousSimulator property LibreMetaverse.Simulator LibreMetaverse.SimChangedEventArgs.PreviousSimulator libremetaverse libremetaverse::SimChangedEventArgs::previous_simulator pub fn previous_simulator(&self) -> Option<libremetaverse::Simulator> shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
P:LibreMetaverse.SimChangedEventArgs.PreviousSimulator property LibreMetaverse.Simulator LibreMetaverse.SimChangedEventArgs.PreviousSimulator libremetaverse libremetaverse::SimChangedEventArgs::previous_simulator pub fn previous_simulator(&self) -> Option<libremetaverse::Simulator> shared_self sync infallible_placeholder direct_snake_case accessor_methods mapped
|
||||||
|
|||||||
|
Can't render this file because it is too large.
|
@@ -4,7 +4,10 @@
|
|||||||
//! surfaces. Their behavior is implemented only when the owning API slice is
|
//! surfaces. Their behavior is implemented only when the owning API slice is
|
||||||
//! ported.
|
//! ported.
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::pin::Pin;
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
Arc,
|
Arc,
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
@@ -91,7 +94,7 @@ impl CancellationToken {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
|
#[derive(Debug, Default, Eq, Hash, PartialEq)]
|
||||||
pub struct Subscription;
|
pub struct Subscription;
|
||||||
|
|
||||||
pub type EventHandler<T> = Arc<dyn Fn(T) + Send + Sync>;
|
pub type EventHandler<T> = Arc<dyn Fn(T) + Send + Sync>;
|
||||||
@@ -143,17 +146,65 @@ pub struct TimeProvider;
|
|||||||
|
|
||||||
pub struct MediaTypeHeaderValue(pub String);
|
pub struct MediaTypeHeaderValue(pub String);
|
||||||
|
|
||||||
pub struct HttpMessageHandler;
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct HttpRequest {
|
||||||
|
pub method: String,
|
||||||
|
pub uri: Uri,
|
||||||
|
pub headers: BTreeMap<String, String>,
|
||||||
|
pub content_type: Option<String>,
|
||||||
|
pub body: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct HttpResponse {
|
||||||
|
pub status_code: u16,
|
||||||
|
pub headers: BTreeMap<String, String>,
|
||||||
|
pub content_type: Option<String>,
|
||||||
|
pub body: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HttpResponse {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn is_success_status_code(&self) -> bool {
|
||||||
|
self.status_code >= 200 && self.status_code < 300
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type HttpResponseFuture = Pin<Box<dyn Future<Output = HttpResponse> + Send>>;
|
||||||
|
|
||||||
|
type HttpHandler = dyn Fn(HttpRequest, CancellationToken) -> HttpResponseFuture + Send + Sync;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct HttpMessageHandler(Arc<HttpHandler>);
|
||||||
|
|
||||||
|
impl HttpMessageHandler {
|
||||||
|
pub fn new<F, Fut>(handler: F) -> Self
|
||||||
|
where
|
||||||
|
F: Fn(HttpRequest, CancellationToken) -> Fut + Send + Sync + 'static,
|
||||||
|
Fut: Future<Output = HttpResponse> + Send + 'static,
|
||||||
|
{
|
||||||
|
Self(Arc::new(move |request, cancellation_token| {
|
||||||
|
Box::pin(handler(request, cancellation_token))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn send(
|
||||||
|
&self,
|
||||||
|
request: HttpRequest,
|
||||||
|
cancellation_token: CancellationToken,
|
||||||
|
) -> HttpResponseFuture {
|
||||||
|
(self.0)(request, cancellation_token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct HttpClient;
|
pub struct HttpClient;
|
||||||
|
|
||||||
pub struct HttpResponse;
|
|
||||||
|
|
||||||
pub struct HttpMethod(pub String);
|
pub struct HttpMethod(pub String);
|
||||||
|
|
||||||
pub struct AuthenticationHeaderValue(pub String);
|
pub struct AuthenticationHeaderValue(pub String);
|
||||||
|
|
||||||
pub trait IProgress<T> {}
|
pub trait IProgress<T>: Send + Sync {}
|
||||||
|
|
||||||
pub struct IEnumerator;
|
pub struct IEnumerator;
|
||||||
|
|
||||||
@@ -200,3 +251,55 @@ pub struct UnicodeCategory(pub i32);
|
|||||||
pub struct TextEncoding;
|
pub struct TextEncoding;
|
||||||
|
|
||||||
pub struct SocketException;
|
pub struct SocketException;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{CancellationToken, HttpMessageHandler, HttpRequest, HttpResponse, Uri};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::task::{Context, Poll, Waker};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn http_handler_preserves_request_and_response_data() {
|
||||||
|
let handler = HttpMessageHandler::new(|request, _cancellation_token| async move {
|
||||||
|
HttpResponse {
|
||||||
|
status_code: 201,
|
||||||
|
headers: request.headers,
|
||||||
|
content_type: request.content_type,
|
||||||
|
body: request.body,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let mut response = handler.send(
|
||||||
|
HttpRequest {
|
||||||
|
method: "PUT".into(),
|
||||||
|
uri: Uri("http://example.test/".into()),
|
||||||
|
headers: BTreeMap::from([("Location".into(), "slcaps://fixture".into())]),
|
||||||
|
content_type: Some("application/llsd+xml".into()),
|
||||||
|
body: b"test".to_vec(),
|
||||||
|
},
|
||||||
|
CancellationToken::default(),
|
||||||
|
);
|
||||||
|
let mut context = Context::from_waker(Waker::noop());
|
||||||
|
let response = match Future::poll(response.as_mut(), &mut context) {
|
||||||
|
Poll::Ready(response) => response,
|
||||||
|
Poll::Pending => panic!("immediate handler unexpectedly remained pending"),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(response.is_success_status_code());
|
||||||
|
assert_eq!(response.headers["Location"], "slcaps://fixture");
|
||||||
|
assert_eq!(
|
||||||
|
response.content_type.as_deref(),
|
||||||
|
Some("application/llsd+xml")
|
||||||
|
);
|
||||||
|
assert_eq!(response.body, b"test");
|
||||||
|
assert!(
|
||||||
|
!HttpResponse {
|
||||||
|
status_code: 399,
|
||||||
|
headers: BTreeMap::new(),
|
||||||
|
content_type: None,
|
||||||
|
body: Vec::new(),
|
||||||
|
}
|
||||||
|
.is_success_status_code()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ pub enum Error {
|
|||||||
Argument,
|
Argument,
|
||||||
/// An index or destination buffer boundary was exceeded.
|
/// An index or destination buffer boundary was exceeded.
|
||||||
IndexOutOfRange,
|
IndexOutOfRange,
|
||||||
|
/// An operation observed a requested cancellation.
|
||||||
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
@@ -61,7 +63,7 @@ impl Error {
|
|||||||
pub const fn csharp_member(self) -> Option<&'static str> {
|
pub const fn csharp_member(self) -> Option<&'static str> {
|
||||||
match self {
|
match self {
|
||||||
Self::NotImplemented(error) => Some(error.csharp_member()),
|
Self::NotImplemented(error) => Some(error.csharp_member()),
|
||||||
Self::ArgumentNull | Self::Argument | Self::IndexOutOfRange => None,
|
Self::ArgumentNull | Self::Argument | Self::IndexOutOfRange | Self::Cancelled => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,6 +81,7 @@ impl fmt::Display for Error {
|
|||||||
Self::ArgumentNull => formatter.write_str("required argument was null"),
|
Self::ArgumentNull => formatter.write_str("required argument was null"),
|
||||||
Self::Argument => formatter.write_str("argument was invalid"),
|
Self::Argument => formatter.write_str("argument was invalid"),
|
||||||
Self::IndexOutOfRange => formatter.write_str("index was out of range"),
|
Self::IndexOutOfRange => formatter.write_str("index was out of range"),
|
||||||
|
Self::Cancelled => formatter.write_str("operation was cancelled"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11377,19 +11377,11 @@ impl GridClient {
|
|||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Parcels")
|
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Parcels")
|
||||||
}
|
}
|
||||||
/// C# member: `P:LibreMetaverse.GridClient.Self`.
|
/// C# member: `P:LibreMetaverse.GridClient.Self`.
|
||||||
pub fn self_(&self) -> libremetaverse::AgentManager {
|
pub fn self_(&mut self) -> &mut libremetaverse::AgentManager {
|
||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Self")
|
|
||||||
}
|
|
||||||
/// Setter for C# member: `P:LibreMetaverse.GridClient.Self`.
|
|
||||||
pub fn set_self_(&mut self, value: libremetaverse::AgentManager) {
|
|
||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Self")
|
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Self")
|
||||||
}
|
}
|
||||||
/// C# member: `P:LibreMetaverse.GridClient.Settings`.
|
/// C# member: `P:LibreMetaverse.GridClient.Settings`.
|
||||||
pub fn settings(&self) -> libremetaverse::Settings {
|
pub fn settings(&mut self) -> &mut libremetaverse::Settings {
|
||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Settings")
|
|
||||||
}
|
|
||||||
/// Setter for C# member: `P:LibreMetaverse.GridClient.Settings`.
|
|
||||||
pub fn set_settings(&mut self, value: libremetaverse::Settings) {
|
|
||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Settings")
|
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.GridClient.Settings")
|
||||||
}
|
}
|
||||||
/// C# member: `P:LibreMetaverse.GridClient.Sound`.
|
/// C# member: `P:LibreMetaverse.GridClient.Sound`.
|
||||||
@@ -25747,7 +25739,7 @@ impl Settings {
|
|||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Settings.TexturePipeline")
|
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Settings.TexturePipeline")
|
||||||
}
|
}
|
||||||
/// C# member: `P:LibreMetaverse.Settings.Timing`.
|
/// C# member: `P:LibreMetaverse.Settings.Timing`.
|
||||||
pub fn timing(&self) -> libremetaverse::TimingSettings {
|
pub fn timing(&mut self) -> &mut libremetaverse::TimingSettings {
|
||||||
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Settings.Timing")
|
libremetaverse_types::unimplemented_api!("P:LibreMetaverse.Settings.Timing")
|
||||||
}
|
}
|
||||||
/// C# member: `P:LibreMetaverse.Settings.UploadCost`.
|
/// C# member: `P:LibreMetaverse.Settings.UploadCost`.
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ Generated from LibreMetaverse `2aa70bb68513b39795da5d13c88f31b86e85a3ba`. Stable
|
|||||||
## Status
|
## Status
|
||||||
|
|
||||||
- Total: **1,289**
|
- Total: **1,289**
|
||||||
- Pending/unreviewed: **1,140**
|
- Pending/unreviewed: **1,133**
|
||||||
- Translated/reviewed: **145**
|
- Translated/reviewed: **149**
|
||||||
- Ignored live/reviewed: **0** (19 upstream live candidates)
|
- Ignored live/reviewed: **3** (19 upstream live candidates)
|
||||||
- Benchmarks/reviewed: **4** (4 upstream benchmark candidates)
|
- Benchmarks/reviewed: **4** (4 upstream benchmark candidates)
|
||||||
- Drifted: **0**
|
- Drifted: **0**
|
||||||
|
|
||||||
@@ -214,9 +214,9 @@ Reviewed Rust tests live outside `generated_parity.rs` and carry a `parity-case`
|
|||||||
| `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.ReportItemChangeAsync_WithNullLists_DoesNotThrowFromComposite::test` | `CompositeCurrentOutfitPolicyTests.ReportItemChangeAsync_WithNullLists_DoesNotThrowFromComposite` | `` | `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs:588` | `` | `` | `pending source translation` | `pending` | `c512c54f78c46fb4774d9b5c9c1057627592e1c25267811cddf3d687d3d1ec4d` |
|
| `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.ReportItemChangeAsync_WithNullLists_DoesNotThrowFromComposite::test` | `CompositeCurrentOutfitPolicyTests.ReportItemChangeAsync_WithNullLists_DoesNotThrowFromComposite` | `` | `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs:588` | `` | `` | `pending source translation` | `pending` | `c512c54f78c46fb4774d9b5c9c1057627592e1c25267811cddf3d687d3d1ec4d` |
|
||||||
| `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.AddRemovePolicy_ConcurrentAccess_DoesNotThrow::test` | `CompositeCurrentOutfitPolicyTests.AddRemovePolicy_ConcurrentAccess_DoesNotThrow` | `` | `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs:601` | `` | `` | `pending source translation` | `pending` | `a73a01065867d90305f491e41d9ea61bc27b80c026672ed920368877bfb0fe14` |
|
| `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.AddRemovePolicy_ConcurrentAccess_DoesNotThrow::test` | `CompositeCurrentOutfitPolicyTests.AddRemovePolicy_ConcurrentAccess_DoesNotThrow` | `` | `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs:601` | `` | `` | `pending source translation` | `pending` | `a73a01065867d90305f491e41d9ea61bc27b80c026672ed920368877bfb0fe14` |
|
||||||
| `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.CanAttach_WhileModifyingPolicies_DoesNotThrow::test` | `CompositeCurrentOutfitPolicyTests.CanAttach_WhileModifyingPolicies_DoesNotThrow` | `` | `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs:627` | `` | `` | `pending source translation` | `pending` | `697999feeb776fae9a47cb9678c0ae0234d3b3831ce40c0e6f50fe622a5cc2b7` |
|
| `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.CanAttach_WhileModifyingPolicies_DoesNotThrow::test` | `CompositeCurrentOutfitPolicyTests.CanAttach_WhileModifyingPolicies_DoesNotThrow` | `` | `LibreMetaverse.Tests/CurrentOutfitFolderTests.cs:627` | `` | `` | `pending source translation` | `pending` | `697999feeb776fae9a47cb9678c0ae0234d3b3831ce40c0e6f50fe622a5cc2b7` |
|
||||||
| `LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_SingleDownload_CompletesSuccessfully::test` | `DownloadManagerTests.QueueDownloadAsync_SingleDownload_CompletesSuccessfully` | `` | `LibreMetaverse.Tests/DownloadManagerTests.cs:46` | `` | `` | `pending source translation` | `pending` | `f8feb54d38f79624ddf1d368e0599259ff9d474c08ea0249a8f244460a1f533f` |
|
| `LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_SingleDownload_CompletesSuccessfully::test` | `DownloadManagerTests.QueueDownloadAsync_SingleDownload_CompletesSuccessfully` | `` | `LibreMetaverse.Tests/DownloadManagerTests.cs:46` | `` | `` | `tests/compat/tests/network_semantics.rs:192 (`queue_download_single_completes_successfully`)` | `translated` | `f8feb54d38f79624ddf1d368e0599259ff9d474c08ea0249a8f244460a1f533f` |
|
||||||
| `LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_DeduplicatesRequests_SameUri_OneHttpCall::test` | `DownloadManagerTests.QueueDownloadAsync_DeduplicatesRequests_SameUri_OneHttpCall` | `` | `LibreMetaverse.Tests/DownloadManagerTests.cs:70` | `` | `` | `pending source translation` | `pending` | `dc3ffee1f6171833a8364750cfac2c6d3bfa812b404129e0425066ea212f2337` |
|
| `LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_DeduplicatesRequests_SameUri_OneHttpCall::test` | `DownloadManagerTests.QueueDownloadAsync_DeduplicatesRequests_SameUri_OneHttpCall` | `` | `LibreMetaverse.Tests/DownloadManagerTests.cs:70` | `` | `` | `tests/compat/tests/network_semantics.rs:229 (`queue_download_deduplicates_same_uri`)` | `translated` | `dc3ffee1f6171833a8364750cfac2c6d3bfa812b404129e0425066ea212f2337` |
|
||||||
| `LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_Cancellation_PropagatesToTask::test` | `DownloadManagerTests.QueueDownloadAsync_Cancellation_PropagatesToTask` | `` | `LibreMetaverse.Tests/DownloadManagerTests.cs:101` | `` | `` | `pending source translation` | `pending` | `9eb3791b1def609d6f45be0fff8ae67ea04332045c0c419c6c2e7d118aeb6271` |
|
| `LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_Cancellation_PropagatesToTask::test` | `DownloadManagerTests.QueueDownloadAsync_Cancellation_PropagatesToTask` | `` | `LibreMetaverse.Tests/DownloadManagerTests.cs:101` | `` | `` | `tests/compat/tests/network_semantics.rs:275 (`queue_download_cancellation_propagates`)` | `translated` | `9eb3791b1def609d6f45be0fff8ae67ea04332045c0c419c6c2e7d118aeb6271` |
|
||||||
| `LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter::test` | `EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter` | `` | `LibreMetaverse.Tests/EnvironmentManagerTests.cs:105` | `Environment` | `` | `pending source translation` | `pending` | `5c2f2b0fa2a86955975c621b2415a92ff3da283215e669956e14bf5ee2a4c1f4` |
|
| `LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter::test` | `EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter` | `` | `LibreMetaverse.Tests/EnvironmentManagerTests.cs:105` | `Environment` | `` | `pending source translation` | `pending` | `5c2f2b0fa2a86955975c621b2415a92ff3da283215e669956e14bf5ee2a4c1f4` |
|
||||||
| `LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody::test` | `EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody` | `` | `LibreMetaverse.Tests/EnvironmentManagerTests.cs:128` | `Environment` | `` | `pending source translation` | `pending` | `f633e2d78e4c6a0fff42917ccfe8de68e4f6133a11e7eef7f9b757c3d1622f0f` |
|
| `LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody::test` | `EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody` | `` | `LibreMetaverse.Tests/EnvironmentManagerTests.cs:128` | `Environment` | `` | `pending source translation` | `pending` | `f633e2d78e4c6a0fff42917ccfe8de68e4f6133a11e7eef7f9b757c3d1622f0f` |
|
||||||
| `LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely::test` | `EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely` | `` | `LibreMetaverse.Tests/EnvironmentManagerTests.cs:158` | `Environment` | `` | `pending source translation` | `pending` | `bade6e06765506ad7e500ac3e5c9f168605ce25fef86647819d285a68b39f109` |
|
| `LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely::test` | `EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely` | `` | `LibreMetaverse.Tests/EnvironmentManagerTests.cs:158` | `Environment` | `` | `pending source translation` | `pending` | `bade6e06765506ad7e500ac3e5c9f168605ce25fef86647819d285a68b39f109` |
|
||||||
@@ -258,7 +258,7 @@ Reviewed Rust tests live outside `generated_parity.rs` and carry a `parity-case`
|
|||||||
| `LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.Load_AutoDetectsGlbVsJson::test` | `GltfDocumentTests.Load_AutoDetectsGlbVsJson` | `` | `LibreMetaverse.Tests/GltfDocumentTests.cs:252` | `` | `` | `pending source translation` | `pending` | `6d07930be2302e504ef9ece3fef10f47b855d33ae6c8bff152e82df0beb2a474` |
|
| `LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.Load_AutoDetectsGlbVsJson::test` | `GltfDocumentTests.Load_AutoDetectsGlbVsJson` | `` | `LibreMetaverse.Tests/GltfDocumentTests.cs:252` | `` | `` | `pending source translation` | `pending` | `6d07930be2302e504ef9ece3fef10f47b855d33ae6c8bff152e82df0beb2a474` |
|
||||||
| `LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_TrsDefaults::test` | `GltfDocumentTests.ParseNode_TrsDefaults` | `` | `LibreMetaverse.Tests/GltfDocumentTests.cs:268` | `` | `` | `pending source translation` | `pending` | `0f0fbe116d20276c2aee917b940bded9de277ed0b3e3b659844c5b3532755259` |
|
| `LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_TrsDefaults::test` | `GltfDocumentTests.ParseNode_TrsDefaults` | `` | `LibreMetaverse.Tests/GltfDocumentTests.cs:268` | `` | `` | `pending source translation` | `pending` | `0f0fbe116d20276c2aee917b940bded9de277ed0b3e3b659844c5b3532755259` |
|
||||||
| `LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_ExplicitMatrix::test` | `GltfDocumentTests.ParseNode_ExplicitMatrix` | `` | `LibreMetaverse.Tests/GltfDocumentTests.cs:280` | `` | `` | `pending source translation` | `pending` | `197ba2ee3a66cbb7d927acea13ce9dc84e62af8a500d939957749039118755c8` |
|
| `LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_ExplicitMatrix::test` | `GltfDocumentTests.ParseNode_ExplicitMatrix` | `` | `LibreMetaverse.Tests/GltfDocumentTests.cs:280` | `` | `` | `pending source translation` | `pending` | `197ba2ee3a66cbb7d927acea13ce9dc84e62af8a500d939957749039118755c8` |
|
||||||
| `LibreMetaverse.Tests/GridClientTests.cs::GridClientTests.GetGridRegion::test` | `GridClientTests.GetGridRegion` | `` | `LibreMetaverse.Tests/GridClientTests.cs:90` | `GridClient, RequiresLiveServer` | `` | `pending source translation` | `pending` | `b0b72fc63fe829984167a479b763784c7daae8691399f3f3d2feb824090ad59f` |
|
| `LibreMetaverse.Tests/GridClientTests.cs::GridClientTests.GetGridRegion::test` | `GridClientTests.GetGridRegion` | `` | `LibreMetaverse.Tests/GridClientTests.cs:90` | `GridClient, RequiresLiveServer` | `` | `tests/compat/tests/network_semantics.rs:372 (`get_grid_region_live`)` | `ignored-live` | `b0b72fc63fe829984167a479b763784c7daae8691399f3f3d2feb824090ad59f` |
|
||||||
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroDecode_ValidInput_DecodesCorrectly::test` | `HelpersZeroCodingTests.ZeroDecode_ValidInput_DecodesCorrectly` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:36` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:79 (`zero_decode_valid_input_decodes_correctly`)` | `translated` | `62353da2b1afb7bfdf5142706d15d22086a5e1e8c55f39af3e64686dda4ea071` |
|
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroDecode_ValidInput_DecodesCorrectly::test` | `HelpersZeroCodingTests.ZeroDecode_ValidInput_DecodesCorrectly` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:36` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:79 (`zero_decode_valid_input_decodes_correctly`)` | `translated` | `62353da2b1afb7bfdf5142706d15d22086a5e1e8c55f39af3e64686dda4ea071` |
|
||||||
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroDecode_NullSource_ThrowsArgumentNullException::test` | `HelpersZeroCodingTests.ZeroDecode_NullSource_ThrowsArgumentNullException` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:64` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:97 (`zero_decode_null_source_throws_argument_null`)` | `translated` | `50ebbd8ea35b87df18cccdea9a26534d5c142228e5b1698cf191b9fd2e9a9957` |
|
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroDecode_NullSource_ThrowsArgumentNullException::test` | `HelpersZeroCodingTests.ZeroDecode_NullSource_ThrowsArgumentNullException` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:64` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:97 (`zero_decode_null_source_throws_argument_null`)` | `translated` | `50ebbd8ea35b87df18cccdea9a26534d5c142228e5b1698cf191b9fd2e9a9957` |
|
||||||
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroDecode_NullDestination_ThrowsArgumentNullException::test` | `HelpersZeroCodingTests.ZeroDecode_NullDestination_ThrowsArgumentNullException` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:73` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:108 (`zero_decode_null_destination_throws_argument_null`)` | `translated` | `97197cffb02908653d831f3a62cdce2c1ddd52818343e9aacebc9b4c5ac1ee3e` |
|
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroDecode_NullDestination_ThrowsArgumentNullException::test` | `HelpersZeroCodingTests.ZeroDecode_NullDestination_ThrowsArgumentNullException` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:73` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:108 (`zero_decode_null_destination_throws_argument_null`)` | `translated` | `97197cffb02908653d831f3a62cdce2c1ddd52818343e9aacebc9b4c5ac1ee3e` |
|
||||||
@@ -273,7 +273,7 @@ Reviewed Rust tests live outside `generated_parity.rs` and carry a `parity-case`
|
|||||||
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroEncode_DestinationTooSmall_ThrowsIndexOutOfRangeException::test` | `HelpersZeroCodingTests.ZeroEncode_DestinationTooSmall_ThrowsIndexOutOfRangeException` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:218` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:222 (`zero_encode_destination_too_small_throws_index_out_of_range`)` | `translated` | `3870f0680f25e8df8de54f27c153feae9d8398e38531d67d6e0255cc34d50966` |
|
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroEncode_DestinationTooSmall_ThrowsIndexOutOfRangeException::test` | `HelpersZeroCodingTests.ZeroEncode_DestinationTooSmall_ThrowsIndexOutOfRangeException` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:218` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:222 (`zero_encode_destination_too_small_throws_index_out_of_range`)` | `translated` | `3870f0680f25e8df8de54f27c153feae9d8398e38531d67d6e0255cc34d50966` |
|
||||||
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroEncode_WithAppendedAcks_HandlesCorrectly::test` | `HelpersZeroCodingTests.ZeroEncode_WithAppendedAcks_HandlesCorrectly` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:231` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:235 (`zero_encode_with_appended_acks_preserves_count`)` | `translated` | `9803ec7bad46a1fd0f32c58d3ee08cf6a98b03a40a336ae231d1faf8211b273a` |
|
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroEncode_WithAppendedAcks_HandlesCorrectly::test` | `HelpersZeroCodingTests.ZeroEncode_WithAppendedAcks_HandlesCorrectly` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:231` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:235 (`zero_encode_with_appended_acks_preserves_count`)` | `translated` | `9803ec7bad46a1fd0f32c58d3ee08cf6a98b03a40a336ae231d1faf8211b273a` |
|
||||||
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroEncodeAndDecode_RoundTrip_PreservesData::test` | `HelpersZeroCodingTests.ZeroEncodeAndDecode_RoundTrip_PreservesData` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:254` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:248 (`zero_encode_decode_round_trip_preserves_patterns`)` | `translated` | `7847520873f87d798ea94fd1b6543db9d3606829a4bc3f4ec873e629fb6687eb` |
|
| `LibreMetaverse.Tests/HelpersZeroCodingTests.cs::HelpersZeroCodingTests.ZeroEncodeAndDecode_RoundTrip_PreservesData::test` | `HelpersZeroCodingTests.ZeroEncodeAndDecode_RoundTrip_PreservesData` | `` | `LibreMetaverse.Tests/HelpersZeroCodingTests.cs:254` | `Helpers` | `` | `tests/compat/tests/wire_semantics.rs:248 (`zero_encode_decode_round_trip_preserves_patterns`)` | `translated` | `7847520873f87d798ea94fd1b6543db9d3606829a4bc3f4ec873e629fb6687eb` |
|
||||||
| `LibreMetaverse.Tests/HttpCapsClientNonHttpLocationTests.cs::HttpCapsClientNonHttpLocationTests.PutAsync_ResponseWithNonHttpLocationHeader_DoesNotThrow::test` | `HttpCapsClientNonHttpLocationTests.PutAsync_ResponseWithNonHttpLocationHeader_DoesNotThrow` | `` | `LibreMetaverse.Tests/HttpCapsClientNonHttpLocationTests.cs:47` | `Http` | `` | `pending source translation` | `pending` | `9dbcf4023212af6f2294fa048068fe2f4d9e7e3f976d8eefb1dacbc9f6899aa8` |
|
| `LibreMetaverse.Tests/HttpCapsClientNonHttpLocationTests.cs::HttpCapsClientNonHttpLocationTests.PutAsync_ResponseWithNonHttpLocationHeader_DoesNotThrow::test` | `HttpCapsClientNonHttpLocationTests.PutAsync_ResponseWithNonHttpLocationHeader_DoesNotThrow` | `` | `LibreMetaverse.Tests/HttpCapsClientNonHttpLocationTests.cs:47` | `Http` | `` | `tests/compat/tests/network_semantics.rs:306 (`put_response_with_non_http_location_does_not_throw`)` | `translated` | `9dbcf4023212af6f2294fa048068fe2f4d9e7e3f976d8eefb1dacbc9f6899aa8` |
|
||||||
| `LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_ObjectAsset_ResultsInAttachmentInventoryTypeAndParsesFields::test` | `InventoryAISClientTests.ParseLinksFromEmbedded_ObjectAsset_ResultsInAttachmentInventoryTypeAndParsesFields` | `` | `LibreMetaverse.Tests/InventoryAISClientTests.cs:37` | `` | `` | `pending source translation` | `pending` | `3ae365ed34f12d036dcd44c94f8568d163cfeec2a58b4975975b77b418770131` |
|
| `LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_ObjectAsset_ResultsInAttachmentInventoryTypeAndParsesFields::test` | `InventoryAISClientTests.ParseLinksFromEmbedded_ObjectAsset_ResultsInAttachmentInventoryTypeAndParsesFields` | `` | `LibreMetaverse.Tests/InventoryAISClientTests.cs:37` | `` | `` | `pending source translation` | `pending` | `3ae365ed34f12d036dcd44c94f8568d163cfeec2a58b4975975b77b418770131` |
|
||||||
| `LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseItemsFromEmbedded_ItemsKey_ParsesConcreteItems::test` | `InventoryAISClientTests.ParseItemsFromEmbedded_ItemsKey_ParsesConcreteItems` | `` | `LibreMetaverse.Tests/InventoryAISClientTests.cs:82` | `` | `` | `pending source translation` | `pending` | `d9e7c64106639071e1ec6ada7346bfa050a31183becaac79efefcd4755fe2855` |
|
| `LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseItemsFromEmbedded_ItemsKey_ParsesConcreteItems::test` | `InventoryAISClientTests.ParseItemsFromEmbedded_ItemsKey_ParsesConcreteItems` | `` | `LibreMetaverse.Tests/InventoryAISClientTests.cs:82` | `` | `` | `pending source translation` | `pending` | `d9e7c64106639071e1ec6ada7346bfa050a31183becaac79efefcd4755fe2855` |
|
||||||
| `LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_MeshAsset_TreatedAsAttachment::test` | `InventoryAISClientTests.ParseLinksFromEmbedded_MeshAsset_TreatedAsAttachment` | `` | `LibreMetaverse.Tests/InventoryAISClientTests.cs:122` | `` | `` | `pending source translation` | `pending` | `f807110d577c654128dd8d42e618c610c260c4f3367cf2795776564409f876a2` |
|
| `LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_MeshAsset_TreatedAsAttachment::test` | `InventoryAISClientTests.ParseLinksFromEmbedded_MeshAsset_TreatedAsAttachment` | `` | `LibreMetaverse.Tests/InventoryAISClientTests.cs:122` | `` | `` | `pending source translation` | `pending` | `f807110d577c654128dd8d42e618c610c260c4f3367cf2795776564409f876a2` |
|
||||||
@@ -433,8 +433,8 @@ Reviewed Rust tests live outside `generated_parity.rs` and carry a `parity-case`
|
|||||||
| `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsAttachment_WhenTargetIsAttachment::test` | `MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsAttachment_WhenTargetIsAttachment` | `` | `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs:168` | `Inventory` | `` | `pending source translation` | `pending` | `f58debff8f66b7b417215eb6879f96935647b66cc619fdb00e6815c9ce5e7c67` |
|
| `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsAttachment_WhenTargetIsAttachment::test` | `MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsAttachment_WhenTargetIsAttachment` | `` | `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs:168` | `Inventory` | `` | `pending source translation` | `pending` | `f58debff8f66b7b417215eb6879f96935647b66cc619fdb00e6815c9ce5e7c67` |
|
||||||
| `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsObject_WhenTargetIsObject::test` | `MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsObject_WhenTargetIsObject` | `` | `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs:192` | `Inventory` | `` | `pending source translation` | `pending` | `b8137c994019103977b0b85d8c148e12ae8f9051334ca487db7c88bcbe707d40` |
|
| `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsObject_WhenTargetIsObject::test` | `MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsObject_WhenTargetIsObject` | `` | `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs:192` | `Inventory` | `` | `pending source translation` | `pending` | `b8137c994019103977b0b85d8c148e12ae8f9051334ca487db7c88bcbe707d40` |
|
||||||
| `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_NotContains_WhenTargetAbsent::test` | `MisclassifiedLinkRegressionTests.InventoryStore_NotContains_WhenTargetAbsent` | `` | `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs:216` | `Inventory` | `` | `pending source translation` | `pending` | `6900e220c33ec135d02c55e047c7052a095d5dd9d71da4a857ae70bc151c472b` |
|
| `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_NotContains_WhenTargetAbsent::test` | `MisclassifiedLinkRegressionTests.InventoryStore_NotContains_WhenTargetAbsent` | `` | `LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs:216` | `Inventory` | `` | `pending source translation` | `pending` | `6900e220c33ec135d02c55e047c7052a095d5dd9d71da4a857ae70bc151c472b` |
|
||||||
| `LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.DetectObjects::test` | `NetworkTests.DetectObjects` | `` | `LibreMetaverse.Tests/NetworkTests.cs:121` | `Network, RequiresLiveServer` | `` | `pending source translation` | `pending` | `8b72f1ca30feda2fad0812faf3a2f83d691d3cca9268054b3cc3bf89ad786e87` |
|
| `LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.DetectObjects::test` | `NetworkTests.DetectObjects` | `` | `LibreMetaverse.Tests/NetworkTests.cs:121` | `Network, RequiresLiveServer` | `` | `tests/compat/tests/network_semantics.rs:436 (`detect_objects_live`)` | `ignored-live` | `8b72f1ca30feda2fad0812faf3a2f83d691d3cca9268054b3cc3bf89ad786e87` |
|
||||||
| `LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.CapsQueue::test` | `NetworkTests.CapsQueue` | `` | `LibreMetaverse.Tests/NetworkTests.cs:188` | `Network, RequiresLiveServer` | `` | `pending source translation` | `pending` | `cd5af4e7d69df3e938540711877d167fe28efb9af8af7518a62b8f406e46cc18` |
|
| `LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.CapsQueue::test` | `NetworkTests.CapsQueue` | `` | `LibreMetaverse.Tests/NetworkTests.cs:188` | `Network, RequiresLiveServer` | `` | `tests/compat/tests/network_semantics.rs:515 (`caps_queue_live`)` | `ignored-live` | `cd5af4e7d69df3e938540711877d167fe28efb9af8af7518a62b8f406e46cc18` |
|
||||||
| `LibreMetaverse.Tests/NotationLLSDTests.cs::NotationSDTests.HelperFunctions::test` | `NotationSDTests.HelperFunctions` | `` | `LibreMetaverse.Tests/NotationLLSDTests.cs:53` | `` | `` | `tests/compat/tests/structured_data.rs:622 (`notation_helper_functions`)` | `translated` | `a521ca5407ed3afd1d59f5b65a283bcebe9d34b4c384d68c5fc674b3a1eeb9df` |
|
| `LibreMetaverse.Tests/NotationLLSDTests.cs::NotationSDTests.HelperFunctions::test` | `NotationSDTests.HelperFunctions` | `` | `LibreMetaverse.Tests/NotationLLSDTests.cs:53` | `` | `` | `tests/compat/tests/structured_data.rs:622 (`notation_helper_functions`)` | `translated` | `a521ca5407ed3afd1d59f5b65a283bcebe9d34b4c384d68c5fc674b3a1eeb9df` |
|
||||||
| `LibreMetaverse.Tests/NotationLLSDTests.cs::NotationSDTests.DeserializeUndef::test` | `NotationSDTests.DeserializeUndef` | `` | `LibreMetaverse.Tests/NotationLLSDTests.cs:80` | `` | `` | `tests/compat/tests/structured_data.rs:644 (`notation_deserialize_undef`)` | `translated` | `8c802fb14244cb423223c7c25702e4120da261f5dd1b378d2eca597277371406` |
|
| `LibreMetaverse.Tests/NotationLLSDTests.cs::NotationSDTests.DeserializeUndef::test` | `NotationSDTests.DeserializeUndef` | `` | `LibreMetaverse.Tests/NotationLLSDTests.cs:80` | `` | `` | `tests/compat/tests/structured_data.rs:644 (`notation_deserialize_undef`)` | `translated` | `8c802fb14244cb423223c7c25702e4120da261f5dd1b378d2eca597277371406` |
|
||||||
| `LibreMetaverse.Tests/NotationLLSDTests.cs::NotationSDTests.SerializeUndef::test` | `NotationSDTests.SerializeUndef` | `` | `LibreMetaverse.Tests/NotationLLSDTests.cs:88` | `` | `` | `tests/compat/tests/structured_data.rs:652 (`notation_serialize_undef`)` | `translated` | `2ceee97b1826a3ba88a50798dba184b48998196192e31527171a9980f06c3281` |
|
| `LibreMetaverse.Tests/NotationLLSDTests.cs::NotationSDTests.SerializeUndef::test` | `NotationSDTests.SerializeUndef` | `` | `LibreMetaverse.Tests/NotationLLSDTests.cs:88` | `` | `` | `tests/compat/tests/structured_data.rs:652 (`notation_serialize_undef`)` | `translated` | `2ceee97b1826a3ba88a50798dba184b48998196192e31527171a9980f06c3281` |
|
||||||
|
|||||||
@@ -13932,13 +13932,11 @@ fn member_02488(value: &mut libremetaverse::GridClient) {
|
|||||||
// C# member: `P:LibreMetaverse.GridClient.Self`.
|
// C# member: `P:LibreMetaverse.GridClient.Self`.
|
||||||
fn member_02489(value: &mut libremetaverse::GridClient) {
|
fn member_02489(value: &mut libremetaverse::GridClient) {
|
||||||
let _ = value.self_();
|
let _ = value.self_();
|
||||||
let _ = value.set_self_(argument());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// C# member: `P:LibreMetaverse.GridClient.Settings`.
|
// C# member: `P:LibreMetaverse.GridClient.Settings`.
|
||||||
fn member_02490(value: &mut libremetaverse::GridClient) {
|
fn member_02490(value: &mut libremetaverse::GridClient) {
|
||||||
let _ = value.settings();
|
let _ = value.settings();
|
||||||
let _ = value.set_settings(argument());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// C# member: `P:LibreMetaverse.GridClient.Sound`.
|
// C# member: `P:LibreMetaverse.GridClient.Sound`.
|
||||||
|
|||||||
30
tests/compat/build.rs
Normal file
30
tests/compat/build.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
const KEYS: [&str; 3] = ["GRID_USER", "GRID_PASSWORD", "GRID_LOGIN_URL"];
|
||||||
|
|
||||||
|
fn dotenv_has(path: &Path, key: &str) -> bool {
|
||||||
|
std::fs::read_to_string(path).is_ok_and(|contents| {
|
||||||
|
contents.lines().any(|line| {
|
||||||
|
let line = line.trim().strip_prefix("export ").unwrap_or(line.trim());
|
||||||
|
line.split_once('=').is_some_and(|(name, value)| {
|
||||||
|
name.trim() == key && !value.trim().trim_matches(['\'', '"']).is_empty()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let dotenv = Path::new(&std::env::var("CARGO_MANIFEST_DIR").expect("manifest directory"))
|
||||||
|
.join("../..")
|
||||||
|
.join(".env");
|
||||||
|
println!("cargo:rustc-check-cfg=cfg(live_grid_credentials)");
|
||||||
|
println!("cargo:rerun-if-changed={}", dotenv.display());
|
||||||
|
for key in KEYS {
|
||||||
|
println!("cargo:rerun-if-env-changed={key}");
|
||||||
|
}
|
||||||
|
if KEYS.iter().all(|key| {
|
||||||
|
std::env::var(key).is_ok_and(|value| !value.trim().is_empty()) || dotenv_has(&dotenv, key)
|
||||||
|
}) {
|
||||||
|
println!("cargo:rustc-cfg=live_grid_credentials");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -175,9 +175,6 @@
|
|||||||
// pending-parity-case: LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.ReportItemChangeAsync_WithNullLists_DoesNotThrowFromComposite::test c512c54f78c46fb4774d9b5c9c1057627592e1c25267811cddf3d687d3d1ec4d
|
// pending-parity-case: LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.ReportItemChangeAsync_WithNullLists_DoesNotThrowFromComposite::test c512c54f78c46fb4774d9b5c9c1057627592e1c25267811cddf3d687d3d1ec4d
|
||||||
// pending-parity-case: LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.AddRemovePolicy_ConcurrentAccess_DoesNotThrow::test a73a01065867d90305f491e41d9ea61bc27b80c026672ed920368877bfb0fe14
|
// pending-parity-case: LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.AddRemovePolicy_ConcurrentAccess_DoesNotThrow::test a73a01065867d90305f491e41d9ea61bc27b80c026672ed920368877bfb0fe14
|
||||||
// pending-parity-case: LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.CanAttach_WhileModifyingPolicies_DoesNotThrow::test 697999feeb776fae9a47cb9678c0ae0234d3b3831ce40c0e6f50fe622a5cc2b7
|
// pending-parity-case: LibreMetaverse.Tests/CurrentOutfitFolderTests.cs::CompositeCurrentOutfitPolicyTests.CanAttach_WhileModifyingPolicies_DoesNotThrow::test 697999feeb776fae9a47cb9678c0ae0234d3b3831ce40c0e6f50fe622a5cc2b7
|
||||||
// pending-parity-case: LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_SingleDownload_CompletesSuccessfully::test f8feb54d38f79624ddf1d368e0599259ff9d474c08ea0249a8f244460a1f533f
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_DeduplicatesRequests_SameUri_OneHttpCall::test dc3ffee1f6171833a8364750cfac2c6d3bfa812b404129e0425066ea212f2337
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_Cancellation_PropagatesToTask::test 9eb3791b1def609d6f45be0fff8ae67ea04332045c0c419c6c2e7d118aeb6271
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter::test 5c2f2b0fa2a86955975c621b2415a92ff3da283215e669956e14bf5ee2a4c1f4
|
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.GetParcelEnvironment_UsesParcelidQueryParameter::test 5c2f2b0fa2a86955975c621b2415a92ff3da283215e669956e14bf5ee2a4c1f4
|
||||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody::test f633e2d78e4c6a0fff42917ccfe8de68e4f6133a11e7eef7f9b757c3d1622f0f
|
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetParcelEnvironment_SendsParcelidInQueryStringNotBody::test f633e2d78e4c6a0fff42917ccfe8de68e4f6133a11e7eef7f9b757c3d1622f0f
|
||||||
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely::test bade6e06765506ad7e500ac3e5c9f168605ce25fef86647819d285a68b39f109
|
// pending-parity-case: LibreMetaverse.Tests/EnvironmentManagerTests.cs::EnvironmentManagerTests.SetRegionEnvironment_OmitsQueryStringEntirely::test bade6e06765506ad7e500ac3e5c9f168605ce25fef86647819d285a68b39f109
|
||||||
@@ -219,8 +216,6 @@
|
|||||||
// pending-parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.Load_AutoDetectsGlbVsJson::test 6d07930be2302e504ef9ece3fef10f47b855d33ae6c8bff152e82df0beb2a474
|
// pending-parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.Load_AutoDetectsGlbVsJson::test 6d07930be2302e504ef9ece3fef10f47b855d33ae6c8bff152e82df0beb2a474
|
||||||
// pending-parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_TrsDefaults::test 0f0fbe116d20276c2aee917b940bded9de277ed0b3e3b659844c5b3532755259
|
// pending-parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_TrsDefaults::test 0f0fbe116d20276c2aee917b940bded9de277ed0b3e3b659844c5b3532755259
|
||||||
// pending-parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_ExplicitMatrix::test 197ba2ee3a66cbb7d927acea13ce9dc84e62af8a500d939957749039118755c8
|
// pending-parity-case: LibreMetaverse.Tests/GltfDocumentTests.cs::GltfDocumentTests.ParseNode_ExplicitMatrix::test 197ba2ee3a66cbb7d927acea13ce9dc84e62af8a500d939957749039118755c8
|
||||||
// pending-parity-case: LibreMetaverse.Tests/GridClientTests.cs::GridClientTests.GetGridRegion::test b0b72fc63fe829984167a479b763784c7daae8691399f3f3d2feb824090ad59f
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/HttpCapsClientNonHttpLocationTests.cs::HttpCapsClientNonHttpLocationTests.PutAsync_ResponseWithNonHttpLocationHeader_DoesNotThrow::test 9dbcf4023212af6f2294fa048068fe2f4d9e7e3f976d8eefb1dacbc9f6899aa8
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_ObjectAsset_ResultsInAttachmentInventoryTypeAndParsesFields::test 3ae365ed34f12d036dcd44c94f8568d163cfeec2a58b4975975b77b418770131
|
// pending-parity-case: LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_ObjectAsset_ResultsInAttachmentInventoryTypeAndParsesFields::test 3ae365ed34f12d036dcd44c94f8568d163cfeec2a58b4975975b77b418770131
|
||||||
// pending-parity-case: LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseItemsFromEmbedded_ItemsKey_ParsesConcreteItems::test d9e7c64106639071e1ec6ada7346bfa050a31183becaac79efefcd4755fe2855
|
// pending-parity-case: LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseItemsFromEmbedded_ItemsKey_ParsesConcreteItems::test d9e7c64106639071e1ec6ada7346bfa050a31183becaac79efefcd4755fe2855
|
||||||
// pending-parity-case: LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_MeshAsset_TreatedAsAttachment::test f807110d577c654128dd8d42e618c610c260c4f3367cf2795776564409f876a2
|
// pending-parity-case: LibreMetaverse.Tests/InventoryAISClientTests.cs::InventoryAISClientTests.ParseLinksFromEmbedded_MeshAsset_TreatedAsAttachment::test f807110d577c654128dd8d42e618c610c260c4f3367cf2795776564409f876a2
|
||||||
@@ -344,8 +339,6 @@
|
|||||||
// pending-parity-case: LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsAttachment_WhenTargetIsAttachment::test f58debff8f66b7b417215eb6879f96935647b66cc619fdb00e6815c9ce5e7c67
|
// pending-parity-case: LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsAttachment_WhenTargetIsAttachment::test f58debff8f66b7b417215eb6879f96935647b66cc619fdb00e6815c9ce5e7c67
|
||||||
// pending-parity-case: LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsObject_WhenTargetIsObject::test b8137c994019103977b0b85d8c148e12ae8f9051334ca487db7c88bcbe707d40
|
// pending-parity-case: LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_Indexer_ReturnsObject_WhenTargetIsObject::test b8137c994019103977b0b85d8c148e12ae8f9051334ca487db7c88bcbe707d40
|
||||||
// pending-parity-case: LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_NotContains_WhenTargetAbsent::test 6900e220c33ec135d02c55e047c7052a095d5dd9d71da4a857ae70bc151c472b
|
// pending-parity-case: LibreMetaverse.Tests/MisclassifiedLinkRegressionTests.cs::MisclassifiedLinkRegressionTests.InventoryStore_NotContains_WhenTargetAbsent::test 6900e220c33ec135d02c55e047c7052a095d5dd9d71da4a857ae70bc151c472b
|
||||||
// pending-parity-case: LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.DetectObjects::test 8b72f1ca30feda2fad0812faf3a2f83d691d3cca9268054b3cc3bf89ad786e87
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.CapsQueue::test cd5af4e7d69df3e938540711877d167fe28efb9af8af7518a62b8f406e46cc18
|
|
||||||
// pending-parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_StandardRegion_Loads256x256::test c4e3a994baf06b0106a6614e9c3efbcc27e45ff1725f5470d2db6ded1fff6014
|
// pending-parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_StandardRegion_Loads256x256::test c4e3a994baf06b0106a6614e9c3efbcc27e45ff1725f5470d2db6ded1fff6014
|
||||||
// pending-parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_Varregion_Loads512x512::test 4820338f10acbb4987e26992d7a7957be58ab6bc548674bf18943ef312962894
|
// pending-parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_Varregion_Loads512x512::test 4820338f10acbb4987e26992d7a7957be58ab6bc548674bf18943ef312962894
|
||||||
// pending-parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_WrongByteCount_FailsGracefully::test ff6fb4feb2773c93397d412d0ecf6aef1f3636e823dabb729a7a6cbe94d1513f
|
// pending-parity-case: LibreMetaverse.Tests/OarFileTerrainTests.cs::OarFileTerrainTests.LoadTerrain_WrongByteCount_FailsGracefully::test ff6fb4feb2773c93397d412d0ecf6aef1f3636e823dabb729a7a6cbe94d1513f
|
||||||
|
|||||||
600
tests/compat/tests/network_semantics.rs
Normal file
600
tests/compat/tests/network_semantics.rs
Normal file
@@ -0,0 +1,600 @@
|
|||||||
|
#![allow(clippy::needless_pass_by_value)]
|
||||||
|
|
||||||
|
// Exact fixture provenance at LibreMetaverse 2aa70bb68513b39795da5d13c88f31b86e85a3ba:
|
||||||
|
// DownloadManagerTests.cs 07f31d4db35335602bc8d0a70ef440d38ce7a59f2c7765a184bc33f03b6c6015
|
||||||
|
// GridClientTests.cs adfee7ccb929270d5e88dccdb354c686bd008a167a3a1028b536664813c6d1
|
||||||
|
// HttpCapsClientNonHttpLocationTests.cs 92cac055067808883132d7415dc87d17e6ad05a62b85cd454e552879f568016f
|
||||||
|
// NetworkTests.cs 325586ce3cf9af1dbcb8dd36fc2be5647e524f4baeeb260520e44e66172142dc
|
||||||
|
|
||||||
|
use libremetaverse::http::DownloadManager;
|
||||||
|
use libremetaverse::packets::PacketType;
|
||||||
|
use libremetaverse::{GridClient, GridLayerType, HttpCapsClient, NetworkManager};
|
||||||
|
use libremetaverse_compat_tests::block_on;
|
||||||
|
use libremetaverse_types::compat::{
|
||||||
|
CancellationToken, CancellationTokenSource, HttpMessageHandler, HttpRequest, HttpResponse, Uri,
|
||||||
|
};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::{Arc, Mutex, mpsc};
|
||||||
|
use std::task::{Context, Poll, Waker};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct FakeHandler {
|
||||||
|
requests: Arc<Mutex<Vec<HttpRequest>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Delay {
|
||||||
|
state: Arc<Mutex<(bool, Option<Waker>)>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Delay {
|
||||||
|
fn new(duration: Duration) -> Self {
|
||||||
|
let state = Arc::new(Mutex::new((false, None::<Waker>)));
|
||||||
|
let worker_state = Arc::clone(&state);
|
||||||
|
thread::spawn(move || {
|
||||||
|
thread::sleep(duration);
|
||||||
|
let waker = {
|
||||||
|
let mut state = worker_state
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||||
|
state.0 = true;
|
||||||
|
state.1.take()
|
||||||
|
};
|
||||||
|
if let Some(waker) = waker {
|
||||||
|
waker.wake();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self { state }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Future for Delay {
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn poll(self: std::pin::Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let mut state = self
|
||||||
|
.state
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||||
|
if state.0 {
|
||||||
|
Poll::Ready(())
|
||||||
|
} else {
|
||||||
|
state.1 = Some(context.waker().clone());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FakeHandler {
|
||||||
|
fn new(data: &[u8], delay: Duration) -> (Self, HttpMessageHandler) {
|
||||||
|
let requests = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
let recorded = Arc::clone(&requests);
|
||||||
|
let response = HttpResponse {
|
||||||
|
status_code: 200,
|
||||||
|
headers: BTreeMap::from([("Content-Length".into(), data.len().to_string())]),
|
||||||
|
content_type: None,
|
||||||
|
body: data.to_vec(),
|
||||||
|
};
|
||||||
|
let handler = HttpMessageHandler::new(move |request, _cancellation_token| {
|
||||||
|
let recorded = Arc::clone(&recorded);
|
||||||
|
let response = response.clone();
|
||||||
|
async move {
|
||||||
|
recorded
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
.push(request);
|
||||||
|
if !delay.is_zero() {
|
||||||
|
Delay::new(delay).await;
|
||||||
|
}
|
||||||
|
response
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(Self { requests }, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_count(&self) -> usize {
|
||||||
|
self.requests
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn only_request(&self) -> HttpRequest {
|
||||||
|
let requests = self
|
||||||
|
.requests
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||||
|
assert_eq!(requests.len(), 1, "expected exactly one HTTP request");
|
||||||
|
requests[0].clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_on_timeout<F>(future: F, timeout: Duration) -> F::Output
|
||||||
|
where
|
||||||
|
F: Future + Send + 'static,
|
||||||
|
F::Output: Send + 'static,
|
||||||
|
{
|
||||||
|
let (sender, receiver) = mpsc::sync_channel(1);
|
||||||
|
let worker = thread::spawn(move || {
|
||||||
|
let _ = sender.send(block_on(future));
|
||||||
|
});
|
||||||
|
let output = receiver.recv_timeout(timeout).expect("operation timed out");
|
||||||
|
worker.join().expect("operation worker panicked");
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn join<F1, F2>(first: F1, second: F2) -> (F1::Output, F2::Output)
|
||||||
|
where
|
||||||
|
F1: Future,
|
||||||
|
F2: Future,
|
||||||
|
{
|
||||||
|
let mut first = std::pin::pin!(first);
|
||||||
|
let mut second = std::pin::pin!(second);
|
||||||
|
let mut first_output = None;
|
||||||
|
let mut second_output = None;
|
||||||
|
std::future::poll_fn(|context| {
|
||||||
|
if first_output.is_none()
|
||||||
|
&& let Poll::Ready(output) = first.as_mut().poll(context)
|
||||||
|
{
|
||||||
|
first_output = Some(output);
|
||||||
|
}
|
||||||
|
if second_output.is_none()
|
||||||
|
&& let Poll::Ready(output) = second.as_mut().poll(context)
|
||||||
|
{
|
||||||
|
second_output = Some(output);
|
||||||
|
}
|
||||||
|
if first_output.is_some() && second_output.is_some() {
|
||||||
|
Poll::Ready((
|
||||||
|
first_output.take().expect("first future output"),
|
||||||
|
second_output.take().expect("second future output"),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn credential(name: &str) -> String {
|
||||||
|
if let Ok(value) = std::env::var(name)
|
||||||
|
&& !value.trim().is_empty()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
let dotenv = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.join("../..")
|
||||||
|
.join(".env");
|
||||||
|
let contents = std::fs::read_to_string(dotenv).expect("read workspace .env");
|
||||||
|
contents
|
||||||
|
.lines()
|
||||||
|
.find_map(|line| {
|
||||||
|
let line = line.trim().strip_prefix("export ").unwrap_or(line.trim());
|
||||||
|
let (key, value) = line.split_once('=')?;
|
||||||
|
(key.trim() == name).then(|| value.trim().trim_matches(['\'', '"']).to_owned())
|
||||||
|
})
|
||||||
|
.filter(|value| !value.is_empty())
|
||||||
|
.unwrap_or_else(|| panic!("live test requires {name}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn live_credentials() -> (String, String, String, String) {
|
||||||
|
let full_name = credential("GRID_USER");
|
||||||
|
let password = credential("GRID_PASSWORD");
|
||||||
|
let login_url = credential("GRID_LOGIN_URL");
|
||||||
|
let mut names = full_name.split(' ');
|
||||||
|
let first = names.next().expect("live first name").to_owned();
|
||||||
|
let last = names.next().expect("live last name").to_owned();
|
||||||
|
(first, last, password, login_url)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_SingleDownload_CompletesSuccessfully::test f8feb54d38f79624ddf1d368e0599259ff9d474c08ea0249a8f244460a1f533f translated
|
||||||
|
#[test]
|
||||||
|
fn queue_download_single_completes_successfully() {
|
||||||
|
let bytes = b"hello world".to_vec();
|
||||||
|
let (handler, message_handler) = FakeHandler::new(&bytes, Duration::ZERO);
|
||||||
|
let http_caps = HttpCapsClient::new(message_handler).expect("HttpCapsClient constructor");
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
client.set_http_caps_client(http_caps);
|
||||||
|
let downloads = Arc::new(DownloadManager::new(client).expect("DownloadManager constructor"));
|
||||||
|
let worker_downloads = Arc::clone(&downloads);
|
||||||
|
|
||||||
|
let result = block_on_timeout(
|
||||||
|
async move {
|
||||||
|
worker_downloads
|
||||||
|
.queue_download_with_uri_string_i_progress_cancellation_token_int32(
|
||||||
|
Uri("http://example.test/one".into()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(CancellationToken::default()),
|
||||||
|
Some(1),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
},
|
||||||
|
Duration::from_secs(5),
|
||||||
|
);
|
||||||
|
let dispose_result = downloads.dispose();
|
||||||
|
let (response, data) = result.expect("QueueDownloadAsync");
|
||||||
|
|
||||||
|
assert_eq!(data, bytes);
|
||||||
|
assert!(response.is_success_status_code());
|
||||||
|
assert_eq!(response.headers["Content-Length"], bytes.len().to_string());
|
||||||
|
let request = handler.only_request();
|
||||||
|
assert_eq!(request.method, "GET");
|
||||||
|
assert_eq!(request.uri, Uri("http://example.test/one".into()));
|
||||||
|
dispose_result.expect("DownloadManager Dispose");
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_DeduplicatesRequests_SameUri_OneHttpCall::test dc3ffee1f6171833a8364750cfac2c6d3bfa812b404129e0425066ea212f2337 translated
|
||||||
|
#[test]
|
||||||
|
fn queue_download_deduplicates_same_uri() {
|
||||||
|
let bytes = b"duplicate payload".to_vec();
|
||||||
|
let (handler, message_handler) = FakeHandler::new(&bytes, Duration::from_millis(200));
|
||||||
|
let http_caps = HttpCapsClient::new(message_handler).expect("HttpCapsClient constructor");
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
client.set_http_caps_client(http_caps);
|
||||||
|
let downloads = Arc::new(DownloadManager::new(client).expect("DownloadManager constructor"));
|
||||||
|
let uri = Uri("http://example.test/dup".into());
|
||||||
|
let worker_downloads = Arc::clone(&downloads);
|
||||||
|
let (first_result, second_result) = block_on_timeout(
|
||||||
|
async move {
|
||||||
|
let first = worker_downloads
|
||||||
|
.queue_download_with_uri_string_i_progress_cancellation_token_int32(
|
||||||
|
uri.clone(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(CancellationToken::default()),
|
||||||
|
Some(1),
|
||||||
|
);
|
||||||
|
let second = worker_downloads
|
||||||
|
.queue_download_with_uri_string_i_progress_cancellation_token_int32(
|
||||||
|
uri,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(CancellationToken::default()),
|
||||||
|
Some(1),
|
||||||
|
);
|
||||||
|
join(first, second).await
|
||||||
|
},
|
||||||
|
Duration::from_secs(5),
|
||||||
|
);
|
||||||
|
let dispose_result = downloads.dispose();
|
||||||
|
let (_, first_data) = first_result.expect("first download");
|
||||||
|
let (_, second_data) = second_result.expect("second download");
|
||||||
|
|
||||||
|
assert_eq!(first_data, bytes);
|
||||||
|
assert_eq!(second_data, bytes);
|
||||||
|
assert_eq!(handler.send_count(), 1);
|
||||||
|
let request = handler.only_request();
|
||||||
|
assert_eq!(request.method, "GET");
|
||||||
|
assert_eq!(request.uri, Uri("http://example.test/dup".into()));
|
||||||
|
dispose_result.expect("DownloadManager Dispose");
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/DownloadManagerTests.cs::DownloadManagerTests.QueueDownloadAsync_Cancellation_PropagatesToTask::test 9eb3791b1def609d6f45be0fff8ae67ea04332045c0c419c6c2e7d118aeb6271 translated
|
||||||
|
#[test]
|
||||||
|
fn queue_download_cancellation_propagates() {
|
||||||
|
let bytes = b"will cancel".to_vec();
|
||||||
|
let (handler, message_handler) = FakeHandler::new(&bytes, Duration::ZERO);
|
||||||
|
let http_caps = HttpCapsClient::new(message_handler).expect("HttpCapsClient constructor");
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
client.set_http_caps_client(http_caps);
|
||||||
|
let downloads = DownloadManager::new(client).expect("DownloadManager constructor");
|
||||||
|
let cancellation = CancellationTokenSource::new();
|
||||||
|
cancellation.cancel();
|
||||||
|
|
||||||
|
let result = block_on(
|
||||||
|
downloads.queue_download_with_uri_string_i_progress_cancellation_token_int32(
|
||||||
|
Uri("http://example.test/cancel".into()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some(cancellation.token()),
|
||||||
|
Some(1),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let dispose_result = downloads.dispose();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
matches!(&result, Err(libremetaverse::Error::Cancelled)),
|
||||||
|
"expected Cancelled, got {result:?}"
|
||||||
|
);
|
||||||
|
assert_eq!(handler.send_count(), 0);
|
||||||
|
dispose_result.expect("DownloadManager Dispose");
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/HttpCapsClientNonHttpLocationTests.cs::HttpCapsClientNonHttpLocationTests.PutAsync_ResponseWithNonHttpLocationHeader_DoesNotThrow::test 9dbcf4023212af6f2294fa048068fe2f4d9e7e3f976d8eefb1dacbc9f6899aa8 translated
|
||||||
|
#[test]
|
||||||
|
fn put_response_with_non_http_location_does_not_throw() {
|
||||||
|
const SLCAPS: &str = "slcaps://11111111-1111-1111-1111-111111111111/category/x";
|
||||||
|
let body = b"<llsd><map/></llsd>";
|
||||||
|
let response = HttpResponse {
|
||||||
|
status_code: 201,
|
||||||
|
headers: BTreeMap::from([
|
||||||
|
("Location".into(), SLCAPS.into()),
|
||||||
|
("Content-Location".into(), SLCAPS.into()),
|
||||||
|
("Content-Length".into(), body.len().to_string()),
|
||||||
|
]),
|
||||||
|
content_type: Some("application/llsd+xml".into()),
|
||||||
|
body: body.to_vec(),
|
||||||
|
};
|
||||||
|
let requests = Arc::new(Mutex::new(Vec::new()));
|
||||||
|
let recorded = Arc::clone(&requests);
|
||||||
|
let message_handler = HttpMessageHandler::new(move |request, _cancellation_token| {
|
||||||
|
let recorded = Arc::clone(&recorded);
|
||||||
|
let response = response.clone();
|
||||||
|
async move {
|
||||||
|
recorded
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
.push(request);
|
||||||
|
response
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
let http_caps = HttpCapsClient::new(message_handler).expect("HttpCapsClient constructor");
|
||||||
|
client.set_http_caps_client(http_caps);
|
||||||
|
|
||||||
|
let (reply, reply_body) = block_on(
|
||||||
|
client
|
||||||
|
.http_caps_client()
|
||||||
|
.put_with_uri_string_bytes_cancellation_token_i_progress(
|
||||||
|
Uri("http://127.0.0.1/".into()),
|
||||||
|
"application/llsd+xml".into(),
|
||||||
|
b"test".to_vec(),
|
||||||
|
CancellationToken::default(),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("HttpCapsClient PutAsync");
|
||||||
|
|
||||||
|
assert_eq!(reply.status_code, 201);
|
||||||
|
assert_eq!(reply.headers["Location"], SLCAPS);
|
||||||
|
assert_eq!(reply.headers["Content-Location"], SLCAPS);
|
||||||
|
assert_eq!(reply.content_type.as_deref(), Some("application/llsd+xml"));
|
||||||
|
assert_eq!(reply_body, body);
|
||||||
|
let request = {
|
||||||
|
let requests = requests
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||||
|
assert_eq!(requests.len(), 1, "expected exactly one HTTP request");
|
||||||
|
requests[0].clone()
|
||||||
|
};
|
||||||
|
assert_eq!(request.method, "PUT");
|
||||||
|
assert_eq!(request.uri, Uri("http://127.0.0.1/".into()));
|
||||||
|
assert_eq!(
|
||||||
|
request.content_type.as_deref(),
|
||||||
|
Some("application/llsd+xml")
|
||||||
|
);
|
||||||
|
assert_eq!(request.body, b"test");
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/GridClientTests.cs::GridClientTests.GetGridRegion::test b0b72fc63fe829984167a479b763784c7daae8691399f3f3d2feb824090ad59f ignored-live
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(live_grid_credentials),
|
||||||
|
ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env"
|
||||||
|
)]
|
||||||
|
fn get_grid_region_live() {
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
client.self_().movement.set_fly(true);
|
||||||
|
let network = client.network();
|
||||||
|
let (first, last, password, login_url) = live_credentials();
|
||||||
|
let start = NetworkManager::start_location("Hooper".into(), 179, 18, 32)
|
||||||
|
.expect("NetworkManager StartLocation");
|
||||||
|
let mut login = network
|
||||||
|
.default_login_params(
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
password,
|
||||||
|
"Unit Test Framework".into(),
|
||||||
|
"contact@radegast.life".into(),
|
||||||
|
)
|
||||||
|
.expect("NetworkManager DefaultLoginParams");
|
||||||
|
login.start = start;
|
||||||
|
login.uri = login_url;
|
||||||
|
let logged_in = block_on(network.login_with_login_params_cancellation_token(login, None))
|
||||||
|
.expect("NetworkManager LoginAsync");
|
||||||
|
assert!(
|
||||||
|
logged_in,
|
||||||
|
"client failed to log in: {}",
|
||||||
|
network.login_message()
|
||||||
|
);
|
||||||
|
assert!(network.connected(), "client is not connected to the grid");
|
||||||
|
let simulator = network
|
||||||
|
.current_sim()
|
||||||
|
.expect("CurrentSim is null after successful login");
|
||||||
|
if simulator.name.is_empty() {
|
||||||
|
eprintln!("CurrentSim.Name is empty after login, proceeding with tests");
|
||||||
|
} else if !simulator.name.eq_ignore_ascii_case("hooper") {
|
||||||
|
eprintln!(
|
||||||
|
"logged in to region '{}' instead of 'Hooper', proceeding with tests",
|
||||||
|
simulator.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let region = block_on(
|
||||||
|
client
|
||||||
|
.grid()
|
||||||
|
.get_grid_region_with_string_grid_layer_type_cancellation_token(
|
||||||
|
"Hippo Hollow".into(),
|
||||||
|
GridLayerType::Terrain,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("GridManager GetGridRegionAsync");
|
||||||
|
if let Some(Some(region)) = region {
|
||||||
|
assert_eq!(region.name.to_lowercase(), "hippo hollow");
|
||||||
|
} else {
|
||||||
|
eprintln!("Grid region 'Hippo Hollow' not found; skipping assertion");
|
||||||
|
}
|
||||||
|
|
||||||
|
network.logout_with_method().expect("NetworkManager Logout");
|
||||||
|
let _ = client.dispose_with_method();
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.DetectObjects::test 8b72f1ca30feda2fad0812faf3a2f83d691d3cca9268054b3cc3bf89ad786e87 ignored-live
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(live_grid_credentials),
|
||||||
|
ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env"
|
||||||
|
)]
|
||||||
|
fn detect_objects_live() {
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
client.settings().timing().login_timeout = 30 * 1_000;
|
||||||
|
client.self_().movement.set_fly(true);
|
||||||
|
let detected = Arc::new(AtomicBool::new(false));
|
||||||
|
let callback_detected = Arc::clone(&detected);
|
||||||
|
let network = Arc::new(client.network());
|
||||||
|
network
|
||||||
|
.register_callback_with_packet_type_event_handler(
|
||||||
|
PacketType::ObjectUpdate,
|
||||||
|
Arc::new(move |_event| callback_detected.store(true, Ordering::SeqCst)),
|
||||||
|
)
|
||||||
|
.expect("register ObjectUpdate callback");
|
||||||
|
let (first, last, password, login_url) = live_credentials();
|
||||||
|
let start = NetworkManager::start_location("Hooper".into(), 179, 18, 32)
|
||||||
|
.expect("NetworkManager StartLocation");
|
||||||
|
let mut login = network
|
||||||
|
.default_login_params(
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
password,
|
||||||
|
"Unit Test Framework".into(),
|
||||||
|
"admin@radegast.life".into(),
|
||||||
|
)
|
||||||
|
.expect("NetworkManager DefaultLoginParams");
|
||||||
|
login.start = start;
|
||||||
|
login.uri = login_url;
|
||||||
|
let login_network = Arc::clone(&network);
|
||||||
|
let logged_in = block_on_timeout(
|
||||||
|
async move {
|
||||||
|
login_network
|
||||||
|
.login_with_login_params_cancellation_token(login, None)
|
||||||
|
.await
|
||||||
|
},
|
||||||
|
Duration::from_secs(45),
|
||||||
|
)
|
||||||
|
.expect("NetworkManager LoginAsync");
|
||||||
|
assert!(
|
||||||
|
logged_in,
|
||||||
|
"client failed to log in: {}",
|
||||||
|
network.login_message()
|
||||||
|
);
|
||||||
|
assert!(network.connected(), "client is not connected to the grid");
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
let simulator = network
|
||||||
|
.current_sim()
|
||||||
|
.expect("CurrentSim is null after successful login");
|
||||||
|
if simulator.name.is_empty() {
|
||||||
|
eprintln!("CurrentSim.Name is empty, but proceeding with tests");
|
||||||
|
} else if !simulator.name.eq_ignore_ascii_case("hooper") {
|
||||||
|
eprintln!(
|
||||||
|
"logged in to region '{}' instead of 'Hooper', but proceeding with tests",
|
||||||
|
simulator.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let started = Instant::now();
|
||||||
|
while !detected.load(Ordering::SeqCst) {
|
||||||
|
assert!(
|
||||||
|
started.elapsed() <= Duration::from_secs(20),
|
||||||
|
"timeout waiting for an ObjectUpdate packet after 20 seconds"
|
||||||
|
);
|
||||||
|
thread::sleep(Duration::from_millis(100));
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
detected.load(Ordering::SeqCst),
|
||||||
|
"successfully detected objects"
|
||||||
|
);
|
||||||
|
|
||||||
|
network.logout_with_method().expect("NetworkManager Logout");
|
||||||
|
let _ = client.dispose_with_method();
|
||||||
|
}
|
||||||
|
|
||||||
|
// parity-case: LibreMetaverse.Tests/NetworkTests.cs::NetworkTests.CapsQueue::test cd5af4e7d69df3e938540711877d167fe28efb9af8af7518a62b8f406e46cc18 ignored-live
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(live_grid_credentials),
|
||||||
|
ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env"
|
||||||
|
)]
|
||||||
|
fn caps_queue_live() {
|
||||||
|
let mut client = GridClient::new().expect("GridClient constructor");
|
||||||
|
client.settings().timing().login_timeout = 30 * 1_000;
|
||||||
|
client.self_().movement.set_fly(true);
|
||||||
|
let detected = Arc::new(AtomicBool::new(false));
|
||||||
|
let callback_detected = Arc::clone(&detected);
|
||||||
|
let network = Arc::new(client.network());
|
||||||
|
network
|
||||||
|
.register_callback_with_packet_type_event_handler(
|
||||||
|
PacketType::ObjectUpdate,
|
||||||
|
Arc::new(move |_event| callback_detected.store(true, Ordering::SeqCst)),
|
||||||
|
)
|
||||||
|
.expect("register ObjectUpdate callback");
|
||||||
|
let (first, last, password, login_url) = live_credentials();
|
||||||
|
let start = NetworkManager::start_location("Hooper".into(), 179, 18, 32)
|
||||||
|
.expect("NetworkManager StartLocation");
|
||||||
|
let mut login = network
|
||||||
|
.default_login_params(
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
password,
|
||||||
|
"Unit Test Framework".into(),
|
||||||
|
"admin@radegast.life".into(),
|
||||||
|
)
|
||||||
|
.expect("NetworkManager DefaultLoginParams");
|
||||||
|
login.start = start;
|
||||||
|
login.uri = login_url;
|
||||||
|
let login_network = Arc::clone(&network);
|
||||||
|
let logged_in = block_on_timeout(
|
||||||
|
async move {
|
||||||
|
login_network
|
||||||
|
.login_with_login_params_cancellation_token(login, None)
|
||||||
|
.await
|
||||||
|
},
|
||||||
|
Duration::from_secs(45),
|
||||||
|
)
|
||||||
|
.expect("NetworkManager LoginAsync");
|
||||||
|
assert!(
|
||||||
|
logged_in,
|
||||||
|
"client failed to log in: {}",
|
||||||
|
network.login_message()
|
||||||
|
);
|
||||||
|
assert!(network.connected(), "client is not connected to the grid");
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
let simulator = network
|
||||||
|
.current_sim()
|
||||||
|
.expect("CurrentSim is null after successful login");
|
||||||
|
if simulator.name.is_empty() {
|
||||||
|
eprintln!("CurrentSim.Name is empty, but proceeding with tests");
|
||||||
|
} else if !simulator.name.eq_ignore_ascii_case("hooper") {
|
||||||
|
eprintln!(
|
||||||
|
"logged in to region '{}' instead of 'Hooper', but proceeding with tests",
|
||||||
|
simulator.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let already_running = network
|
||||||
|
.current_sim()
|
||||||
|
.and_then(|simulator| simulator.caps)
|
||||||
|
.is_some_and(|caps| caps.is_event_queue_running());
|
||||||
|
let event_queue_running = if already_running {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
let (sender, receiver) = mpsc::sync_channel(1);
|
||||||
|
let _subscription = network.subscribe_event_queue_running(Arc::new(move |_event| {
|
||||||
|
let _ = sender.send(());
|
||||||
|
}));
|
||||||
|
receiver
|
||||||
|
.recv_timeout(Duration::from_secs(10))
|
||||||
|
.expect("timeout waiting for event queue to start");
|
||||||
|
true
|
||||||
|
};
|
||||||
|
assert!(
|
||||||
|
event_queue_running,
|
||||||
|
"CAPS Event Queue is not running and failed to start"
|
||||||
|
);
|
||||||
|
|
||||||
|
network.logout_with_method().expect("NetworkManager Logout");
|
||||||
|
let _ = client.dispose_with_method();
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -188,6 +188,20 @@ MEMBER_SIGNATURE_OVERRIDES = {
|
|||||||
"mutable_self,owned,mutable_borrow,mutable_borrow,optional_mutable_borrow",
|
"mutable_self,owned,mutable_borrow,mutable_borrow,optional_mutable_borrow",
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
PROPERTY_SIGNATURE_OVERRIDES = {
|
||||||
|
"P:LibreMetaverse.GridClient.Self": (
|
||||||
|
"pub fn self_(&mut self) -> &mut libremetaverse::AgentManager",
|
||||||
|
"mutable_self",
|
||||||
|
),
|
||||||
|
"P:LibreMetaverse.GridClient.Settings": (
|
||||||
|
"pub fn settings(&mut self) -> &mut libremetaverse::Settings",
|
||||||
|
"mutable_self",
|
||||||
|
),
|
||||||
|
"P:LibreMetaverse.Settings.Timing": (
|
||||||
|
"pub fn timing(&mut self) -> &mut libremetaverse::TimingSettings",
|
||||||
|
"mutable_self",
|
||||||
|
),
|
||||||
|
}
|
||||||
TYPE_USAGE_OVERRIDES = {
|
TYPE_USAGE_OVERRIDES = {
|
||||||
"LibreMetaverse.DictionaryChangeCallback": (
|
"LibreMetaverse.DictionaryChangeCallback": (
|
||||||
"std::sync::Arc<dyn Fn(libremetaverse::DictionaryEventAction, "
|
"std::sync::Arc<dyn Fn(libremetaverse::DictionaryEventAction, "
|
||||||
@@ -673,6 +687,9 @@ def member_signature(mapper: Mapper, owner: dict, item: dict, rust_name: str) ->
|
|||||||
signature = f"pub {rust_name}: {value_type}"
|
signature = f"pub {rust_name}: {value_type}"
|
||||||
return signature, "owned_value", asyncness, "none", "direct"
|
return signature, "owned_value", asyncness, "none", "direct"
|
||||||
if kind in {"property", "indexer"}:
|
if kind in {"property", "indexer"}:
|
||||||
|
if item["doc_id"] in PROPERTY_SIGNATURE_OVERRIDES:
|
||||||
|
signature, ownership = PROPERTY_SIGNATURE_OVERRIDES[item["doc_id"]]
|
||||||
|
return signature, ownership, asyncness, error_model, "accessor_methods"
|
||||||
value_type = mapper.type(item["type"], item.get("nullability"), generics)
|
value_type = mapper.type(item["type"], item.get("nullability"), generics)
|
||||||
accessors = {accessor["kind"] for accessor in item.get("accessors", [])}
|
accessors = {accessor["kind"] for accessor in item.get("accessors", [])}
|
||||||
pieces = []
|
pieces = []
|
||||||
|
|||||||
Reference in New Issue
Block a user