oc2_hlapi_v2 0.2.0

A client for the new version of OpenComputers II's HLAPI
Documentation
//! Device wrappers: `DeviceBase`, `Device`, `GenericDevice`.

mod common;

use std::thread;

use common::*;
use oc2_hlapi_v2::client::{Device, DeviceBase, HlapiClientError};
use oc2_hlapi_v2::devices::GenericDevice;
use serde_json::json;

#[test]
fn wrappers_know_their_type_and_uuid() {
    assert_eq!(Redstone::TYPE, "redstone");
    assert_eq!(Storage::TYPE, "storage");
    assert_eq!(GenericDevice::TYPE, "");
    let (client, _s) = client_silent();
    let d = Redstone::new(client, id(77)).unwrap();
    assert_eq!(d.uuid(), id(77));
    assert_eq!(d.uuid_base(), id(77));
}

#[test]
fn typed_wrapper_methods_send_the_right_calls() {
    let (client, s) = client_serving(|req, _, host| {
        let reply = match req["data"]["name"].as_str().unwrap() {
            "getInput" => result_reply(req, 1, json!(11)),
            _ => empty_result_reply(req, 1),
        };
        host.reply(&reply);
    });
    let d = Redstone::new(client, id(4)).unwrap();
    assert_eq!(d.get_input("left").unwrap(), 11);
    d.set_output("back", 15).unwrap();
    let reqs = s.requests();
    assert_eq!(reqs[0]["data"]["name"], "getInput");
    assert_eq!(reqs[0]["data"]["parameters"], json!(["left"]));
    assert_eq!(reqs[1]["data"]["name"], "setOutput");
    assert_eq!(reqs[1]["data"]["parameters"], json!(["back", 15]));
    assert_eq!(reqs[1]["data"]["deviceId"], json!(id(4)));
}

#[test]
fn generic_device_call_matches_the_trait_method() {
    let (client, s) = client_serving(|req, _, host| host.reply(&result_reply(req, 1, json!("ok"))));
    let d = GenericDevice::new(client, id(3)).unwrap();
    let inherent: (String, _) = d.call("m", &[&1], &[]).unwrap();
    let via_trait: (String, _) = DeviceBase::call(&d, "m", &[&1], &[]).unwrap();
    assert_eq!(inherent.0, via_trait.0);
    let reqs = s.requests();
    assert_eq!(reqs[0]["data"], reqs[1]["data"]);
}

#[test]
fn list_methods_returns_the_hosts_description() {
    let (client, s) = client_serving(|req, _, host| {
        host.reply(&json!({
            "type": "methods", "id": req["id"], "gen": 1,
            "data": [{
                "name": "getInput", "returnType": "int", "description": "d",
                "parameters": [{"name": "side", "type": "string"}],
            }, {"name": "other"}],
        }));
    });
    let d = Redstone::new(client, id(4)).unwrap();
    let methods = d.list_methods().unwrap();
    assert_eq!(methods.len(), 2);
    assert_eq!(methods[0].name, "getInput");
    assert_eq!(methods[0].return_type.as_deref(), Some("int"));
    assert_eq!(
        methods[0].parameters.as_ref().unwrap()[0].name.as_deref(),
        Some("side")
    );
    let req = &s.requests()[0];
    assert_eq!(req["type"], "methods");
    assert_eq!(req["data"], json!(id(4)));
}

#[test]
fn list_methods_errors() {
    let (client, _s) =
        client_serving(|req, _, host| host.reply(&error_reply(req, 1, "no such device")));
    let err = Redstone::new(client, id(4))
        .unwrap()
        .list_methods()
        .unwrap_err();
    assert!(matches!(&err, HlapiClientError::Hlapi(m) if m == "no such device"));

    let (client, _s) = client_serving(|req, _, host| host.reply(&result_reply(req, 1, json!(1))));
    let err = Redstone::new(client, id(4))
        .unwrap()
        .list_methods()
        .unwrap_err();
    assert!(
        matches!(err, HlapiClientError::UnexpectedResponseType),
        "{err:?}"
    );
}

#[test]
fn wrappers_are_cheap_handles_on_the_same_connection() {
    let (client, s) = client_serving(simple_host);
    let a = Redstone::new(client.clone(), id(1)).unwrap();
    let b = a.clone();
    let handle = thread::spawn(move || b.get_input("left").unwrap());
    assert_eq!(a.get_input("right").unwrap(), 7);
    assert_eq!(handle.join().unwrap(), 7);
    assert_eq!(s.total(), 2);
    assert!(format!("{a:?}").contains("Redstone"));
}

#[test]
fn the_client_of_a_found_wrapper_is_the_client_that_found_it() {
    let (client, s) = client_serving(simple_host);
    let d: Redstone = client.find_device_by_type().unwrap().unwrap();
    d.get_input("left").unwrap();
    assert_eq!(s.count("list"), 1);
    assert_eq!(s.count("invoke"), 1);
    assert_eq!(d.client().list_devices().unwrap().len(), 2);
    assert_eq!(s.count("list"), 1, "shared cache");
}