Skip to content

Commit 527d509

Browse files
authored
Merge pull request kstep#24 from tomprince/test-mpd
Start a fresh daemon for tests.
2 parents 95f30e0 + c707896 commit 527d509

File tree

6 files changed

+173
-11
lines changed

6 files changed

+173
-11
lines changed

.travis.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ env:
1818
before_script:
1919
- sudo apt-get update -qq
2020
- sudo apt-get install -y mpd
21+
# Stop mpd service to ensure we use the test-started ones.
22+
- sudo /etc/init.d/mpd stop
2123
- /usr/bin/mpd --version
2224
- export PATH=$HOME/.cargo/bin:$HOME/.local/bin:$PATH
2325
- |

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ rustc-serialize = "0.3.16"
1414
time = "0.1.34"
1515

1616
[dev-dependencies]
17+
tempdir = "0.3.5"
1718
unix_socket = "0.5.0"

tests/helpers.rs

Lines changed: 0 additions & 9 deletions
This file was deleted.

tests/helpers/daemon.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
extern crate tempdir;
2+
3+
use self::tempdir::TempDir;
4+
use super::mpd;
5+
use std::fs::{File, create_dir};
6+
use std::io::{Write, Read};
7+
use std::os::unix::net::UnixStream;
8+
use std::path::{Path, PathBuf};
9+
use std::process::{Command, Child, Stdio};
10+
11+
struct MpdConfig {
12+
db_file: PathBuf,
13+
music_directory: PathBuf,
14+
playlist_directory: PathBuf,
15+
config_path: PathBuf,
16+
sock_path: PathBuf,
17+
}
18+
19+
impl MpdConfig {
20+
pub fn new<P>(base: P) -> MpdConfig
21+
where P: AsRef<Path>
22+
{
23+
let base = base.as_ref();
24+
MpdConfig {
25+
db_file: base.join("db"),
26+
music_directory: base.join("music"),
27+
playlist_directory: base.join("playlists"),
28+
config_path: base.join("config"),
29+
sock_path: base.join("sock"),
30+
}
31+
}
32+
33+
fn config_text(&self) -> String {
34+
format!(r#"
35+
db_file "{db_file}"
36+
log_file "/dev/null"
37+
music_directory "{music_directory}"
38+
playlist_directory "{playlist_directory}"
39+
bind_to_address "{sock_path}"
40+
audio_output {{
41+
type "null"
42+
name "null"
43+
}}
44+
"#,
45+
db_file=self.db_file.display(),
46+
music_directory=self.music_directory.display(),
47+
playlist_directory=self.playlist_directory.display(),
48+
sock_path=self.sock_path.display(),
49+
)
50+
}
51+
52+
fn generate(&self) {
53+
create_dir(&self.music_directory).expect("Could not create music directory.");
54+
create_dir(&self.playlist_directory).expect("Could not create playlist directory.");
55+
let mut file = File::create(&self.config_path).expect("Could not create config file.");
56+
file.write_all(self.config_text().as_bytes()).expect("Could not write config file.");
57+
}
58+
}
59+
60+
pub struct Daemon {
61+
// Saved here so it gets dropped when this does.
62+
_temp_dir: TempDir,
63+
config: MpdConfig,
64+
process: Child,
65+
}
66+
67+
impl Drop for Daemon {
68+
fn drop(&mut self) {
69+
self.process.kill().expect("Could not kill mpd daemon.");
70+
self.process.wait().expect("Could not wait for mpd daemon to shutdown.");
71+
if let Some(ref mut stderr) = self.process.stderr {
72+
let mut output = String::new();
73+
stderr.read_to_string(&mut output).expect("Could not collect output from mpd.");
74+
println!{"Output from mpd:"}
75+
println!{"{}", output};
76+
}
77+
}
78+
}
79+
80+
fn sleep() {
81+
use std::{thread, time};
82+
let ten_millis = time::Duration::from_millis(10);
83+
thread::sleep(ten_millis);
84+
}
85+
86+
impl Daemon {
87+
pub fn start() -> Daemon {
88+
let temp_dir = TempDir::new("mpd-test").unwrap();
89+
let config = MpdConfig::new(&temp_dir);
90+
config.generate();
91+
let process = Command::new("mpd")
92+
.arg("--no-daemon")
93+
.arg(&config.config_path)
94+
.stdin(Stdio::null())
95+
.stdout(Stdio::null())
96+
.stderr(Stdio::piped())
97+
.spawn()
98+
.expect("Could not create mpd daemon.");
99+
100+
let daemon = Daemon {
101+
_temp_dir: temp_dir,
102+
config: config,
103+
process: process,
104+
};
105+
106+
// Wait until we can connect to the daemon
107+
let mut client;
108+
loop {
109+
if let Ok(c) = daemon.maybe_connect() {
110+
client = c;
111+
break;
112+
}
113+
sleep()
114+
}
115+
while let Some(_) = client.status().expect("Couldn't get status.").updating_db {
116+
sleep()
117+
}
118+
119+
daemon
120+
}
121+
122+
fn maybe_connect(&self) -> Result<mpd::Client<UnixStream>, mpd::error::Error> {
123+
let stream = UnixStream::connect(&self.config.sock_path)?;
124+
mpd::Client::new(stream)
125+
}
126+
127+
pub fn connect(&self) -> mpd::Client<UnixStream> {
128+
self.maybe_connect().expect("Could not connect to daemon.")
129+
}
130+
}

tests/helpers/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
extern crate mpd;
2+
3+
mod daemon;
4+
5+
pub use self::daemon::Daemon;
6+
use std::os::unix::net::UnixStream;
7+
8+
pub struct DaemonClient {
9+
_daemon: Daemon,
10+
client: mpd::Client<UnixStream>,
11+
}
12+
13+
use std::ops::{Deref, DerefMut};
14+
15+
impl Deref for DaemonClient {
16+
type Target = mpd::Client<UnixStream>;
17+
fn deref(&self) -> &Self::Target {
18+
&self.client
19+
}
20+
}
21+
22+
impl DerefMut for DaemonClient {
23+
fn deref_mut(&mut self) -> &mut Self::Target {
24+
&mut self.client
25+
}
26+
}
27+
28+
#[allow(dead_code)]
29+
pub fn connect() -> DaemonClient {
30+
let daemon = Daemon::start();
31+
let client = daemon.connect();
32+
DaemonClient {
33+
_daemon: daemon,
34+
client: client,
35+
}
36+
}

tests/idle.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
extern crate mpd;
22

33
mod helpers;
4+
use helpers::Daemon;
45

56
use mpd::Idle;
67

78
#[test]
89
fn idle() {
9-
let mut mpd = helpers::connect();
10+
let daemon = Daemon::start();
11+
let mut mpd = daemon.connect();
1012
let idle = mpd.idle(&[]).unwrap();
1113

12-
let mut mpd1 = helpers::connect();
14+
let mut mpd1 = daemon.connect();
1315
mpd1.consume(true).unwrap();
1416
mpd1.consume(false).unwrap();
1517

0 commit comments

Comments
 (0)