use quercus_core::{PixelFormat, Rational, SampleFormat, TimeRange, TimeRangeList};
#[test]
fn rational_reduction_and_sentinel() {
assert_eq!(Rational::new(2, 4), Rational::new(1, 2));
assert_eq!(Rational::new(2, 4).numerator(), 1);
assert_eq!(Rational::new(2, 4).denominator(), 2);
assert_eq!(Rational::new(1, -2), Rational::new(-1, 2));
assert_eq!(Rational::new(1, -2).numerator(), -1);
assert_eq!(Rational::new(1, -2).denominator(), 2);
let n = Rational::new(0, 0);
assert!(n.is_null());
assert!(n.is_nan());
assert_eq!(n, Rational::NULL);
let z = Rational::new(0, 5);
assert!(z.is_null());
assert!(!z.is_nan());
assert_eq!(z, Rational::new(0, 1));
assert_eq!(Rational::NULL, Rational::new(0, 0));
}
#[test]
fn rational_arithmetic_video_rates() {
assert_eq!(
Rational::new(1001, 30000) * Rational::new(30000, 1001),
Rational::new(1, 1)
);
assert_eq!(
Rational::new(1, 3) + Rational::new(1, 6),
Rational::new(1, 2)
);
assert_eq!(
Rational::new(1, 2) - Rational::new(1, 3),
Rational::new(1, 6)
);
assert_eq!(
Rational::new(2, 3) * Rational::new(3, 4),
Rational::new(1, 2)
);
let d = Rational::new(1, 1) / Rational::new(0, 1);
assert!(d.is_nan());
assert!(d.is_null());
assert_eq!(d, Rational::NULL);
assert_eq!(Rational::NULL + Rational::new(1, 2), Rational::NULL);
assert_eq!(Rational::new(1, 2) + Rational::NULL, Rational::NULL);
assert_eq!(Rational::new(1, 2) - Rational::NULL, Rational::NULL);
assert_eq!(Rational::new(1, 2) * Rational::NULL, Rational::NULL);
assert_eq!(Rational::new(1, 2) / Rational::NULL, Rational::NULL);
}
#[test]
fn rational_string_roundtrip() {
assert_eq!(Rational::from_string("0/0"), Rational::NULL);
assert_eq!(
Rational::from_string("2147483647"),
Rational::new(2147483647, 1)
);
assert_eq!(
Rational::from_string("-2147483647/1"),
Rational::new(-2147483647, 1)
);
let g = Rational::from_string("abc");
assert!(g.is_null());
assert!(!g.is_nan());
assert_eq!(g, Rational::new(0, 1));
assert_eq!(g.to_display_string(), "0/1");
assert_eq!(Rational::new(30000, 1001).to_display_string(), "30000/1001");
assert_eq!(Rational::from_string("a/b/c"), Rational::NULL);
}
#[test]
fn rational_ordering() {
assert!(Rational::new(1, 3) < Rational::new(1001, 3000));
assert!(Rational::new(1, 3) > Rational::new(1, 4));
assert_eq!(Rational::new(1, 3), Rational::new(2, 6));
assert!(Rational::new(1, 2) > Rational::new(1, 3));
assert!(Rational::NULL < Rational::new(1, 1));
assert!(Rational::new(1, 1) > Rational::NULL);
assert_eq!(Rational::NULL, Rational::NULL);
let mut v = vec![
Rational::new(1, 2),
Rational::new(1, 4),
Rational::new(1, 3),
];
v.sort();
assert_eq!(
v,
vec![
Rational::new(1, 4),
Rational::new(1, 3),
Rational::new(1, 2)
]
);
}
#[test]
fn timecode_rounding() {
let tb = Rational::new(1001, 30000);
assert_eq!(tb.time_to_timestamp(Rational::new(0, 1)), 0);
assert_eq!(tb.time_to_timestamp(Rational::new(1001, 30000)), 1);
let half = Rational::new(1001, 60000);
assert_eq!(tb.time_to_timestamp(half), 1);
assert_eq!(tb.time_to_timestamp(Rational::new(-1001, 60000)), -1);
assert_eq!(tb.timestamp_to_time(30), Rational::new(1001, 1000));
assert_eq!(tb.time_to_timestamp(tb.timestamp_to_time(29)), 29);
assert_eq!(tb.time_to_timestamp(tb.timestamp_to_time(300)), 300);
assert_eq!(tb.time_to_timestamp(Rational::new(1001, 1000)), 30);
}
#[test]
fn timerange_ops() {
let r = TimeRange::new(Rational::new(0, 1), Rational::new(10, 1));
assert!(r.contains(Rational::new(5, 1)));
assert!(r.contains(Rational::new(0, 1)));
assert!(!r.contains(Rational::new(10, 1)));
assert!(!r.contains(Rational::new(-1, 1)));
assert_eq!(r.length(), Rational::new(10, 1));
let a = TimeRange::new(Rational::new(0, 1), Rational::new(10, 1));
let b = TimeRange::new(Rational::new(5, 1), Rational::new(15, 1));
assert_eq!(
a.intersected(&b),
TimeRange::new(Rational::new(5, 1), Rational::new(10, 1))
);
assert_eq!(
a.combined(&b),
TimeRange::new(Rational::new(0, 1), Rational::new(15, 1))
);
let c = TimeRange::new(Rational::new(10, 1), Rational::new(20, 1));
assert_eq!(
a.combined(&c),
TimeRange::new(Rational::new(0, 1), Rational::new(20, 1))
);
let z = TimeRange::new(Rational::new(5, 1), Rational::new(5, 1));
assert_eq!(z.length(), Rational::new(0, 1));
assert!(!z.contains(Rational::new(5, 1)));
let swapped = TimeRange::new(Rational::new(10, 1), Rational::new(5, 1));
assert_eq!(
swapped,
TimeRange::new(Rational::new(5, 1), Rational::new(10, 1))
);
}
#[test]
fn timerangelist_normalization() {
let mut list = TimeRangeList::new();
assert!(list.is_empty());
assert_eq!(list.first(), Rational::NULL);
list.insert(TimeRange::new(Rational::new(0, 1), Rational::new(10, 1)));
list.insert(TimeRange::new(Rational::new(20, 1), Rational::new(30, 1)));
list.insert(TimeRange::new(Rational::new(5, 1), Rational::new(15, 1)));
assert!(!list.is_empty());
assert_eq!(list.total_length(), Rational::new(25, 1));
assert_eq!(list.ranges().len(), 2);
let mut ins: Vec<_> = list.ranges().iter().map(|r| r.in_()).collect();
ins.sort();
assert_eq!(ins, vec![Rational::new(0, 1), Rational::new(20, 1)]);
let mut t = TimeRangeList::new();
t.insert(TimeRange::new(Rational::new(0, 1), Rational::new(10, 1)));
t.insert(TimeRange::new(Rational::new(10, 1), Rational::new(20, 1)));
assert_eq!(t.ranges().len(), 1);
assert_eq!(
t.ranges()[0],
TimeRange::new(Rational::new(0, 1), Rational::new(20, 1))
);
let mut s = TimeRangeList::new();
s.insert(TimeRange::new(Rational::new(0, 1), Rational::new(20, 1)));
s.remove(TimeRange::new(Rational::new(5, 1), Rational::new(15, 1)));
assert_eq!(s.ranges().len(), 2);
let mut outs: Vec<_> = s.ranges().iter().map(|r| r.out()).collect();
outs.sort();
assert_eq!(outs, vec![Rational::new(5, 1), Rational::new(20, 1)]);
let mut f = TimeRangeList::new();
f.insert(TimeRange::new(Rational::new(3, 1), Rational::new(7, 1)));
assert_eq!(f.first(), Rational::new(3, 1));
}
#[test]
fn timerangelist_snap() {
let tb = Rational::new(1001, 30000);
let half = Rational::new(1001, 60000);
assert_eq!(TimeRangeList::snap(half, tb), Rational::new(0, 1));
let one = Rational::new(1001, 30000);
assert_eq!(TimeRangeList::snap(one, tb), Rational::new(1001, 30000));
let one_and_half = Rational::new(1001, 20000);
assert_eq!(
TimeRangeList::snap(one_and_half, tb),
Rational::new(1001, 30000)
);
assert_eq!(
TimeRangeList::snap(Rational::new(1001, 1000), tb),
Rational::new(1001, 1000)
);
}
#[test]
fn format_enum_values_match_cpp() {
assert_eq!(PixelFormat::Invalid as i32, -1);
assert_eq!(PixelFormat::U8 as i32, 0);
assert_eq!(PixelFormat::U10 as i32, 1);
assert_eq!(PixelFormat::U16 as i32, 2);
assert_eq!(PixelFormat::F16 as i32, 3);
assert_eq!(PixelFormat::F32 as i32, 4);
assert_eq!(PixelFormat::Invalid.bytes_per_channel(), 0);
assert_eq!(PixelFormat::U8.bytes_per_channel(), 1);
assert_eq!(PixelFormat::U10.bytes_per_channel(), 4); assert_eq!(PixelFormat::U16.bytes_per_channel(), 2);
assert_eq!(PixelFormat::F16.bytes_per_channel(), 2);
assert_eq!(PixelFormat::F32.bytes_per_channel(), 4);
assert_eq!(PixelFormat::F32.bytes_per_pixel(4), 16);
assert_eq!(SampleFormat::Invalid as i32, -1);
assert_eq!(SampleFormat::U8Planar as i32, 0);
assert_eq!(SampleFormat::S16Planar as i32, 1);
assert_eq!(SampleFormat::S32Planar as i32, 2);
assert_eq!(SampleFormat::S64Planar as i32, 3);
assert_eq!(SampleFormat::F32Planar as i32, 4);
assert_eq!(SampleFormat::F64Planar as i32, 5);
assert_eq!(SampleFormat::U8 as i32, 6);
assert_eq!(SampleFormat::S16 as i32, 7);
assert_eq!(SampleFormat::S32 as i32, 8);
assert_eq!(SampleFormat::S64 as i32, 9);
assert_eq!(SampleFormat::F32 as i32, 10);
assert_eq!(SampleFormat::F64 as i32, 11);
assert_eq!(SampleFormat::Invalid.bytes_per_sample(), 0);
assert_eq!(SampleFormat::U8.bytes_per_sample(), 1);
assert_eq!(SampleFormat::S16.bytes_per_sample(), 2);
assert_eq!(SampleFormat::S32.bytes_per_sample(), 4);
assert_eq!(SampleFormat::F32.bytes_per_sample(), 4);
assert_eq!(SampleFormat::F64.bytes_per_sample(), 8);
assert_eq!(SampleFormat::F64Planar.bytes_per_sample(), 8);
assert!(SampleFormat::U8Planar.is_planar());
assert!(SampleFormat::F64Planar.is_planar());
assert!(!SampleFormat::U8.is_planar());
assert!(!SampleFormat::Invalid.is_planar());
assert_eq!(SampleFormat::U8Planar.to_packed(), SampleFormat::U8);
assert_eq!(SampleFormat::F64Planar.to_packed(), SampleFormat::F64);
assert_eq!(SampleFormat::U8.to_packed(), SampleFormat::U8);
assert_eq!(SampleFormat::U8.to_planar(), SampleFormat::U8Planar);
assert_eq!(SampleFormat::S16.to_planar(), SampleFormat::S16Planar);
assert_eq!(SampleFormat::F64.to_planar(), SampleFormat::F64Planar);
}
#[test]
fn rational_large_inputs_and_minmax() {
let mn = Rational::new(i64::MIN, 1);
assert_eq!(mn.numerator(), -2147483647);
assert_eq!(mn.denominator(), 1);
let mx = Rational::new(i64::MAX, 1);
assert_eq!(mx.numerator(), 2147483647);
assert_eq!(mx.denominator(), 1);
let mx = Rational::new(2147483647, 1);
assert!(!mx.is_null()); let r = mx + Rational::new(1, 1);
assert!(r.is_nan());
assert_eq!(r, Rational::NULL);
let mn = Rational::new(-2147483647, 1);
let r = Rational::new(1, 1) * mn;
assert!(r.is_nan());
}
#[test]
fn additional_edge_cases() {
let mut l = TimeRangeList::new();
l.insert(TimeRange::new(Rational::new(0, 1), Rational::new(20, 1)));
l.remove(TimeRange::new(Rational::new(-5, 1), Rational::new(25, 1)));
assert!(l.is_empty());
let mut l2 = TimeRangeList::new();
l2.insert(TimeRange::new(Rational::new(0, 1), Rational::new(20, 1)));
l2.remove(TimeRange::new(Rational::new(5, 1), Rational::new(25, 1)));
assert_eq!(l2.ranges().len(), 1);
assert_eq!(
l2.ranges()[0],
TimeRange::new(Rational::new(0, 1), Rational::new(5, 1))
);
let mut l3 = TimeRangeList::new();
l3.insert(TimeRange::new(Rational::new(0, 1), Rational::new(20, 1)));
l3.remove(TimeRange::new(Rational::new(-5, 1), Rational::new(5, 1)));
assert_eq!(l3.ranges().len(), 1);
assert_eq!(
l3.ranges()[0],
TimeRange::new(Rational::new(5, 1), Rational::new(20, 1))
);
assert_eq!(Rational::NULL.time_to_timestamp(Rational::new(1, 1)), 0);
assert!(Rational::NULL.to_f64().is_nan());
assert_eq!(SampleFormat::Invalid.to_packed(), SampleFormat::Invalid);
assert_eq!(SampleFormat::Invalid.to_planar(), SampleFormat::Invalid);
}
#[test]
fn rational_from_double() {
use quercus_core::Rational;
assert!(Rational::from_double(f64::NAN).is_nan());
assert!(Rational::from_double(1e300).is_nan());
assert!(Rational::from_double(-1e300).is_nan());
let r = Rational::from_double(0.5);
assert_eq!((r.numerator(), r.denominator()), (1, 2));
let fps = Rational::from_double(29.97002997002997);
assert!((fps.to_f64() - 29.97002997002997).abs() < 1e-9);
let third = Rational::from_double(1.0 / 3.0);
assert!((third.to_f64() - 1.0 / 3.0).abs() < 1e-9);
assert_eq!(Rational::from_double(0.0).numerator(), 0);
}