File: StringConn.hs

package info (click to toggle)
haskell-libmpd 0.10.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 328 kB
  • sloc: haskell: 2,776; makefile: 3
file content (77 lines) | stat: -rw-r--r-- 2,772 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}
{-# OPTIONS_GHC -Wwarn #-}

-- |
-- Module      : StringConn
-- Copyright   : (c) Ben Sinclair 2005-2009
-- License     : MIT (see LICENSE)
-- Stability   : alpha
--
-- A testing scaffold for MPD commands

module StringConn where

import           Control.Applicative
import           Prelude hiding (exp)
import           Control.Monad
import           Control.Monad.Except
import           Control.Monad.Identity
import           Control.Monad.Reader
import           Control.Monad.State
import           Network.MPD.Core

import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.UTF8 as UTF8

-- | An expected request.
type Expect = String

data StringMPDError
    = TooManyRequests
    | UnexpectedRequest Expect String
      deriving (Show, Eq)

data Result a
    = Ok
    | BadResult (Response a) (Response a)  -- expected, then actual
    | BadRequest StringMPDError
      deriving (Show, Eq)

newtype StringMPD a =
    SMPD { runSMPD :: ExceptT MPDError
                      (StateT [(Expect, Response String)]
                       (ReaderT Password Identity)) a
         } deriving (Functor, Applicative, Monad, MonadError MPDError)

instance MonadMPD StringMPD where
    getVersion  = error "StringConn.getVersion: undefined"
    setPassword = error "StringConn.setPassword: undefined"

    open  = return ()
    close = return ()
    getPassword = SMPD ask
    send request =
        SMPD $ do
            ~pairs@((expected_request,response):rest) <- get
            when (null pairs)
                 (throwError $ Custom "too many requests")
            when (expected_request /= request)
                 (throwError . Custom $ "unexpected request: " ++ show request ++ ", expected: " ++ show expected_request)
            put rest
            either throwError (return . B.lines . UTF8.fromString) response

testMPD :: (Eq a) => [(Expect, Response String)] -> StringMPD a -> Response a
testMPD pairs m = testMPDWithPassword pairs "" m

-- | Run an action against a set of expected requests and responses,
-- and an expected result. The result is Nothing if everything matched
-- what was expected. If anything differed the result of the
-- computation is returned along with pairs of expected and received
-- requests.
testMPDWithPassword :: (Eq a)
        => [(Expect, Response String)] -- ^ The expected requests and their
                                       -- ^ corresponding responses.
        -> Password                    -- ^ A password to be supplied.
        -> StringMPD a                 -- ^ The MPD action to run.
        -> Response a
testMPDWithPassword pairs passwd m = runIdentity $ runReaderT (evalStateT (runExceptT $ runSMPD m) pairs) passwd