mpdclient 0.2.0

Rust interface to MPD using libmpdclient
Documentation
use std::time::SystemTime;

use mpdclient::{AudioFormat, Channels, Constraint, Entity, SupportedBits, Tag};

use crate::common::setup_mpd;

mod common;

// ---Song ---
#[test]
fn uri() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.uri(), "song.mp3");
            Ok(())
        },
    )
}

#[test]
fn duration() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.duration(), Some(30));
            Ok(())
        },
    )
}

#[test]
fn duration_ms() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.duration_ms(), Some(30000));
            Ok(())
        },
    )
}

#[test]
fn start() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.start(), 0);
            Ok(())
        },
    )
}

#[test]
fn start_notnull() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;
            queue.range_id(queue.get_song_pos(0)?.id(), 2.0, None)?;

            assert_eq!(queue.get_song_pos(0)?.start(), 2);
            Ok(())
        },
    )
}

#[test]
fn end() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.end(), None);
            Ok(())
        },
    )
}

// $45
#[test]
fn end_notnull() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;
            queue.range_id(queue.get_song_pos(0)?.id(), 0.0, Some(23.0))?;

            assert_eq!(queue.get_song_pos(0)?.end(), Some(23));
            Ok(())
        },
    )
}

#[test]
fn last_modified() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert!(queue.get_song_pos(0)?.last_modified() <= Some(SystemTime::now()));
            Ok(())
        },
    )
}

#[cfg(feature = "protocol_0_24")]
#[test]
fn added() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;

            assert!(queue.get_song_pos(0)?.added() <= Some(SystemTime::now()));
            Ok(())
        },
    )
}

#[test]
fn pos() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            let id = queue.add_id("song.mp3")?;

            assert_eq!(queue.get_song_id(id)?.pos(), 0);
            Ok(())
        },
    )
}

#[test]
// Value is 0, but invalid
fn pos_no_queue() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .uri("song.mp3")?
                    .commit()?
                    .first()
                    .unwrap()
                    .pos(),
                0
            );
            Ok(())
        },
    )
}

#[test]
fn id() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add_id("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.id(), 1);
            Ok(())
        },
    )
}

#[test]
// Value is 0, but invalid
fn id_no_queue() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .uri("song.mp3")?
                    .commit()?
                    .first()
                    .unwrap()
                    .id(),
                0
            );
            Ok(())
        },
    )
}

#[test]
fn prio() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add_id("song.mp3")?;

            assert_eq!(queue.get_song_pos(0)?.prio(), 0);
            Ok(())
        },
    )
}

#[test]
// Value is 0, but invalid
fn prio_no_queue() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .uri("song.mp3")?
                    .commit()?
                    .first()
                    .unwrap()
                    .prio(),
                0
            );
            Ok(())
        },
    )
}

#[test]
fn audio_format() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let queue = conn.queue();
            queue.add_id("song.mp3")?;

            assert_eq!(
                queue.get_song_pos(0)?.audio_format(),
                Some(AudioFormat {
                    sample_rate: Some(8000),
                    bits: SupportedBits::N16,
                    channels: Channels::Mono
                })
            );
            Ok(())
        },
    )
}

// --- SongTag ---

#[test]
fn artist() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert_eq!(
                song.tag(Tag::Artist).collect::<Vec<String>>(),
                vec!["fregrem", "fx"]
            );
            Ok(())
        },
    )
}

#[test]
fn album() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert_eq!(
                song.tag(Tag::Album).collect::<Vec<String>>(),
                vec!["OneSilence"]
            );
            Ok(())
        },
    )
}

#[test]
fn title() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert_eq!(
                song.tag(Tag::Title).collect::<Vec<String>>(),
                vec!["Silence"]
            );
            Ok(())
        },
    )
}

#[test]
fn track() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert_eq!(song.tag(Tag::Track).collect::<Vec<String>>(), vec!["1"]);
            Ok(())
        },
    )
}

#[test]
fn genre() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert_eq!(
                song.tag(Tag::Genre).collect::<Vec<String>>(),
                vec!["Comedy"]
            );
            Ok(())
        },
    )
}

#[test]
fn date() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert_eq!(song.tag(Tag::Date).collect::<Vec<String>>(), vec!["2025"]);
            Ok(())
        },
    )
}

#[test]
fn comment() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            let db = conn.database().list_meta(None)?.receive_all()?;
            let Some(Entity::Song(song)) = db.first() else {
                unreachable!()
            };

            assert!(song.tag(Tag::Comment).collect::<Vec<String>>().is_empty());
            Ok(())
        },
    )
}