mpdclient 0.2.0

Rust interface to MPD using libmpdclient
Documentation
use std::time::{SystemTime, UNIX_EPOCH};

use mpdclient::{Constraint, Position, Song, Tag};

use crate::common::setup_mpd;

mod common;

#[test]
fn database() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song")
        },
        |conn| {
            assert_eq!(
                conn.search().database(false)?.base("dir")?.commit()?.len(),
                1
            );
            Ok(())
        },
    )
}

#[test]
fn database_add() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song2")
        },
        |conn| {
            conn.search().database_add(false)?.uri("song2")?.commit()?;
            assert_eq!(
                conn.queue()
                    .list()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["dir/song2.mp3"]
            );
            Ok(())
        },
    )
}

#[test]
fn database_add_playlist() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song2")?;
            setup.playlist()
        },
        |conn| {
            conn.search()
                .database_add_playlist("playlist")?
                .uri("song2")?
                .commit()?;
            assert_eq!(
                conn.playlist("playlist")?
                    .list()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["song.mp3", "song2.mp3", "dir/song2.mp3"]
            );
            Ok(())
        },
    )
}

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

            assert_eq!(conn.search().queue(false)?.uri("song2")?.commit()?.len(), 0);
            Ok(())
        },
    )
}

#[test]
fn tags() -> eyre::Result<()> {
    setup_mpd(
        |setup| setup.song("song"),
        |conn| {
            assert_eq!(
                conn.search().tags(Tag::Artist)?.commit()?.receive_all()?,
                vec!["fregrem", "fx"]
            );
            Ok(())
        },
    )
}

#[test]
fn count_database() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song2")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .count_database()?
                    .tag(Tag::Title, "Silence")?
                    .commit()?
                    .songs(),
                Some(2)
            );
            Ok(())
        },
    )
}

// --- Constraint ---
#[test]
fn any_tag() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.song("song2")?;
            setup.directory()?;
            setup.song("dir/song")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .any_tag("silence")?
                    .commit()?
                    .len(),
                3
            );
            Ok(())
        },
    )
}

#[test]
fn modified_since() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.song("song2")?;
            setup.directory()?;
            setup.song("dir/song")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .modified_since(SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs())?
                    .commit()?
                    .len(),
                0
            );
            Ok(())
        },
    )
}

#[test]
#[cfg(feature = "protocol_0_24")]
fn added_since() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.song("song2")?;
            setup.directory()?;
            setup.song("dir/song")
        },
        |conn| {
            std::thread::sleep(std::time::Duration::from_secs(1));
            assert_eq!(
                conn.search()
                    .database(false)?
                    .added_since(SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs())?
                    .commit()?
                    .len(),
                0
            );
            Ok(())
        },
    )
}

#[test]
fn expression() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .expression(r#"((ARTIST == "fregrem") AND (title == "Silence"))"#)?
                    .commit()?
                    .len(),
                2
            );
            Ok(())
        },
    )
}

// --- Grouping/Sorting ---
// TODO: Good testing

// Doesnt get accepted by the server
// #[test]
// fn group_tag() -> eyre::Result<()> {
//     let connection = Connection::new()?;
//     assert_eq!(
//         connection
//             .search()
//             .database(false)?
//             .base("dir")?
//             .group_tag(Tag::Artist)?
//             .commit()?
//             .len(),
//         var("TEST_DATABASE_DIR_LEN")?.parse()?
//     );
//     Ok(())
// }

#[test]
fn sort_name() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song")?;
            setup.song("dir/song2")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .base("dir")?
                    .sort_name(&Tag::Title.name(), false)?
                    .commit()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["dir/song.mp3", "dir/song2.mp3"]
            );
            Ok(())
        },
    )
}

#[test]
fn sort_tag() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song")?;
            setup.song("dir/song2")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .base("dir")?
                    .sort_tag(Tag::Title, false)?
                    .commit()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["dir/song.mp3", "dir/song2.mp3"]
            );
            Ok(())
        },
    )
}

#[test]
fn window() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song")?;
            setup.song("dir/song2")
        },
        |conn| {
            assert_eq!(
                conn.search()
                    .database(false)?
                    .uri("song")?
                    .window(0, 2)?
                    .commit()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["song.mp3", "dir/song.mp3"]
            );
            Ok(())
        },
    )
}

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

            conn.search()
                .database_add(false)?
                .uri("song2")?
                .add_position(1, Position::Absolute)?
                .commit()?;
            assert_eq!(
                conn.queue()
                    .list()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["song.mp3", "dir/song2.mp3", "dir/song.mp3"]
            );
            Ok(())
        },
    )
}

#[test]
fn add_position_playlist() -> eyre::Result<()> {
    setup_mpd(
        |setup| {
            setup.playlist()?;
            setup.song("song")?;
            setup.directory()?;
            setup.song("dir/song")?;
            setup.song("dir/song2")
        },
        |conn| {
            let queue = conn.queue();
            queue.add("song.mp3")?;
            queue.add("dir/song.mp3")?;

            conn.search()
                .database_add_playlist("playlist")?
                .uri("song2")?
                .add_position(1, Position::Absolute)?
                .commit()?;
            assert_eq!(
                conn.playlist("playlist")?
                    .list()?
                    .iter()
                    .map(Song::uri)
                    .collect::<Vec<String>>(),
                vec!["song.mp3", "dir/song2.mp3", "song2.mp3"]
            );
            Ok(())
        },
    )
}