#![cfg_attr(not(feature = "std"), no_std)]
extern crate rosc;
use rosc::{OscArray, OscType};
#[cfg(feature = "std")]
use rosc::{OscBundle, OscColor, OscMessage, OscMidiMessage, OscPacket, OscTime};
#[cfg(feature = "std")]
use std::{
convert::TryFrom,
time::{Duration, SystemTime, UNIX_EPOCH},
};
#[cfg(feature = "std")]
#[test]
fn test_osc_array_from_iter() {
use std::iter::FromIterator;
let iter = (0..3).map(OscType::Int);
let osc_arr = OscArray::from_iter(iter);
assert_eq!(
osc_arr,
OscArray {
content: vec![OscType::Int(0), OscType::Int(1), OscType::Int(2)]
}
);
}
#[cfg(feature = "std")]
#[cfg(target_os = "windows")]
const TOLERANCE_NANOS: u64 = 100;
#[cfg(feature = "std")]
#[cfg(not(target_os = "windows"))]
const TOLERANCE_NANOS: u64 = 5;
#[cfg(feature = "std")]
fn assert_eq_system_times(a: SystemTime, b: SystemTime) {
let difference = if a < b {
b.duration_since(a).unwrap()
} else {
a.duration_since(b).unwrap()
};
let tolerance = Duration::from_nanos(TOLERANCE_NANOS);
if difference > tolerance {
panic!(
"the fractional seconds components of {:?} and {:?} vary more than the required tolerance of {:?}",
a, b, tolerance,
);
}
}
#[cfg(feature = "std")]
#[test]
fn system_times_can_be_converted_to_and_from_osc() {
let times = vec![UNIX_EPOCH, SystemTime::now()];
for time in times {
for i in 0..1000 {
let time = time + Duration::from_nanos(1) * i;
assert_eq_system_times(time, SystemTime::from(OscTime::try_from(time).unwrap()));
}
}
}
#[cfg(feature = "std")]
#[test]
fn osc_time_cannot_represent_times_before_1970_01_01() {
assert!(OscTime::try_from(UNIX_EPOCH - Duration::from_secs(1)).is_err())
}
#[cfg(feature = "std")]
#[test]
fn osc_times_can_be_converted_to_and_from_system_times() {
const UNIX_OFFSET: u64 = 2_208_988_800;
let mut times = vec![];
for seconds in vec![
UNIX_OFFSET as u32,
UNIX_OFFSET as u32 + 1,
UNIX_OFFSET as u32 + 2,
UNIX_OFFSET as u32 + 3,
u32::MAX - 1,
u32::MAX,
] {
let fractional_max = 100;
for fractional in 0..fractional_max {
times.push((seconds, fractional));
times.push((seconds, fractional_max - fractional));
}
}
for osc_time in times.into_iter().map(OscTime::from) {
assert_eq_osc_times(
osc_time,
OscTime::try_from(SystemTime::from(osc_time)).unwrap(),
);
}
}
#[cfg(feature = "std")]
fn assert_eq_osc_times(a: OscTime, b: OscTime) {
const TWO_POW_32: f64 = (u32::MAX as f64) + 1.0;
const NANOS_PER_SECOND: f64 = 1.0e9;
let tolerance_fractional_seconds =
((TOLERANCE_NANOS as f64 * TWO_POW_32) / NANOS_PER_SECOND).round() as i64;
assert_eq!(
a.seconds, b.seconds,
"the seconds components of {:?} and {:?} are different",
a, b
);
if (a.fractional as i64 - b.fractional as i64).abs() > tolerance_fractional_seconds {
panic!(
"the fractional seconds components of {:?} and {:?} vary more than the required tolerance of {} fractional seconds",
a, b, tolerance_fractional_seconds,
);
}
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_int() {
let arg = OscType::Int(123);
assert_eq!(arg.to_string(), "(i) 123".to_string());
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_float() {
let arg = OscType::Float(123.4);
assert_osc_type_display_eq(&arg, "(f) 123.4");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_string() {
let arg = OscType::String("abc".to_string());
assert_osc_type_display_eq(&arg, "(s) abc");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_blob() {
let arg = OscType::Blob(vec![0, 1, 2, 255]);
assert_osc_type_display_eq(&arg, "(b) 0x000102FF");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_time() {
let arg = OscType::Time(OscTime::try_from(UNIX_EPOCH).unwrap());
assert_osc_type_display_eq(&arg, "(t) 1970-01-01T00:00:00.000000000Z");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_long() {
let arg = OscType::Long(123);
assert_osc_type_display_eq(&arg, "(h) 123");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_double() {
let arg = OscType::Double(123.4);
assert_osc_type_display_eq(&arg, "(d) 123.4");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_char() {
let arg = OscType::Char('a');
assert_osc_type_display_eq(&arg, "(c) a");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_color() {
let arg = OscType::Color(OscColor {
red: 255,
green: 127,
blue: 63,
alpha: 255,
});
assert_osc_type_display_eq(&arg, "(r) {255,127,63,255}");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_midi() {
let arg = OscType::Midi(OscMidiMessage {
port: 3,
status: 0xF0,
data1: 0x12,
data2: 0x34,
});
assert_osc_type_display_eq(&arg, "(m) {port:3, status:0xF0, data:0x1234}");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_bool() {
let arg_true = OscType::Bool(true);
assert_osc_type_display_eq(&arg_true, "(T)");
let arg_false = OscType::Bool(false);
assert_osc_type_display_eq(&arg_false, "(F)");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_array() {
let arg = OscType::Array(OscArray {
content: vec![
OscType::Int(123),
OscType::Float(123.4),
OscType::String("abc".to_string()),
],
});
assert_osc_type_display_eq(&arg, "[(i) 123,(f) 123.4,(s) abc]");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_nil() {
let arg = OscType::Nil;
assert_osc_type_display_eq(&arg, "(N)");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_type_infinitum() {
let arg = OscType::Inf;
assert_osc_type_display_eq(&arg, "(I)");
}
#[cfg(feature = "std")]
#[test]
fn display_osc_packet_message() {
let packet = OscPacket::Message(OscMessage {
addr: "/oscillator/1/frequency".to_string(),
args: vec![OscType::Float(123.4), OscType::Bool(true)],
});
assert_eq!(
packet.to_string(),
"/oscillator/1/frequency, (f) 123.4, (T)"
)
}
#[cfg(feature = "std")]
#[test]
fn display_osc_packet_bundle() {
let timetag = OscTime::try_from(UNIX_EPOCH).unwrap();
let packet = OscPacket::Bundle(OscBundle {
timetag,
content: vec![
OscPacket::Message(OscMessage {
addr: "/oscillator/1/frequency".to_string(),
args: vec![OscType::Float(123.4), OscType::Bool(true)],
}),
OscPacket::Message(OscMessage {
addr: "/oscillator/2/frequency".to_string(),
args: vec![OscType::Float(246.8), OscType::Bool(false)],
}),
],
});
assert_eq!(
packet.to_string(),
"#bundle 1970-01-01T00:00:00.000000000Z { /oscillator/1/frequency, (f) 123.4, (T); \
/oscillator/2/frequency, (f) 246.8, (F) }"
)
}
#[cfg(feature = "std")]
#[test]
fn display_osc_packet_nested_bundle() {
let timetag = OscTime::try_from(UNIX_EPOCH).unwrap();
let packet = OscPacket::Bundle(OscBundle {
timetag,
content: vec![
OscPacket::Message(OscMessage {
addr: "/oscillator/1/frequency".to_string(),
args: vec![OscType::Float(123.4), OscType::Bool(true)],
}),
OscPacket::Message(OscMessage {
addr: "/oscillator/2/frequency".to_string(),
args: vec![OscType::Float(246.8), OscType::Bool(false)],
}),
OscPacket::Bundle(OscBundle {
timetag,
content: vec![OscPacket::Message(OscMessage {
addr: "/oscillator/3/frequency".to_string(),
args: vec![OscType::Float(123.4), OscType::Bool(true)],
})],
}),
],
});
assert_eq!(
packet.to_string(),
"#bundle 1970-01-01T00:00:00.000000000Z { /oscillator/1/frequency, (f) 123.4, (T); \
/oscillator/2/frequency, (f) 246.8, (F); #bundle 1970-01-01T00:00:00.000000000Z \
{ /oscillator/3/frequency, (f) 123.4, (T) } }"
)
}
#[cfg(feature = "std")]
fn assert_osc_type_display_eq(arg: &OscType, expected: &str) {
assert_eq!(arg.to_string(), expected.to_string());
}