mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 14:12:31 +00:00
ID3v2: Add tests for OWNE and RVA2 frame parsing
This commit is contained in:
parent
7b98078317
commit
9fdd6b610a
4 changed files with 147 additions and 2 deletions
|
@ -73,8 +73,42 @@ impl OwnershipFrame {
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes.extend(self.date_of_purchase.as_bytes().iter().take(8));
|
bytes.extend(self.date_of_purchase.as_bytes().iter().take(8));
|
||||||
bytes.extend(encode_text(&self.seller, self.encoding, true));
|
bytes.extend(encode_text(&self.seller, self.encoding, false));
|
||||||
|
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::id3::v2::OwnershipFrame;
|
||||||
|
use crate::TextEncoding;
|
||||||
|
|
||||||
|
fn expected() -> OwnershipFrame {
|
||||||
|
OwnershipFrame {
|
||||||
|
encoding: TextEncoding::Latin1,
|
||||||
|
price_paid: String::from("USD1000"),
|
||||||
|
date_of_purchase: String::from("19840407"),
|
||||||
|
seller: String::from("FooBar"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn owne_decode() {
|
||||||
|
let cont = crate::tag::utils::test_utils::read_path("tests/tags/assets/id3v2/test.owne");
|
||||||
|
|
||||||
|
let parsed_owne = OwnershipFrame::parse(&mut &cont[..]).unwrap().unwrap();
|
||||||
|
|
||||||
|
assert_eq!(parsed_owne, expected());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn owne_encode() {
|
||||||
|
let encoded = expected().as_bytes().unwrap();
|
||||||
|
|
||||||
|
let expected_bytes =
|
||||||
|
crate::tag::utils::test_utils::read_path("tests/tags/assets/id3v2/test.owne");
|
||||||
|
|
||||||
|
assert_eq!(encoded, expected_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -166,7 +166,7 @@ impl RelativeVolumeAdjustmentFrame {
|
||||||
if info.peak_volume.is_none() {
|
if info.peak_volume.is_none() {
|
||||||
// Easiest path, no peak
|
// Easiest path, no peak
|
||||||
content.push(0);
|
content.push(0);
|
||||||
return content;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(peak) = &info.peak_volume {
|
if let Some(peak) = &info.peak_volume {
|
||||||
|
@ -188,3 +188,114 @@ impl RelativeVolumeAdjustmentFrame {
|
||||||
content
|
content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::id3::v2::{ChannelInformation, ChannelType, RelativeVolumeAdjustmentFrame};
|
||||||
|
use crate::ParsingMode;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
fn expected() -> RelativeVolumeAdjustmentFrame {
|
||||||
|
let mut channels = HashMap::new();
|
||||||
|
|
||||||
|
channels.insert(
|
||||||
|
ChannelType::MasterVolume,
|
||||||
|
ChannelInformation {
|
||||||
|
channel_type: ChannelType::MasterVolume,
|
||||||
|
volume_adjustment: 15,
|
||||||
|
bits_representing_peak: 4,
|
||||||
|
peak_volume: Some(vec![4]),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
channels.insert(
|
||||||
|
ChannelType::FrontLeft,
|
||||||
|
ChannelInformation {
|
||||||
|
channel_type: ChannelType::FrontLeft,
|
||||||
|
volume_adjustment: 21,
|
||||||
|
bits_representing_peak: 0,
|
||||||
|
peak_volume: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
channels.insert(
|
||||||
|
ChannelType::Subwoofer,
|
||||||
|
ChannelInformation {
|
||||||
|
channel_type: ChannelType::Subwoofer,
|
||||||
|
volume_adjustment: 30,
|
||||||
|
bits_representing_peak: 11,
|
||||||
|
peak_volume: Some(vec![0xFF, 0x07]),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
RelativeVolumeAdjustmentFrame {
|
||||||
|
identification: String::from("Surround sound"),
|
||||||
|
channels,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rva2_decode() {
|
||||||
|
let cont = crate::tag::utils::test_utils::read_path("tests/tags/assets/id3v2/test.rva2");
|
||||||
|
|
||||||
|
let parsed_rva2 = RelativeVolumeAdjustmentFrame::parse(&mut &cont[..], ParsingMode::Strict)
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(parsed_rva2, expected());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(unstable_name_collisions)]
|
||||||
|
fn rva2_encode() {
|
||||||
|
let encoded = expected().as_bytes();
|
||||||
|
|
||||||
|
let expected_bytes =
|
||||||
|
crate::tag::utils::test_utils::read_path("tests/tags/assets/id3v2/test.rva2");
|
||||||
|
|
||||||
|
// We have to check the output in fragments, as the order of channels is not guaranteed.
|
||||||
|
assert_eq!(encoded.len(), expected_bytes.len());
|
||||||
|
|
||||||
|
let mut needles = vec![
|
||||||
|
&[1, 0, 15, 4, 4][..], // Master volume configuration
|
||||||
|
&[8, 0, 30, 11, 255, 7][..], // Front left configuration
|
||||||
|
&[3, 0, 21, 0][..], // Subwoofer configuration
|
||||||
|
];
|
||||||
|
|
||||||
|
let encoded_reader = &mut &encoded[..];
|
||||||
|
|
||||||
|
let mut ident = [0; 15];
|
||||||
|
encoded_reader.read_exact(&mut ident).unwrap();
|
||||||
|
assert_eq!(ident, b"Surround sound\0"[..]);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if needles.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut remove_idx = None;
|
||||||
|
for (idx, needle) in needles.iter().enumerate() {
|
||||||
|
if encoded_reader.starts_with(needle) {
|
||||||
|
std::io::copy(
|
||||||
|
&mut encoded_reader.take(needle.len() as u64),
|
||||||
|
&mut std::io::sink(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
remove_idx = Some(idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(remove_idx) = remove_idx else {
|
||||||
|
unreachable!("Unexpected data in RVA2 frame: {:?}", &encoded);
|
||||||
|
};
|
||||||
|
|
||||||
|
needles.remove(remove_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(needles.is_empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
BIN
tests/tags/assets/id3v2/test.owne
Normal file
BIN
tests/tags/assets/id3v2/test.owne
Normal file
Binary file not shown.
BIN
tests/tags/assets/id3v2/test.rva2
Normal file
BIN
tests/tags/assets/id3v2/test.rva2
Normal file
Binary file not shown.
Loading…
Reference in a new issue