use super::*;
use crate::Client;
use crate::ClientOptions;
use crate::Error;
use crate::NotificationHandler;
use crate::PortId;
use crate::PORT_NAME_SIZE;
use std::collections::HashSet;
use std::sync::mpsc;
use std::sync::Mutex;
use std::{thread, time};
fn open_test_client(name: &str) -> Client {
Client::new(name, ClientOptions::NO_START_SERVER).unwrap().0
}
#[test]
fn client_port_can_register_port() {
let c = open_test_client("cp_can_register_port");
c.register_port("cpcrp_a", AudioIn::default()).unwrap();
}
#[test]
fn client_port_register_port_enforces_unique_names() {
let pname = "cprpeun_a";
let c = open_test_client("cp_can_register_port");
c.register_port(pname, AudioIn::default()).unwrap();
assert_eq!(
c.register_port(pname, AudioIn::default()).err(),
Some(Error::PortRegistrationError(pname.to_string()))
);
}
#[test]
fn client_port_register_port_enforces_name_length() {
let c = open_test_client("cp_can_register_port");
let pname = (0..=*PORT_NAME_SIZE)
.map(|_| "a")
.collect::<Vec<&str>>()
.join("_");
assert_eq!(
c.register_port(&pname, AudioIn::default()).err(),
Some(Error::PortRegistrationError(pname.to_string()))
);
}
#[test]
fn client_port_can_request_monitor_by_name() {
let c = open_test_client("cp_can_request_monitor_by_name");
let p = c.register_port("cpcrmbn_a", AudioIn::default()).unwrap();
c.request_monitor_by_name(&p.name().unwrap(), true).unwrap();
c.request_monitor_by_name(&p.name().unwrap(), false)
.unwrap();
}
#[test]
fn client_port_can_get_port_by_name() {
let c = open_test_client("cp_can_get_port_by_name");
let p = c.register_port("named_port", AudioIn::default()).unwrap();
let _p = c.port_by_name(&p.name().unwrap()).unwrap();
}
pub struct PortIdHandler {
pub reg_tx: Mutex<mpsc::SyncSender<PortId>>,
}
impl NotificationHandler for PortIdHandler {
fn port_registration(&mut self, _: &Client, pid: PortId, is_registered: bool) {
if is_registered {
self.reg_tx.lock().unwrap().send(pid).unwrap()
}
}
}
#[test]
fn client_port_can_get_port_by_id() {
let (client_name, port_name) = ("cp_can_get_port_by_id", "cp_registered_port_name");
let (reg_tx, reg_rx) = mpsc::sync_channel(200);
let h = PortIdHandler {
reg_tx: Mutex::new(reg_tx),
};
let c = open_test_client(client_name);
let ac = c.activate_async(h, ()).unwrap();
let _pa = ac
.as_client()
.register_port(port_name, AudioIn::default())
.unwrap();
let c = ac.deactivate().unwrap().0;
let mut registered_ports = reg_rx
.iter()
.flat_map(|i| c.port_by_id(i))
.map(|p| p.name().unwrap());
let port_name = format!("{client_name}:{port_name}");
assert!(registered_ports.any(|n| n == port_name));
}
#[test]
fn client_port_fails_to_nonexistant_port() {
let c = open_test_client("cp_can_request_monitor_by_name");
let p = c.register_port("cpcrmbn_a", AudioIn::default()).unwrap();
let _p = c.port_by_name(&p.name().unwrap()).unwrap();
}
#[test]
fn client_port_recognizes_my_ports() {
let ca = open_test_client("cp_cprmp_ca");
let cb = open_test_client("cp_cprmp_cb");
let first = ca.register_port("cpcprmp_pa", AudioIn::default()).unwrap();
let second = cb.register_port("cpcprmp_pb", AudioIn::default()).unwrap();
let first_alt = ca.port_by_name(&first.name().unwrap()).unwrap();
let second_alt = ca.port_by_name(&second.name().unwrap()).unwrap();
assert!(ca.is_mine(&first));
assert!(ca.is_mine(&first_alt));
assert!(!ca.is_mine(&second));
assert!(!ca.is_mine(&second_alt));
}
#[test]
fn client_port_can_connect_ports() {
let client = open_test_client("client_port_ccp");
let in_p = client.register_port("inp", AudioIn::default()).unwrap();
let out_p = client.register_port("outp", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client.as_client().connect_ports(&out_p, &in_p).unwrap();
}
#[test]
fn client_port_can_connect_ports_by_name() {
let client = open_test_client("client_port_ccpbn");
let _in_p = client.register_port("inp", AudioIn::default()).unwrap();
let _out_p = client.register_port("outp", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client
.as_client()
.connect_ports_by_name("client_port_ccpbn:outp", "client_port_ccpbn:inp")
.unwrap();
}
#[test]
fn client_port_can_connect_unowned_ports() {
let client = open_test_client("client_port_ccup");
let connector = open_test_client("client_port_ccup_conn");
let _in_p = client.register_port("inp", AudioIn::default()).unwrap();
let _out_p = client.register_port("outp", AudioOut::default()).unwrap();
let _client = client.activate_async((), ()).unwrap();
connector
.connect_ports_by_name("client_port_ccup:outp", "client_port_ccup:inp")
.unwrap();
}
#[test]
fn client_port_cant_connect_inactive_client() {
let client = open_test_client("client_port_ccic");
let other = open_test_client("client_port_ccic_other");
let in_p = other
.register_port("inp", AudioIn::default())
.unwrap()
.name()
.unwrap();
let out_p = other
.register_port("outp", AudioOut::default())
.unwrap()
.name()
.unwrap();
assert_eq!(
client.connect_ports_by_name(&in_p, &out_p).err(),
Some(Error::PortConnectionError(in_p, out_p))
);
}
#[test]
fn client_port_recognizes_already_connected_ports() {
let client = open_test_client("client_port_racp");
let in_p = client.register_port("conna", AudioIn::default()).unwrap();
let out_p = client.register_port("connb", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client.as_client().connect_ports(&out_p, &in_p).unwrap();
assert_eq!(
client.as_client().connect_ports(&out_p, &in_p),
Err(Error::PortAlreadyConnected(
out_p.name().unwrap(),
in_p.name().unwrap(),
))
);
}
#[test]
fn client_port_fails_to_connect_nonexistant_ports() {
let client = open_test_client("client_port_ftcnp")
.activate_async((), ())
.unwrap();
assert_eq!(
client
.as_client()
.connect_ports_by_name("doesnt_exist", "also_no_exist"),
Err(Error::PortConnectionError(
"doesnt_exist".to_string(),
"also_no_exist".to_string(),
))
);
}
#[test]
fn client_port_can_disconnect_port_from_all() {
let client = open_test_client("client_port_cdpfa");
let in_p = client.register_port("conna", AudioIn::default()).unwrap();
let out_p = client.register_port("connb", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client.as_client().connect_ports(&out_p, &in_p).unwrap();
client.as_client().disconnect(&in_p).unwrap();
}
#[test]
fn client_port_can_disconnect_ports() {
let client = open_test_client("client_port_cdp");
let in_p = client.register_port("conna", AudioIn::default()).unwrap();
let out_p = client.register_port("connb", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client.as_client().connect_ports(&out_p, &in_p).unwrap();
client.as_client().disconnect_ports(&out_p, &in_p).unwrap();
}
#[test]
fn client_port_can_disconnect_ports_by_name() {
let client = open_test_client("client_port_cdpbn");
let in_p = client.register_port("conna", AudioIn::default()).unwrap();
let out_p = client.register_port("connb", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client
.as_client()
.connect_ports_by_name(&out_p.name().unwrap(), &in_p.name().unwrap())
.unwrap();
client
.as_client()
.disconnect_ports_by_name(&out_p.name().unwrap(), &in_p.name().unwrap())
.unwrap();
}
#[test]
fn client_port_can_disconnect_unowned_ports() {
let client = open_test_client("client_port_cdup");
let disconnector = open_test_client("client_port_cdup_disc");
let in_p = client.register_port("conna", AudioIn::default()).unwrap();
let out_p = client.register_port("connb", AudioOut::default()).unwrap();
let client = client.activate_async((), ()).unwrap();
client
.as_client()
.connect_ports_by_name(&out_p.name().unwrap(), &in_p.name().unwrap())
.unwrap();
disconnector
.disconnect_ports_by_name(&out_p.name().unwrap(), &in_p.name().unwrap())
.unwrap();
}
#[test]
fn client_port_can_get_existing_ports() {
let client = open_test_client("client_port_cgep");
let port_getter = open_test_client("client_port_cgep_getter");
let in_p = client.register_port("conna", AudioIn::default()).unwrap();
let out_p = client.register_port("connb", AudioOut::default()).unwrap();
let known_ports = [
in_p.name().unwrap(),
out_p.name().unwrap(),
"system:playback_2".to_string(),
"system:playback_1".to_string(),
"system:capture_1".to_string(),
"system:capture_2".to_string(),
];
let exp: HashSet<String> = known_ports.iter().cloned().collect();
let got: HashSet<String> = port_getter
.ports(None, None, PortFlags::empty())
.into_iter()
.collect();
let intersection: HashSet<String> = exp.intersection(&got).cloned().collect();
assert_eq!(exp, intersection);
}
#[test]
fn client_port_can_get_port_by_name_pattern() {
let client = open_test_client("client_port_cgpbnp");
let known_ports = [
"system:playback_2".to_string(),
"system:capture_2".to_string(),
];
let exp: HashSet<String> = known_ports.iter().cloned().collect();
let got: HashSet<String> = client
.ports(Some("2"), None, PortFlags::empty())
.into_iter()
.collect();
assert_eq!(got, exp);
}
#[test]
fn client_port_can_get_port_by_type_pattern() {
let c_name = "client_port_cgpbtp";
let p_name = "midip";
let full_name = format!("{c_name}:{p_name}");
let client = open_test_client(c_name);
let _p = client.register_port(p_name, MidiIn::default());
thread::sleep(time::Duration::from_millis(400));
let ports = client.ports(None, Some("midi"), PortFlags::empty());
assert!(
ports.contains(&full_name),
"{:?} does not contain {}",
&ports,
&full_name
);
}