// Exact Rust translations of the message, sharing, and name restriction tests.

use libremetaverse_compat_tests::block_on;
use libremetaverse_compat_tests::rlv_support::{RlvHarness, guid};
use libremetaverse_rlv::RlvPermissionsServiceHoverTextLocation as HoverTextLocation;

const USER_1: &str = "00000000-0000-4000-8000-000000000000";
const USER_2: &str = "11111111-1111-4111-8111-111111111111";
const SENDER_2: &str = "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa";
const SENDER_3: &str = "22222222-2222-4222-8222-222222222222";

fn harness() -> RlvHarness {
    RlvHarness::new().expect("RlvService constructor")
}

fn process(h: &RlvHarness, commands: &[&str]) {
    for command in commands {
        block_on(h.process(command)).unwrap();
    }
}

fn receive_im(h: &RlvHarness, user: &str, group: Option<&str>) -> bool {
    h.service
        .permissions()
        .can_receive_im(
            "Hello world".into(),
            Some(Some(guid(user))),
            group.map(Into::into),
        )
        .unwrap()
}

fn send_im(h: &RlvHarness, user: &str, group: Option<&str>) -> bool {
    h.service
        .permissions()
        .can_send_im(
            "Hello world".into(),
            Some(Some(guid(user))),
            group.map(Into::into),
        )
        .unwrap()
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvChatExceptionTests.cs::RecvChatExceptionTests.CanRecvChat::test 017906038e211352d7d2751fafbcab5028cd8b189e7aa29a6202ff578976a23c translated
#[test]
fn receive_chat_blocks_chat_but_not_emote() {
    let h = harness();
    process(&h, &["@recvchat=n"]);
    let permissions = h.service.permissions();
    assert!(
        !permissions
            .can_receive_chat("Hello world".into(), guid(SENDER_2))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("/me says Hello world".into(), guid(SENDER_2))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvChatFromRestrictionTests.cs::RecvChatFromRestrictionTests.CanRecvChatFrom::test aaf24dc0b8533a7e93cc567fecbb866067b72da1837207869f879647840bfa21 translated
#[test]
fn receive_chat_from_one_user() {
    let h = harness();
    process(&h, &[&format!("@recvchatfrom:{USER_1}=add")]);
    let permissions = h.service.permissions();
    assert!(
        !permissions
            .can_receive_chat("Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("/me says Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(USER_2))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvChatSecExceptionTests.cs::RecvChatSecExceptionTests.CanRecvChat_Secure::test cba089ebe607088e37be285918a1d2c674f1acc4cad075733108afea3ad0279b translated
#[test]
fn secure_receive_chat_exceptions_are_sender_scoped() {
    let h = harness();
    process(&h, &["@recvchat_sec=n"]);
    block_on(h.process_from(&format!("@recvchat:{USER_1}=add"), SENDER_2, "Sender 2")).unwrap();
    process(&h, &[&format!("@recvchat:{USER_2}=add")]);
    let permissions = h.service.permissions();
    assert!(
        !permissions
            .can_receive_chat("Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(USER_2))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvEmoteFromRestrictionTests.cs::RecvEmoteFromRestrictionTests.CanRecvChat_RecvEmoteFrom::test d07ded724315cf135603d4dc5a684e5a59a5cf8415963acc30d402ad81916ac1 translated
#[test]
fn receive_emote_from_one_user() {
    let h = harness();
    process(&h, &[&format!("@recvemotefrom:{USER_1}=n")]);
    let permissions = h.service.permissions();
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(USER_2))
            .unwrap()
    );
    assert!(
        !permissions
            .can_receive_chat("/me says Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("/me says Hello world".into(), guid(USER_2))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvEmoteRestrictionTests.cs::RecvEmoteRestrictionTests.CanRecvChat_RecvEmote::test 438b72e6c44570580bf41aa7b8ed00afb800eff8836ee971eab9fc6a00fecc19 translated
#[test]
fn receive_emote_restriction() {
    let h = harness();
    process(&h, &["@recvemote=n"]);
    let permissions = h.service.permissions();
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(SENDER_2))
            .unwrap()
    );
    assert!(
        !permissions
            .can_receive_chat("/me says Hello world".into(), guid(SENDER_2))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvEmoteSecRestrictionTests.cs::RecvEmoteSecRestrictionTests.CanRecvChat_RecvEmote_Secure::test 9e1f72426762569b1c650fdf80c53e4a590b6476f8539fff6e110101e48459e8 translated
#[test]
fn secure_receive_emote_exceptions_are_sender_scoped() {
    let h = harness();
    process(&h, &["@recvemote_sec=n"]);
    block_on(h.process_from(&format!("@recvemote:{USER_1}=add"), SENDER_2, "Sender 2")).unwrap();
    process(&h, &[&format!("@recvemote:{USER_2}=add")]);
    let permissions = h.service.permissions();
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("Hello world".into(), guid(USER_2))
            .unwrap()
    );
    assert!(
        !permissions
            .can_receive_chat("/me says Hello world".into(), guid(USER_1))
            .unwrap()
    );
    assert!(
        permissions
            .can_receive_chat("/me says Hello world".into(), guid(USER_2))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImFromRestrictionTests.cs::RecvImFromRestrictionTests.CanReceiveIMFrom::test ebe072c7e1c8ba440b560c2e4a0aa5151ba546f5b6cd5505012958e901c58201 translated
#[test]
fn receive_im_from_one_user() {
    let h = harness();
    process(&h, &[&format!("@recvimfrom:{USER_1}=n")]);
    assert!(!receive_im(&h, USER_1, None));
    assert!(receive_im(&h, USER_2, None));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImFromRestrictionTests.cs::RecvImFromRestrictionTests.CanReceiveIMFrom_Group::test d3d155240723ca2d379f00111a3b27acb41786615a2f5b0ad2c968040d7f4447 translated
#[test]
fn receive_im_from_one_group() {
    let h = harness();
    process(&h, &["@recvimfrom:First Group=n"]);
    assert!(!receive_im(&h, USER_1, Some("First Group")));
    assert!(receive_im(&h, USER_2, Some("Second Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImFromRestrictionTests.cs::RecvImFromRestrictionTests.CanReceiveIMTo_AllGroups::test dd1050e7ef3e9805b88964822485856d6b2e5e98ee647ee08251cbc5bd452208 translated
#[test]
fn receive_im_from_all_groups() {
    let h = harness();
    process(&h, &["@recvimfrom:allgroups=n"]);
    assert!(!receive_im(&h, USER_1, Some("First Group")));
    assert!(!receive_im(&h, USER_2, Some("Second Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImRestrictionTests.cs::RecvImRestrictionTests.CanReceiveIM::test 9c88e79ed2686e571e32ccecbc93c130423b966ff4e65e72f228f1713e5047cd translated
#[test]
fn receive_im_restriction() {
    let h = harness();
    process(&h, &["@recvim=n"]);
    assert!(
        !h.service
            .permissions()
            .can_receive_im("Hello".into(), Some(Some(guid(USER_1))), None)
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_receive_im(
                "Hello".into(),
                Some(Some(guid(USER_1))),
                Some("Group Name".into())
            )
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImSecRestrictionTests.cs::RecvImSecRestrictionTests.CanReceiveIM_Secure::test e549fe9719efd180f8ab8c80b989701cd23ebf07cd004d9a5a18a0cc7db12e64 translated
#[test]
fn secure_receive_im_user_exceptions_are_sender_scoped() {
    let h = harness();
    process(&h, &["@recvim_sec=n", &format!("@recvim:{USER_1}=add")]);
    block_on(h.process_from(&format!("@recvim:{USER_2}=add"), SENDER_2, "Sender 2")).unwrap();
    assert!(receive_im(&h, USER_1, None));
    assert!(!receive_im(&h, USER_2, None));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImSecRestrictionTests.cs::RecvImSecRestrictionTests.CanReceiveIM_Secure_Group::test 13653ee7443d2eca88f2940d0c3804de3685dcf6c9277a4717a42dad4c01fca4 translated
#[test]
fn secure_receive_im_group_exception() {
    let h = harness();
    process(&h, &["@recvim_sec=n", "@recvim:Group Name=add"]);
    block_on(h.process_from("@recvim:allgroups=add", SENDER_2, "Sender 2")).unwrap();
    assert!(receive_im(&h, USER_1, Some("Group Name")));
    assert!(!receive_im(&h, USER_1, Some("Another Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/RecvImSecRestrictionTests.cs::RecvImSecRestrictionTests.CanReceiveIM_Secure_AllGroups::test d99435b52a3b774ab5d2bb6911824fa45803fe82cfe0b2c192a05473b72463c8 translated
#[test]
fn secure_receive_im_all_groups_exception() {
    let h = harness();
    process(&h, &["@recvim_sec=n", "@recvim:allgroups=add"]);
    assert!(receive_im(&h, USER_1, Some("Group Name")));
    assert!(receive_im(&h, USER_1, Some("Another Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendChannelRestrictionTests.cs::SendChannelRestrictionTests.CanSendChannel::test 8496734391f57cf2f2d8156f3b5a9ad9147c959e3bf99f9e76a4072e971a5b42 translated
#[test]
fn send_channel_restriction() {
    let h = harness();
    process(&h, &["@sendchannel=n"]);
    assert!(
        !h.service
            .permissions()
            .can_chat(123, "Hello world".into())
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendChannelSecRestrictionTests.cs::SendChannelSecRestrictionTests.CanSendChannel_Secure::test 5bd9096e9af488d5cdb08ed78120ef46f81f9be1eaf132c49a955eb07ae904eb translated
#[test]
fn secure_send_channel_restrictions_are_sender_scoped() {
    let h = harness();
    process(&h, &["@sendchannel_sec=n", "@sendchannel:123=n"]);
    block_on(h.process_from("@sendchannel:456=n", SENDER_2, "Sender 2")).unwrap();
    assert!(
        h.service
            .permissions()
            .can_chat(123, "Hello world".into())
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_chat(456, "Hello world".into())
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendChannelSecRestrictionTests.cs::SendChannelSecRestrictionTests.CanSendChannel_Secure_Exception::test e675121ba9f6ab8f6e4484e66d76d0dd14f8ef39122c8fff2878ba5e6b3a7409 translated
#[test]
fn secure_send_channel_exception() {
    let h = harness();
    process(&h, &["@sendchannel_sec=n", "@sendchannel_sec:123=n"]);
    assert!(
        h.service
            .permissions()
            .can_chat(123, "Hello world".into())
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_chat(456, "Hello world".into())
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImRestrictionTests.cs::SendImRestrictionTests.CanSendIM::test c63ab3a41b6b302e7c84c54374c7193335840bafc40f2d0f2b1c3a2787b26203 translated
#[test]
fn send_im_restriction() {
    let h = harness();
    process(&h, &["@sendim=n"]);
    assert!(
        !h.service
            .permissions()
            .can_send_im("Hello".into(), Some(Some(guid(USER_1))), None)
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_send_im(
                "Hello".into(),
                Some(Some(guid(USER_1))),
                Some("Group Name".into())
            )
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImSecRestrictionTests.cs::SendImSecRestrictionTests.CanSendIM_Secure::test 65422234501bcbf151f27e0d45c74726e670665f39d90df23396f79450ba2b91 translated
#[test]
fn secure_send_im_user_exceptions_are_sender_scoped() {
    let h = harness();
    process(&h, &["@sendim_sec=n", &format!("@sendim:{USER_1}=add")]);
    block_on(h.process_from(&format!("@sendim:{USER_2}=add"), SENDER_2, "Sender 2")).unwrap();
    assert!(send_im(&h, USER_1, None));
    assert!(!send_im(&h, USER_2, None));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImSecRestrictionTests.cs::SendImSecRestrictionTests.CanSendIM_Secure_Group::test 4ed2e6416a86eb2406e20bbb7e60a380de25577ad034ba613530ed28f6001df9 translated
#[test]
fn secure_send_im_group_exception() {
    let h = harness();
    process(&h, &["@sendim_sec=n", "@sendim:Group Name=add"]);
    block_on(h.process_from("@sendim:allgroups=add", SENDER_2, "Sender 2")).unwrap();
    assert!(send_im(&h, USER_1, Some("Group Name")));
    assert!(!send_im(&h, USER_1, Some("Another Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImSecRestrictionTests.cs::SendImSecRestrictionTests.CanSendIM_Secure_AllGroups::test a4b699c9ada01ca4ce4d535739178e5310affa938d02dfaede6d034488d24f5f translated
#[test]
fn secure_send_im_all_groups_exception() {
    let h = harness();
    process(&h, &["@sendim_sec=n", "@sendim:allgroups=add"]);
    assert!(send_im(&h, USER_1, Some("Group Name")));
    assert!(send_im(&h, USER_1, Some("Another Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImToRestrictionTests.cs::SendImToRestrictionTests.CanSendIMTo::test 38258cda1081160b6b34f8e909adbc683a0f08efce8c63066bcac09835e5cdcc translated
#[test]
fn send_im_to_one_user() {
    let h = harness();
    process(&h, &[&format!("@sendimto:{USER_1}=n")]);
    assert!(!send_im(&h, USER_1, None));
    assert!(send_im(&h, USER_2, None));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImToRestrictionTests.cs::SendImToRestrictionTests.CanSendIMTo_Group::test 1e12f7e3dbbee7d8dfb757fc8797644a353dfaa995e343e59124aa85126d70aa translated
#[test]
fn send_im_to_one_group() {
    let h = harness();
    process(&h, &["@sendimto:First Group=n"]);
    assert!(!send_im(&h, USER_1, Some("First Group")));
    assert!(send_im(&h, USER_2, Some("Second Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/SendImToRestrictionTests.cs::SendImToRestrictionTests.CanSendIMTo_AllGroups::test bc9b87ab7b171c76987ddaf94f05c0ac2ad8dc0c1f24f5dfce2f4125e7b28df5 translated
#[test]
fn send_im_to_all_groups() {
    let h = harness();
    process(&h, &["@sendimto:allgroups=n"]);
    assert!(!send_im(&h, USER_1, Some("First Group")));
    assert!(!send_im(&h, USER_2, Some("Second Group")));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShareRestrictionTests.cs::ShareRestrictionTests.CanShare::test 23052e5792ff72624d45b54ccfd02fa5d8025d977010f1e8d34a90d27a4d0e29 translated
#[test]
fn share_restriction() {
    let h = harness();
    process(&h, &["@share=n"]);
    assert!(!h.service.permissions().can_share(None).unwrap());
    assert!(
        !h.service
            .permissions()
            .can_share(Some(Some(guid(SENDER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShareSecRestrictionTests.cs::ShareSecRestrictionTests.CanShare_Secure_Default::test 6d61bafb190791ceaccb6c46cde3adf5b5479e6b5e76bafeadd0942400389248 translated
#[test]
fn secure_share_default() {
    let h = harness();
    process(&h, &["@share_sec=n"]);
    assert!(!h.service.permissions().can_share(None).unwrap());
    assert!(
        !h.service
            .permissions()
            .can_share(Some(Some(guid(USER_1))))
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_share(Some(Some(guid(USER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShareSecRestrictionTests.cs::ShareSecRestrictionTests.CanShare_Secure::test e1aed5b3b8efccef47094788c3221e20240c671c1004d6d6bd899e5d9ddd51fa translated
#[test]
fn secure_share_exceptions_are_sender_scoped() {
    let h = harness();
    process(&h, &["@share_sec=n", &format!("@share:{USER_1}=add")]);
    block_on(h.process_from(&format!("@share:{USER_2}=add"), SENDER_2, "Sender 2")).unwrap();
    assert!(!h.service.permissions().can_share(None).unwrap());
    assert!(
        h.service
            .permissions()
            .can_share(Some(Some(guid(USER_1))))
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_share(Some(Some(guid(USER_2))))
            .unwrap()
    );
}

fn hover(h: &RlvHarness, location: HoverTextLocation, object: &str) -> bool {
    h.service
        .permissions()
        .can_show_hover_text(location, Some(Some(guid(object))))
        .unwrap()
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowHoverTextAllRestrictionTests.cs::ShowHoverTextAllRestrictionTests.CanShowHoverTextAll::test 6a855738e87477d31dc7867d0c75ba1bf563e2b1e180f54759657a58b7da9793 translated
#[test]
fn show_hover_text_all_restriction() {
    let h = harness();
    process(&h, &["@showhovertextall=n"]);
    assert!(!hover(&h, HoverTextLocation::World, USER_1));
    assert!(!hover(&h, HoverTextLocation::Hud, USER_1));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowHoverTextHudRestrictionTests.cs::ShowHoverTextHudRestrictionTests.CanShowHoverTextHud::test 9d08e2a3eb303b14c4b222cae5d52537e81a7d9cfc9fcfe9625d513b6311a6ed translated
#[test]
fn show_hover_text_hud_restriction() {
    let h = harness();
    process(&h, &["@showhovertexthud=n"]);
    for object in [USER_1, USER_2] {
        assert!(hover(&h, HoverTextLocation::World, object));
        assert!(!hover(&h, HoverTextLocation::Hud, object));
    }
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowHoverTextRestrictionTests.cs::ShowHoverTextRestrictionTests.CanShowHoverText::test 5642102d6832b227c37c14d0fbfc30921022c5789b811021805db6f3a2120f36 translated
#[test]
fn show_hover_text_one_object_restriction() {
    let h = harness();
    process(&h, &[&format!("@showhovertext:{USER_1}=n")]);
    assert!(!hover(&h, HoverTextLocation::World, USER_1));
    assert!(!hover(&h, HoverTextLocation::Hud, USER_1));
    assert!(hover(&h, HoverTextLocation::World, USER_2));
    assert!(hover(&h, HoverTextLocation::Hud, USER_2));
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowHoverTextWorldRestrictionTests.cs::ShowHoverTextWorldRestrictionTests.CanShowHoverTextWorld::test 1be82408fbc87f1525dc7652e01fbbc17a993b70a2268f0b742d035b37cbf70c translated
#[test]
fn show_hover_text_world_restriction() {
    let h = harness();
    process(&h, &["@showhovertextworld=n"]);
    for object in [USER_1, USER_2] {
        assert!(!hover(&h, HoverTextLocation::World, object));
        assert!(hover(&h, HoverTextLocation::Hud, object));
    }
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowNameTagsRestrictionTests.cs::ShowNameTagsRestrictionTests.CanShowNameTags::test 74e8a6aefdefb9eb41509f6b4438e6854e5ad0ace38ab663f445aae484e94e22 translated
#[test]
fn show_name_tags_restriction() {
    let h = harness();
    process(&h, &["@shownametags=n"]);
    assert!(!h.service.permissions().can_show_name_tags(None).unwrap());
    assert!(
        !h.service
            .permissions()
            .can_show_name_tags(Some(Some(guid(SENDER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowNamesRestrictionTests.cs::ShowNamesRestrictionTests.CanShowNames::test c44fe98d881a89af5db856e98f7bd7480d9bfb4378730002e518a7d1da412812 translated
#[test]
fn show_names_restriction() {
    let h = harness();
    process(&h, &["@shownames=n"]);
    assert!(!h.service.permissions().can_show_names(None).unwrap());
    assert!(
        !h.service
            .permissions()
            .can_show_names(Some(Some(guid(SENDER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowNamesSecRestrictionTests.cs::ShowNamesSecRestrictionTests.CanShowNames_Secure_Default::test 98d2c84d2f226fbb4b03c365f3ab007142d87b1980dda3666ce5ec36909fc599 translated
#[test]
fn secure_show_names_default() {
    let h = harness();
    process(&h, &["@shownames_sec=n"]);
    assert!(!h.service.permissions().can_show_names(None).unwrap());
    assert!(
        !h.service
            .permissions()
            .can_show_names(Some(Some(guid(USER_1))))
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_show_names(Some(Some(guid(USER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowNamesSecRestrictionTests.cs::ShowNamesSecRestrictionTests.CanShowNames_Secure::test 90ae29916dc2b60cd3de336e4a37683de8967f448fef26af360e3d24278773d3 translated
#[test]
fn secure_show_names_exceptions_are_sender_scoped() {
    let h = harness();
    process(
        &h,
        &["@shownames_sec=n", &format!("@shownames:{USER_1}=add")],
    );
    block_on(h.process_from(&format!("@shownames:{USER_2}=add"), SENDER_3, "Sender 2")).unwrap();
    assert!(!h.service.permissions().can_show_names(None).unwrap());
    assert!(
        h.service
            .permissions()
            .can_show_names(Some(Some(guid(USER_1))))
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_show_names(Some(Some(guid(USER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/ShowNamesSecRestrictionTests.cs::ShowNamesSecRestrictionTests.CanShowNames_Secure_Except::test 457772321f7fd1ea88a279e99a4b0a955e462652bac1fb7953b8455f3d67a155 translated
#[test]
fn secure_show_names_direct_exception() {
    let h = harness();
    process(
        &h,
        &["@shownames_sec=n", &format!("@shownames_sec:{USER_1}=n")],
    );
    assert!(!h.service.permissions().can_show_names(None).unwrap());
    assert!(
        h.service
            .permissions()
            .can_show_names(Some(Some(guid(USER_1))))
            .unwrap()
    );
    assert!(
        !h.service
            .permissions()
            .can_show_names(Some(Some(guid(USER_2))))
            .unwrap()
    );
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/StartImRestrictionTests.cs::StartImRestrictionTests.CanStartIM::test cc8318d5233b947ca96939369de3a2fdc2c21468cc13a87c87908126c6e45500 translated
#[test]
fn start_im_restriction() {
    let h = harness();
    process(&h, &["@startim=n"]);
    assert!(!h.service.permissions().can_start_im(guid(USER_1)).unwrap());
}

// parity-case: LibreMetaverse.Tests/RLV/Restrictions/StartImToRestrictionTests.cs::StartImToRestrictionTests.CanStartIMTo::test 0c7e19de2ecf94a6db09ee409ff88ff503e02d8dd8f7f11f427cebc51a3ac09f translated
#[test]
fn start_im_to_one_user() {
    let h = harness();
    process(&h, &[&format!("@startimto:{USER_2}=n")]);
    assert!(h.service.permissions().can_start_im(guid(USER_1)).unwrap());
    assert!(!h.service.permissions().can_start_im(guid(USER_2)).unwrap());
}
