Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backend: add test for lyric #625

Merged
merged 12 commits into from
Jan 1, 2025
Prev Previous commit
Next Next commit
add dump lyrics in metadata
vnghia committed Jan 1, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit e9ac370adb43b5cd02c0005ef2c0c243dd79ea50
47 changes: 47 additions & 0 deletions nghe-backend/src/file/lyric/mod.rs
Original file line number Diff line number Diff line change
@@ -192,6 +192,7 @@ mod test {
use diesel::{QueryDsl, SelectableHelper};
use fake::{Dummy, Fake, Faker};
use itertools::Itertools;
use lofty::id3::v2::Frame;

use super::*;
use crate::test::Mock;
@@ -237,6 +238,20 @@ mod test {
}

impl Lyric<'static> {
pub async fn query(mock: &Mock, id: Uuid) -> Vec<Self> {
lyrics::table
.filter(lyrics::song_id.eq(id))
.filter(lyrics::source.is_null())
.select(lyrics::Data::as_select())
.order_by(lyrics::scanned_at)
.get_results(&mut mock.get().await)
.await
.unwrap()
.into_iter()
.map(Self::from)
.collect()
}

pub async fn query_external(mock: &Mock, id: Uuid) -> Option<Self> {
lyrics::table
.filter(lyrics::song_id.eq(id))
@@ -280,6 +295,38 @@ mod test {
}
}
}

impl From<Lyric<'_>> for Frame<'static> {
fn from(value: Lyric<'_>) -> Self {
let language = value.language.to_639_3().as_bytes().try_into().unwrap();
match value.lines {
Lines::Unsync(lines) => UnsynchronizedTextFrame::new(
lofty::TextEncoding::UTF8,
language,
value.description.map(Cow::into_owned).unwrap_or_default(),
lines.join("\n"),
)
.into(),
Lines::Sync(lines) => BinaryFrame::new(
crate::config::parsing::id3v2::Id3v2::SYNC_LYRIC_FRAME_ID,
SynchronizedTextFrame::new(
lofty::TextEncoding::UTF8,
language,
lofty::id3::v2::TimestampFormat::MS,
lofty::id3::v2::SyncTextContentType::Lyrics,
value.description.map(Cow::into_owned),
lines
.into_iter()
.map(|(duration, text)| (duration, text.into_owned()))
.collect(),
)
.as_bytes()
.unwrap(),
)
.into(),
}
}
}
}

#[cfg(test)]
6 changes: 6 additions & 0 deletions nghe-backend/src/test/file/audio/dump/file.rs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ use lofty::ogg::{OggPictureStorage as _, VorbisComments};
use super::Metadata;
use crate::config;
use crate::file::audio::{Album, Artists, Genres, NameDateMbz, TrackDisc};
use crate::file::lyric::Lyric;
use crate::file::picture::Picture;

trait TagMut {
@@ -48,6 +49,11 @@ default impl<T: TagMut> Metadata for T {
self
}

fn dump_lyrics(&mut self, config: &config::Parsing, lyrics: Vec<Lyric<'_>>) -> &mut Self {
self.tag_mut().dump_lyrics(config, lyrics);
self
}

fn dump_picture(&mut self, picture: Option<Picture<'_>>) -> &mut Self {
self.tag_mut().dump_picture(picture);
self
17 changes: 16 additions & 1 deletion nghe-backend/src/test/file/audio/dump/mod.rs
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ use isolang::Language;

use crate::config;
use crate::file::audio::{self, Album, Artists, File, Genres, NameDateMbz, TrackDisc};
use crate::file::lyric::Lyric;
use crate::file::picture::Picture;

pub trait Metadata {
@@ -14,21 +15,23 @@ pub trait Metadata {
fn dump_track_disc(&mut self, config: &config::Parsing, track_disc: TrackDisc) -> &mut Self;
fn dump_languages(&mut self, config: &config::Parsing, languages: Vec<Language>) -> &mut Self;
fn dump_genres(&mut self, config: &config::Parsing, genres: Genres<'_>) -> &mut Self;
fn dump_lyrics(&mut self, config: &config::Parsing, lyrics: Vec<Lyric<'_>>) -> &mut Self;
fn dump_picture(&mut self, picture: Option<Picture<'_>>) -> &mut Self;

fn dump_metadata(
&mut self,
config: &config::Parsing,
metadata: audio::Metadata<'_>,
) -> &mut Self {
let audio::Metadata { song, album, artists, genres, picture } = metadata;
let audio::Metadata { song, album, artists, genres, lyrics, picture } = metadata;
let audio::Song { main, track_disc, languages } = song;
self.dump_song(config, main)
.dump_album(config, album)
.dump_artists(config, artists)
.dump_track_disc(config, track_disc)
.dump_languages(config, languages)
.dump_genres(config, genres)
.dump_lyrics(config, lyrics)
.dump_picture(picture)
}
}
@@ -106,6 +109,18 @@ impl Metadata for File {
self
}

fn dump_lyrics(&mut self, config: &config::Parsing, lyrics: Vec<Lyric<'_>>) -> &mut Self {
match self {
File::Flac { audio, .. } => {
audio.dump_lyrics(config, lyrics);
}
File::Mpeg { audio, .. } => {
audio.dump_lyrics(config, lyrics);
}
}
self
}

fn dump_picture(&mut self, picture: Option<Picture<'_>>) -> &mut Self {
match self {
File::Flac { audio, .. } => {
8 changes: 8 additions & 0 deletions nghe-backend/src/test/file/audio/dump/tag/id3v2.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ use crate::config;
use crate::config::parsing::id3v2::frame;
use crate::file::audio::position::Position;
use crate::file::audio::{Album, Artist, Artists, Date, Genres, NameDateMbz, TrackDisc};
use crate::file::lyric::Lyric;
use crate::file::picture::Picture;
use crate::test::file::audio::dump;

@@ -139,6 +140,13 @@ impl dump::Metadata for Id3v2Tag {
self
}

fn dump_lyrics(&mut self, _: &config::Parsing, lyrics: Vec<Lyric<'_>>) -> &mut Self {
for lyric in lyrics {
self.insert(lyric.into());
}
self
}

fn dump_picture(&mut self, picture: Option<Picture<'_>>) -> &mut Self {
if let Some(picture) = picture {
self.insert_picture(picture.into());
16 changes: 16 additions & 0 deletions nghe-backend/src/test/file/audio/dump/tag/vorbis_comments.rs
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ use uuid::Uuid;
use crate::config;
use crate::file::audio::position::Position;
use crate::file::audio::{Album, Artist, Artists, Date, Genres, NameDateMbz, TrackDisc};
use crate::file::lyric::Lyric;
use crate::file::picture::Picture;
use crate::test::file::audio::dump;

@@ -108,6 +109,21 @@ impl dump::Metadata for VorbisComments {
self
}

fn dump_lyrics(&mut self, config: &config::Parsing, lyrics: Vec<Lyric<'_>>) -> &mut Self {
for lyric in lyrics {
self.push(
if lyric.is_sync() {
&config.vorbis_comments.lyric.sync
} else {
&config.vorbis_comments.lyric.unsync
}
.clone(),
lyric.to_string(),
);
}
self
}

fn dump_picture(&mut self, picture: Option<Picture<'_>>) -> &mut Self {
if let Some(picture) = picture {
self.insert_picture(picture.into(), None).unwrap();
8 changes: 8 additions & 0 deletions nghe-backend/src/test/mock_impl/information.rs
Original file line number Diff line number Diff line change
@@ -42,6 +42,7 @@ impl Mock<'static, 'static, 'static, 'static> {
let album = audio::Album::query_upsert(mock, upsert.foreign.album_id).await;
let artists = audio::Artists::query(mock, id).await;
let genres = audio::Genres::query(mock, id).await;
let lyrics = lyric::Lyric::query(mock, id).await;
let picture = picture::Picture::query_song(mock, id).await;

let external_lyric = lyric::Lyric::query_external(mock, id).await;
@@ -54,6 +55,7 @@ impl Mock<'static, 'static, 'static, 'static> {
album: album.data.try_into().unwrap(),
artists,
genres,
lyrics,
picture,
},
property: upsert.data.property.try_into().unwrap(),
@@ -76,6 +78,7 @@ impl Mock<'static, 'static, 'static, 'static> {
album: Option<audio::Album<'static>>,
artists: Option<audio::Artists<'static>>,
genres: Option<audio::Genres<'static>>,
lyrics: Option<Vec<lyric::Lyric<'static>>>,
picture: Option<Option<picture::Picture<'static>>>,
format: Option<audio::Format>,
file_property: Option<file::Property<audio::Format>>,
@@ -89,6 +92,11 @@ impl Mock<'static, 'static, 'static, 'static> {
album: album.unwrap_or_else(|| Faker.fake()),
artists: artists.unwrap_or_else(|| Faker.fake()),
genres: genres.unwrap_or_else(|| Faker.fake()),
lyrics: lyrics.unwrap_or_else(|| {
let unsync = if Faker.fake() { Some(lyric::Lyric::fake_unsync()) } else { None };
let sync = if Faker.fake() { Some(lyric::Lyric::fake_sync()) } else { None };
unsync.into_iter().chain(sync).collect()
}),
picture: picture.unwrap_or_else(|| Faker.fake()),
});
let file = file_property.unwrap_or_else(|| file::Property {