rstango 0.4.0

Implementation of the Tango distributed control system
Documentation
//! What the integration tests share: a server `Test/test` served by a [`TestContext`],
//! and what its database was told.

#![allow(dead_code, unused_imports)]

use tango::server::ServerBuilder;
use tango::testing::{TestDatabase, TestContext};


/// A context whose database defines the server `Test/test` with those devices, of
/// those classes, and has forgotten being told so.
pub fn test_context(listed: &[(&str, &str)]) -> TestContext {
    let ctx = TestContext::new().unwrap();
    ctx.database().add_server("Test/test", listed).unwrap();
    ctx.test_database().clear_log();
    ctx
}

/// The server `Test/test`, to be served by a context, see [`test_context`], its devices
/// being reached directly by this process if `local`, and through the backend otherwise,
/// see [`ServerBuilder::local`].
pub fn test_server(local: bool) -> ServerBuilder {
    ServerBuilder::new("Test", "test").local(local)
}

/// A test run twice, as a module of two tests: `local`, the devices of the server being
/// reached directly, as this process does, and `wire`, through the backend, as another
/// process does, which is what checks the protocol along with the server. The function
/// is given which one it is, which it gives the server, see [`test_server`].
///
/// The attributes of the function, its documentation included, are the ones of both
/// tests, which is how both are ignored under Miri for instance.
macro_rules! local_and_wire {
    ($(#[$meta:meta])* fn $name:ident($local:ident: bool) $body:block) => {
        mod $name {

            use super::*;

            fn run($local: bool) $body

            #[test]
            $(#[$meta])*
            fn local() {
                run(true)
            }

            #[test]
            $(#[$meta])*
            fn wire() {
                run(false)
            }

        }
    };
}

pub(crate) use local_and_wire;

/// Whether the device of that name is reached directly by this process, see
/// [`TestContext::is_local`].
pub fn is_local(ctx: &TestContext, name: &str) -> bool {
    ctx.is_local(name).unwrap()
}

/// The commands the database was sent.
pub fn commands(database: &TestDatabase) -> Vec<String> {
    database.log().into_iter().map(|(name, _)| name).collect()
}

/// The devices exported, in order.
pub fn exported(database: &TestDatabase) -> Vec<String> {
    database.log().into_iter()
        .filter(|(name, _)| name == "DbExportDevice" || name == "DbExportServer")
        .flat_map(|(_, input)| Vec::<String>::try_from(input).unwrap().into_iter().step_by(5))
        .collect()
}

/// The devices unexported, in order, a whole server being given as its name.
pub fn unexported(database: &TestDatabase) -> Vec<String> {
    database.log().into_iter()
        .filter(|(name, _)| name == "DbUnExportDevice" || name == "DbUnExportServer")
        .map(|(_, input)| String::try_from(input).unwrap())
        .collect()
}