160 lines
6.8 KiB
Rust
160 lines
6.8 KiB
Rust
// Exact Rust translations of LibreMetaverse.Tests/OfflineMessagesTests.cs and
|
|
// LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs.
|
|
// Source SHA-256: ad649e9efb2b60b8a323d3d457be568fda9cc5ecb80b8999f6066d0b7f5a6527
|
|
// Source SHA-256: fabdc141e6f616b88d998ceca16f1884d4c3aa6efc5152060e8840a4ef0d6db7
|
|
|
|
use libremetaverse::messages::linden::{
|
|
ProductInfoRequestMessage, ProductInfoRequestMessageProductInfo,
|
|
};
|
|
use libremetaverse::{GridClient, HttpCapsClient, Simulator};
|
|
use libremetaverse_compat_tests::block_on;
|
|
use libremetaverse_structured_data::{OSD, OSDMap};
|
|
use libremetaverse_types::compat::{HttpMessageHandler, HttpResponse, Uri};
|
|
use std::collections::{BTreeMap, HashMap};
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
const CAP: &str = "http://test.invalid/read-offline-msgs";
|
|
const SEED: &str = "http://test.invalid/seed";
|
|
|
|
fn response(body: &str) -> HttpResponse {
|
|
HttpResponse {
|
|
status_code: 200,
|
|
headers: BTreeMap::new(),
|
|
content_type: Some("application/json".into()),
|
|
body: body.as_bytes().to_vec(),
|
|
}
|
|
}
|
|
|
|
fn offline_client(body: &str) -> GridClient {
|
|
let body = body.to_owned();
|
|
let handler = HttpMessageHandler::new(move |request, _| {
|
|
let reply = if request.uri.0 == SEED {
|
|
HttpResponse {
|
|
status_code: 200,
|
|
headers: BTreeMap::new(),
|
|
content_type: Some("application/llsd+xml".into()),
|
|
body: format!(
|
|
"<llsd><map><key>ReadOfflineMsgs</key><uri>{CAP}</uri><key>AcceptFriendship</key><uri>http://test.invalid/accept-friendship</uri><key>AcceptGroupInvite</key><uri>http://test.invalid/accept-group-invite</uri></map></llsd>"
|
|
)
|
|
.into_bytes(),
|
|
}
|
|
} else {
|
|
response(&body)
|
|
};
|
|
async move { reply }
|
|
});
|
|
let mut client = GridClient::new().expect("GridClient constructor");
|
|
client.set_http_caps_client(HttpCapsClient::new(handler.clone()).unwrap());
|
|
let mut simulator_client = GridClient::new().expect("simulator GridClient constructor");
|
|
simulator_client.set_http_caps_client(HttpCapsClient::new(handler).unwrap());
|
|
let simulator = Simulator::new(
|
|
simulator_client,
|
|
"127.0.0.1:13".parse().unwrap(),
|
|
0,
|
|
None,
|
|
None,
|
|
)
|
|
.expect("Simulator constructor");
|
|
simulator
|
|
.set_seed_caps(Some(Uri(SEED.into())), Some(true))
|
|
.unwrap();
|
|
let mut network = client.network();
|
|
network.set_current_sim(Some(simulator));
|
|
client.set_network(network);
|
|
client
|
|
}
|
|
|
|
fn message_json(from_name: &str, text: &str) -> String {
|
|
format!(
|
|
"{{\"from_agent_id\":\"11111111-1111-1111-1111-111111111111\",\"from_agent_name\":\"{from_name}\",\"to_agent_id\":\"22222222-2222-2222-2222-222222222222\",\"region_id\":\"33333333-3333-3333-3333-333333333333\",\"dialog\":0,\"transaction-id\":\"44444444-4444-4444-4444-444444444444\",\"timestamp\":0,\"message\":\"{text}\",\"local_x\":1.0,\"local_y\":2.0,\"local_z\":3.0}}"
|
|
)
|
|
}
|
|
|
|
fn retrieve(body: &str) -> Vec<(String, String)> {
|
|
let mut client = offline_client(body);
|
|
let received = Arc::new(Mutex::new(Vec::new()));
|
|
let captured = Arc::clone(&received);
|
|
let agent = client.self_();
|
|
let _subscription = agent.subscribe_im(Arc::new(move |args| {
|
|
let message = args.im();
|
|
captured
|
|
.lock()
|
|
.unwrap()
|
|
.push((message.message, message.from_agent_name));
|
|
}));
|
|
block_on(agent.retrieve_instant_messages(None)).unwrap();
|
|
received.lock().unwrap().clone()
|
|
}
|
|
|
|
fn map(entries: impl IntoIterator<Item = (&'static str, OSD)>) -> OSDMap {
|
|
OSDMap::new_with_dictionary(
|
|
entries
|
|
.into_iter()
|
|
.map(|(key, value)| (key.into(), value))
|
|
.collect(),
|
|
)
|
|
.expect("OSDMap dictionary constructor")
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/OfflineMessagesTests.cs::OfflineMessagesTests.RetrieveInstantMessagesAsync_BareArrayOfArraysResponse_RaisesInstantMessage::test d51f69e0fa1e1e59a5cedec7d60315d1f590848672a9f4f0c5e21d2abff5c372 translated
|
|
#[test]
|
|
fn retrieve_offline_messages_bare_array_raises_instant_message() {
|
|
let received = retrieve(&format!("[[{}]]", message_json("Jim", "hello")));
|
|
assert_eq!(received.len(), 1);
|
|
assert_eq!(received[0].0, "hello");
|
|
assert_eq!(received[0].1, "Jim");
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/OfflineMessagesTests.cs::OfflineMessagesTests.RetrieveInstantMessagesAsync_MessagesMapResponse_RaisesInstantMessage::test dbce6320d57d12ca5557cfba65257e15be314cde947b20dd21bc386819fcb3ce translated
|
|
#[test]
|
|
fn retrieve_offline_messages_map_raises_instant_message() {
|
|
let received = retrieve(&format!(
|
|
"{{\"messages\":[{}]}}",
|
|
message_json("Jim", "hello via map")
|
|
));
|
|
assert_eq!(received.len(), 1);
|
|
assert_eq!(received[0].0, "hello via map");
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs::ProductInfoRequestMessageTests.Deserialize_BareArray_ReadsSkuNameDescription::test 5d51fdbb1bec1ff74df59778d214413e78fb650679d36e7c44be92d1b2e3205f translated
|
|
#[test]
|
|
fn product_info_deserialize_bare_array_reads_fields() {
|
|
let product = OSD::Map(HashMap::from([
|
|
("sku".into(), OSD::String("023".into())),
|
|
("name".into(), OSD::String("Homestead".into())),
|
|
(
|
|
"description".into(),
|
|
OSD::String("A Homestead region".into()),
|
|
),
|
|
]));
|
|
let mut message =
|
|
ProductInfoRequestMessage::new().expect("ProductInfoRequestMessage constructor");
|
|
message
|
|
.deserialize(map([("products", OSD::Array(vec![product]))]))
|
|
.unwrap();
|
|
assert_eq!(message.products.len(), 1);
|
|
assert_eq!(message.products[0].sku, "023");
|
|
assert_eq!(message.products[0].name, "Homestead");
|
|
assert_eq!(message.products[0].description, "A Homestead region");
|
|
}
|
|
|
|
// parity-case: LibreMetaverse.Tests/ProductInfoRequestMessageTests.cs::ProductInfoRequestMessageTests.SerializeDeserialize_RoundTrips::test 5cb54bed4150cf13f815b223d6b7e35e7427004a12e98c7328c7674b6fe6309b translated
|
|
#[test]
|
|
fn product_info_serialize_deserialize_round_trips() {
|
|
let mut product = ProductInfoRequestMessageProductInfo::new().expect("ProductInfo constructor");
|
|
product.sku = "001".into();
|
|
product.name = "Full Region".into();
|
|
product.description = "A full region".into();
|
|
let mut message =
|
|
ProductInfoRequestMessage::new().expect("ProductInfoRequestMessage constructor");
|
|
message.products.push(product);
|
|
let encoded = message.serialize().unwrap();
|
|
let mut decoded =
|
|
ProductInfoRequestMessage::new().expect("ProductInfoRequestMessage constructor");
|
|
decoded.deserialize(encoded).unwrap();
|
|
assert_eq!(decoded.products.len(), 1);
|
|
assert_eq!(decoded.products[0].sku, "001");
|
|
assert_eq!(decoded.products[0].name, "Full Region");
|
|
assert_eq!(decoded.products[0].description, "A full region");
|
|
}
|