[gitconv @ Unit test for password]
[libmpd-haskell.git] / tests / Commands.hs
blob37a11827b51601fbb0c5295e3b988050a6b96669
1 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
3 -- |
4 -- This module provides a way of verifying that the interface to the MPD
5 -- commands is correct. It does so by capturing the data flow between the
6 -- command and a dummy socket, checking the captured data against a set of
7 -- predefined values that are known to be correct. Of course, this does not
8 -- verify that the external behaviour is correct, it's simply a way of
9 -- catching silly mistakes and subtle bugs in the interface itself, without
10 -- having to actually send any requests to a real server.
12 module Commands (main) where
14 import Network.MPD.Commands
15 import Network.MPD.Core (Response, MPDError(..))
16 import Network.MPD.StringConn
18 import Control.Monad
19 import Prelude hiding (repeat)
20 import Text.Printf
22 main = mapM_ (\(n, f) -> f >>= \x -> printf "%-14s: %s\n" n x) tests
23 where tests = [("enableOutput", testEnableOutput)
24 ,("disableOutput", testDisableOutput)
25 ,("outputs", testOutputs)
26 ,("update0", testUpdate0)
27 ,("update1", testUpdate1)
28 ,("updateMany", testUpdateMany)
29 ,("find", testFind)
30 ,("list(Nothing)", testListNothing)
31 ,("list(Just)", testListJust)
32 ,("listAll", testListAll)
33 ,("lsInfo", testLsInfo)
34 ,("listAllInfo", testListAllInfo)
35 ,("search", testSearch)
36 ,("count", testCount)
37 ,("add", testAdd)
38 ,("add_", testAdd_)
39 ,("addId", testAddId)
40 ,("clear", testClear)
41 ,("plChangesPosId 0", testPlChangesPosId_0)
42 ,("plChangesPosId 1", testPlChangesPosId_1)
43 ,("plChangesPosId wierd", testPlChangesPosId_Wierd)
44 ,("currentSong(_)", testCurrentSongStopped)
45 ,("currentSong(>)", testCurrentSongPlaying)
46 ,("delete0", testDelete0)
47 ,("delete1", testDelete1)
48 ,("delete2", testDelete2)
49 ,("load", testLoad)
50 ,("move0", testMove0)
51 ,("move1", testMove1)
52 ,("move2", testMove2)
53 ,("rm", testRm)
54 ,("rename", testRename)
55 ,("save", testSave)
56 ,("swap0", testSwap0)
57 ,("swap1", testSwap1)
58 ,("shuffle", testShuffle)
59 ,("playlistInfo0", testPlaylistInfo0)
60 ,("playlistInfo / pos", testPlaylistInfoPos)
61 ,("playlistInfo / id", testPlaylistInfoId)
62 ,("listPlaylistInfo", testListPlaylistInfo)
63 ,("listPlaylist", testListPlaylist)
64 ,("crossfade", testCrossfade)
65 ,("play", testPlay)
66 ,("play / pos", testPlayPos)
67 ,("play / id", testPlayId)
68 ,("pause", testPause)
69 ,("stop", testStop)
70 ,("next", testNext)
71 ,("previous", testPrevious)
72 ,("random", testRandom)
73 ,("repeat", testRepeat)
74 ,("setVolume", testSetVolume)
75 ,("volume", testVolume)
76 ,("clearError", testClearError)
77 ,("commands", testCommands)
78 ,("notCommands", testNotCommands)
79 ,("tagTypes", testTagTypes)
80 ,("urlHandlers", testUrlHandlers)
81 ,("password", testPassword)
82 ,("ping", testPing)
83 ,("song parsing / incomplete track",
84 testSongParseIncompleteTrack)
85 ,("song parsing / complete track",
86 testSongParseCompleteTrack)
89 test a b c = liftM (showResult b) $ testMPD a b (return Nothing) c
91 test_ a b = test a (Right ()) b
93 showResult :: (Show a) => Response a -> Result a -> String
94 showResult _ Ok = "passed"
95 showResult expectedResult (Failure result mms) =
96 "*** FAILURE ***" ++
97 concatMap (\(x,y) -> "\n expected request: " ++ show x ++
98 "\n actual request: " ++ show y) mms ++
99 "\n expected result: " ++ show expectedResult ++
100 "\n actual result: " ++ show result
102 emptySong = Song { sgArtist = ""
103 , sgAlbum = ""
104 , sgTitle = ""
105 , sgFilePath = ""
106 , sgGenre = ""
107 , sgName = ""
108 , sgComposer = ""
109 , sgPerformer = ""
110 , sgLength = 0
111 , sgDate = 0
112 , sgTrack = (0,0)
113 , sgDisc = (0,0)
114 , sgIndex = Nothing }
117 -- Parser behaviour.
118 -- These tests are meant to expose problems with internal
119 -- parsers.
122 -- Should handle track = 'X'.
123 testSongParseIncompleteTrack =
124 test [("find Artist \"Foo\"", Right "file: dir/Foo-Bar.ogg\n\
125 \Track: 1\n\
126 \OK")]
127 (Right [emptySong { sgTrack = (1,1)
128 , sgFilePath = "dir/Foo-Bar.ogg"
130 (find $ Query Artist "Foo")
132 -- Should handle track = 'X/Y'.
133 testSongParseCompleteTrack =
134 test [("find Artist \"Foo\"", Right "file: dir/Foo-Bar.ogg\n\
135 \Track: 2/12\n\
136 \OK")]
137 (Right [emptySong { sgTrack = (2,12)
138 , sgFilePath = "dir/Foo-Bar.ogg"
140 (find $ Query Artist "Foo")
143 -- Admin commands
146 testEnableOutput = test_ [("enableoutput 1", Right "OK")] (enableOutput 1)
148 testDisableOutput = test_ [("disableoutput 1", Right "OK")] (disableOutput 1)
150 testOutputs =
151 test [("outputs", Right $ unlines ["outputid: 0"
152 ,"outputname: SoundCard0"
153 ,"outputenabled: 1"
154 ,"outputid: 1"
155 ,"outputname: SoundCard1"
156 ,"outputenabled: 0"
157 ,"OK"])]
158 (Right [Device { dOutputID = 0
159 , dOutputName = "SoundCard0"
160 , dOutputEnabled = True }
161 ,Device { dOutputID = 1
162 , dOutputName = "SoundCard1"
163 , dOutputEnabled = False }])
164 outputs
166 testUpdate0 = test_ [("update", Right "updating_db: 1\nOK")] (update [])
168 testUpdate1 =
169 test_ [("update \"foo\"", Right "updating_db: 1\nOK")]
170 (update ["foo"])
172 testUpdateMany =
173 test_ [("command_list_begin\nupdate \"foo\"\nupdate \"bar\"\n\
174 \command_list_end", Right "updating_db: 1\nOK")]
175 (update ["foo","bar"])
178 -- Database commands
181 testFind =
182 test [("find Artist \"Foo\"", Right "file: dir/Foo-Bar.ogg\n\
183 \Time: 60\n\
184 \Artist: Foo\n\
185 \Title: Bar\n\
186 \OK")]
187 (Right [Song { sgArtist = "Foo"
188 , sgAlbum = ""
189 , sgTitle = "Bar"
190 , sgFilePath = "dir/Foo-Bar.ogg"
191 , sgGenre = ""
192 , sgName = ""
193 , sgComposer = ""
194 , sgPerformer = ""
195 , sgLength = 60
196 , sgDate = 0
197 , sgTrack = (0,0)
198 , sgDisc = (0,0)
199 , sgIndex = Nothing
201 (find (Query Artist "Foo"))
203 testListNothing =
204 test [("list Title", Right "Title: Foo\nTitle: Bar\nOK")]
205 (Right ["Foo", "Bar"])
206 (list Title Nothing)
208 testListJust =
209 test [("list Title Artist \"Muzz\"", Right "Title: Foo\nOK")]
210 (Right ["Foo"])
211 (list Title (Just $ Query Artist "Muzz"))
213 testListAll =
214 test [("listall \"\"", Right "directory: FooBand\n\
215 \directory: FooBand/album1\n\
216 \file: FooBand/album1/01 - songA.ogg\n\
217 \file: FooBand/album1/02 - songB.ogg\nOK")]
218 (Right ["FooBand/album1/01 - songA.ogg"
219 ,"FooBand/album1/02 - songB.ogg"])
220 (listAll "")
222 testLsInfo =
223 test [("lsinfo \"\"", Right "directory: Foo\ndirectory: Bar\nOK")]
224 (Right [Left "Bar", Left "Foo"])
225 (lsInfo "")
227 testListAllInfo =
228 test [("listallinfo \"\"", Right "directory: Foo\ndirectory: Bar\nOK")]
229 (Right [Left "Bar", Left "Foo"])
230 (listAllInfo "")
232 testSearch =
233 test [("search Artist \"oo\"", Right "file: dir/Foo-Bar.ogg\n\
234 \Time: 60\n\
235 \Artist: Foo\n\
236 \Title: Bar\n\
237 \OK")]
238 (Right [Song { sgArtist = "Foo"
239 , sgAlbum = ""
240 , sgTitle = "Bar"
241 , sgFilePath = "dir/Foo-Bar.ogg"
242 , sgGenre = ""
243 , sgName = ""
244 , sgComposer = ""
245 , sgPerformer = ""
246 , sgLength = 60
247 , sgDate = 0
248 , sgTrack = (0,0)
249 , sgDisc = (0,0)
250 , sgIndex = Nothing
252 (search (Query Artist "oo"))
254 testCount =
255 test [("count Title \"Foo\"", Right "songs: 1\nplaytime: 60\nOK")]
256 (Right (Count 1 60))
257 (count (Query Title "Foo"))
260 -- Playlist commands
263 testAdd =
264 test [("add \"foo\"", Right "OK"),
265 ("listall \"foo\"", Right "file: Foo\nfile: Bar\nOK")]
266 (Right ["Foo", "Bar"])
267 (add "" "foo")
269 testAdd_ = test_ [("add \"foo\"", Right "OK")] (add_ "" "foo")
271 testAddId =
272 test [("addid \"dir/Foo-Bar.ogg\"", Right "Id: 20\nOK")]
273 (Right 20)
274 (addId "dir/Foo-Bar.ogg")
276 testClear = test_ [("playlistclear \"foo\"", Right "OK")] (clear "foo")
278 testPlChangesPosId_0 =
279 test [("plchangesposid 10", Right "OK")]
280 (Right [])
281 (plChangesPosId 10)
283 testPlChangesPosId_1 =
284 test [("plchangesposid 10", Right "cpos: 0\nId: 20\nOK")]
285 (Right [(Pos 0, ID 20)])
286 (plChangesPosId 10)
288 testPlChangesPosId_Wierd =
289 test [("plchangesposid 10", Right "cpos: foo\nId: bar\nOK")]
290 (Left $ Unexpected "[(\"cpos\",\"foo\"),(\"Id\",\"bar\")]")
291 (plChangesPosId 10)
293 testCurrentSongStopped =
294 test [("status", Right "repeat: 0\n\
295 \random: 0\n\
296 \playlist: 253\n\
297 \playlistlength: 0\n\
298 \xfade: 0\n\
299 \state: stop\nOK")]
300 (Right Nothing)
301 (currentSong)
303 testCurrentSongPlaying =
304 test [("status", Right "volume: 80\n\
305 \repeat: 0\n\
306 \random: 0\n\
307 \playlist: 252\n\
308 \playlistlength: 21\n\
309 \xfade: 0\n\
310 \state: play\n\
311 \song: 20\n\
312 \songid: 238\n\
313 \time: 158:376\n\
314 \bitrate: 192\n\
315 \audio: 44100:16:2\n\
316 \OK")
317 ,("currentsong", Right "file: dir/Foo-Bar.ogg\n\
318 \Time: 60\n\
319 \Artist: Foo\n\
320 \Title: Bar\n\
321 \OK")]
322 (Right . Just $ Song { sgArtist = "Foo"
323 , sgAlbum = ""
324 , sgTitle = "Bar"
325 , sgFilePath = "dir/Foo-Bar.ogg"
326 , sgGenre = ""
327 , sgName = ""
328 , sgComposer = ""
329 , sgPerformer = ""
330 , sgLength = 60
331 , sgDate = 0
332 , sgTrack = (0,0)
333 , sgDisc = (0,0)
334 , sgIndex = Nothing
336 (currentSong)
338 testDelete0 = test_ [("delete 1", Right "OK")] (delete "" (Pos 1))
340 testDelete1 = test_ [("deleteid 1", Right "OK")] (delete "" (ID 1))
342 testDelete2 = test_ [("playlistdelete \"foo\" 1", Right "OK")] (delete "foo" (Pos 1))
344 testLoad = test_ [("load \"foo\"", Right "OK")] (load "foo")
346 testMove0 = test_ [("move 1 2", Right "OK")] (move "" (Pos 1) 2)
348 testMove1 = test_ [("moveid 1 2", Right "OK")] (move "" (ID 1) 2)
350 testMove2 = test_ [("playlistmove \"foo\" 1 2", Right "OK")] (move "foo" (Pos 1) 2)
352 testRm = test_ [("rm \"foo\"", Right "OK")] (rm "foo")
354 testRename = test_ [("rename \"foo\" \"bar\"", Right "OK")] (rename "foo" "bar")
356 testSave = test_ [("save \"foo\"", Right "OK")] (save "foo")
358 testSwap0 = test_ [("swap 1 2", Right "OK")] (swap (Pos 1) (Pos 2))
360 testSwap1 = test_ [("swapid 1 2", Right "OK")] (swap (ID 1) (ID 2))
362 testShuffle = test_ [("shuffle", Right "OK")] shuffle
364 testPlaylistInfo0 = test [("playlistinfo", Right "file: dir/Foo-Bar.ogg\n\
365 \Time: 60\n\
366 \Artist: Foo\n\
367 \Title: Bar\n\
368 \OK")]
369 (Right [emptySong { sgFilePath = "dir/Foo-Bar.ogg"
370 , sgLength = 60
371 , sgArtist = "Foo"
372 , sgTitle = "Bar" }])
373 (playlistInfo Nothing)
375 testPlaylistInfoPos = test [("playlistinfo 1", Right "file: dir/Foo-Bar.ogg\n\
376 \Time: 60\n\
377 \Artist: Foo\n\
378 \Title: Bar\n\
379 \OK")]
380 (Right [emptySong { sgFilePath = "dir/Foo-Bar.ogg"
381 , sgLength = 60
382 , sgArtist = "Foo"
383 , sgTitle = "Bar" }])
384 (playlistInfo . Just $ Pos 1)
386 testPlaylistInfoId = test [("playlistid 1", Right "file: dir/Foo-Bar.ogg\n\
387 \Time: 60\n\
388 \Artist: Foo\n\
389 \Title: Bar\n\
390 \OK")]
391 (Right [emptySong { sgFilePath = "dir/Foo-Bar.ogg"
392 , sgLength = 60
393 , sgArtist = "Foo"
394 , sgTitle = "Bar" }])
395 (playlistInfo . Just $ ID 1)
397 testListPlaylistInfo = test [("listplaylistinfo \"foo\""
398 ,Right "file: dir/Foo-Bar.ogg\n\
399 \Time: 60\n\
400 \Artist: Foo\n\
401 \Title: Bar\n\
402 \OK")]
403 (Right [emptySong { sgFilePath = "dir/Foo-Bar.ogg"
404 , sgLength = 60
405 , sgArtist = "Foo"
406 , sgTitle = "Bar" }])
407 (listPlaylistInfo "foo")
409 testListPlaylist = test [("listplaylist \"foo\""
410 ,Right "file: dir/Foo-bar.ogg\n\
411 \file: dir/Quux-quuz.ogg\n\
412 \OK")]
413 (Right ["dir/Foo-bar.ogg", "dir/Quux-quuz.ogg"])
414 (listPlaylist "foo")
417 -- Playback commands
420 testCrossfade = test_ [("crossfade 0", Right "OK")] (crossfade 0)
422 testPlay = test_ [("play", Right "OK")] (play Nothing)
424 testPlayPos = test_ [("play 1", Right "OK")] (play . Just $ Pos 1)
426 testPlayId = test_ [("playid 1", Right "OK")] (play . Just $ ID 1)
428 testPause = test_ [("pause 0", Right "OK")] (pause False)
430 testStop = test_ [("stop", Right "OK")] stop
432 testNext = test_ [("next", Right "OK")] next
434 testPrevious = test_ [("previous", Right "OK")] previous
436 testRandom = test_ [("random 0", Right "OK")] (random False)
438 testRepeat = test_ [("repeat 0", Right "OK")] (repeat False)
440 testSetVolume = test_ [("setvol 10", Right "OK")] (setVolume 10)
442 testVolume = test_ [("volume 10", Right "OK")] (volume 10)
445 -- Miscellaneous commands
448 testClearError = test_ [("clearerror", Right "OK")] clearError
450 testCommands =
451 test [("commands", Right "command: foo\ncommand: bar")]
452 (Right ["foo", "bar"])
453 commands
455 testNotCommands =
456 test [("notcommands", Right "command: foo\ncommand: bar")]
457 (Right ["foo", "bar"])
458 notCommands
460 testTagTypes =
461 test [("tagtypes", Right "tagtype: foo\ntagtype: bar")]
462 (Right ["foo", "bar"])
463 tagTypes
465 testUrlHandlers =
466 test [("urlhandlers", Right "urlhandler: foo\nurlhandler: bar")]
467 (Right ["foo", "bar"])
468 urlHandlers
470 testPassword = test_ [("password foo", Right "OK")] (password "foo")
472 testPing = test_ [("ping", Right "OK")] ping
475 -- Extensions\/shortcuts