diff --git a/src/id3/v2/items/ownership_frame.rs b/src/id3/v2/items/ownership_frame.rs index 17667954..4522b06f 100644 --- a/src/id3/v2/items/ownership_frame.rs +++ b/src/id3/v2/items/ownership_frame.rs @@ -73,8 +73,42 @@ impl OwnershipFrame { } 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) } } + +#[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); + } +} diff --git a/src/id3/v2/items/relative_volume_adjustment_frame.rs b/src/id3/v2/items/relative_volume_adjustment_frame.rs index c6a88cb8..3aa6f8be 100644 --- a/src/id3/v2/items/relative_volume_adjustment_frame.rs +++ b/src/id3/v2/items/relative_volume_adjustment_frame.rs @@ -166,7 +166,7 @@ impl RelativeVolumeAdjustmentFrame { if info.peak_volume.is_none() { // Easiest path, no peak content.push(0); - return content; + continue; } if let Some(peak) = &info.peak_volume { @@ -188,3 +188,114 @@ impl RelativeVolumeAdjustmentFrame { 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()); + } +} diff --git a/tests/tags/assets/id3v2/test.owne b/tests/tags/assets/id3v2/test.owne new file mode 100644 index 00000000..b6a0ede0 Binary files /dev/null and b/tests/tags/assets/id3v2/test.owne differ diff --git a/tests/tags/assets/id3v2/test.rva2 b/tests/tags/assets/id3v2/test.rva2 new file mode 100644 index 00000000..cd1d1d44 Binary files /dev/null and b/tests/tags/assets/id3v2/test.rva2 differ