packages feed

hspec-server 0.2.2 → 0.3.0

raw patch · 6 files changed

+148/−130 lines, 6 filesdep +hspec-contribPVP ok

version bump matches the API change (PVP)

Dependencies added: hspec-contrib

API changes (from Hackage documentation)

- Test.Hspec.Server.Core: describe :: ServerType dat => String -> ServerSpec dat -> ServerSpec dat
- Test.Hspec.Server.Core: it :: ServerType dat => String -> ServerExample dat () -> ServerSpec dat
- Test.Hspec.Server.Core: serverSpec :: ServerType dat => dat -> ServerSpec dat -> Spec
- Test.Hspec.Server.Core: serverSpecOS :: ServerType dat => dat -> ServerOS -> ServerSpec dat -> Spec
- Test.Hspec.Server.Type: ServerExampleData :: !dat -> !ServerOS -> ServerExampleData dat
- Test.Hspec.Server.Type: ServerSpecGroup :: String -> [ServerSpecTree dat] -> ServerSpecTree dat
- Test.Hspec.Server.Type: ServerSpecItem :: String -> (ServerExample dat ()) -> ServerSpecTree dat
- Test.Hspec.Server.Type: cmd :: ServerType a => a -> FilePath -> [String] -> String -> IO (ExitCode, String, String)
- Test.Hspec.Server.Type: data ServerExampleData dat
- Test.Hspec.Server.Type: data ServerSpecTree dat
- Test.Hspec.Server.Type: instance ServerType dat => Example (ServerExample dat a)
- Test.Hspec.Server.Type: name :: ServerType a => a -> ServerName
- Test.Hspec.Server.Type: serverData :: ServerExampleData dat -> !dat
- Test.Hspec.Server.Type: serverOS :: ServerExampleData dat -> !ServerOS
- Test.Hspec.Server.Type: setup :: ServerType a => a -> IO a
- Test.Hspec.Server.Type: type ServerSpec dat = Writer [ServerSpecTree dat] ()
+ Test.Hspec.Server.Core: (@==) :: (ServerType dat, Sets s) => ServerExample dat s -> s -> ServerExample dat ()
+ Test.Hspec.Server.Core: (@>=) :: (ServerType dat, Sets s) => ServerExample dat s -> s -> ServerExample dat ()
+ Test.Hspec.Server.ServerType: lOS :: Localhost -> !(Maybe ServerOS)
+ Test.Hspec.Server.ServerType: sshOS :: Ssh -> !(Maybe ServerOS)
+ Test.Hspec.Server.ServerType: vOS :: Vagrant -> !(Maybe ServerOS)
+ Test.Hspec.Server.Type: instance ServerType dat => Example (ServerExample dat ())
+ Test.Hspec.Server.Type: stCmd :: ServerType a => a -> FilePath -> [String] -> String -> IO (ExitCode, String, String)
+ Test.Hspec.Server.Type: stName :: ServerType a => a -> ServerName
+ Test.Hspec.Server.Type: stOS :: ServerType a => a -> Maybe ServerOS
+ Test.Hspec.Server.Type: stSetup :: ServerType a => a -> IO a
+ Test.Hspec.Server.Type: with :: ServerType dat => dat -> SpecWith dat -> Spec
- Test.Hspec.Server.Core: getServerOS :: ServerExample dat ServerOS
+ Test.Hspec.Server.Core: getServerOS :: ServerType dat => ServerExample dat (Maybe ServerOS)
- Test.Hspec.Server.ServerType: Localhost :: Localhost
+ Test.Hspec.Server.ServerType: Localhost :: !(Maybe ServerOS) -> Localhost
- Test.Hspec.Server.ServerType: Ssh :: String -> Maybe String -> Maybe String -> Maybe Int -> Maybe String -> Ssh
+ Test.Hspec.Server.ServerType: Ssh :: String -> Maybe String -> Maybe String -> Maybe Int -> Maybe String -> !(Maybe ServerOS) -> Ssh
- Test.Hspec.Server.ServerType: Vagrant :: String -> Maybe String -> Vagrant
+ Test.Hspec.Server.ServerType: Vagrant :: String -> Maybe String -> !(Maybe ServerOS) -> Vagrant
- Test.Hspec.Server.Type: class Show a => Sets a
+ Test.Hspec.Server.Type: class (Eq a, Show a) => Sets a
- Test.Hspec.Server.Type: type ServerExample dat = StateT (ServerExampleData dat) IO
+ Test.Hspec.Server.Type: type ServerExample dat = ReaderT dat IO

Files

Test/Hspec/Server/Command.hs view
@@ -1,4 +1,10 @@-module Test.Hspec.Server.Command where+module Test.Hspec.Server.Command (+  package+, process+, service+, port+, command+  )where  import System.Exit import Control.Monad@@ -8,15 +14,50 @@ import Test.Hspec.Server.Type import Test.Hspec.Server.Core +cmd :: ServerType dat => dat -> FilePath -> [String] -> String -> IO (ExitCode,String,String)+cmd = stCmd++type Patterns = [String]+type Arg = [String]+type Input = String+type TestType = String+type TestedName = String++cmdAndChk :: (ServerType dat, Sets s)+          => TestType+          -> s+          -> s+          -> FilePath +          -> Arg+          -> Input+          -> Patterns+          -> ServerExample dat (Either String s)+cmdAndChk test testedval failedval c arg i [] = do+  dat <- getServerData+  c@(code,out,_) <- liftIO $ cmd dat c arg i+  if (code /= ExitSuccess) +    then return $ Left $ test <> " error:" ++ show c+    else return $ Right testedval+cmdAndChk test testedval failedval c arg i patterns = do+  dat <- getServerData+  c@(code,out,_) <- liftIO $ cmd dat c arg i+  if (code /= ExitSuccess) +    then do +      return $ Left $ test <> " error:" ++ show c+    else do+      if or (map (\v -> foldr (||) False +                               (map (\p -> v =~ p) patterns)+                  )+                 (lines out))+        then return $ Right testedval+        else return $ Right failedval+ package :: ServerType dat => String -> ServerExample dat ServerStatus package pkg = do-  dat <- getServerData-  c@(code,out,_) <- liftIO $ cmd dat "dpkg" ["-l",pkg] []-  when (code /= ExitSuccess) $ do-    error $ "pacakge error:" ++ show c-  if or (map (\v -> v  =~ ("^ii +" <> pkg <> " ")) (lines out))-    then return Installed-    else return None+  r <- cmdAndChk "package" Installed None "dpkg" ["-l",pkg] [] ["^ii +"<>pkg<>" "]+  case r of+    Left err -> error err+    Right v -> return v  process :: ServerType dat => String -> ServerExample dat ServerStatus process ps = do@@ -29,28 +70,32 @@ service :: ServerType dat => String -> ServerExample dat ServerStatus service s = do   dat <- getServerData-  c@(code,out,_) <- liftIO $ cmd dat ("/etc/init.d/"++s) ["status"] []-  when (code /= ExitSuccess) $ do-    error $ "service error:" ++ show c-  if or (map (\v ->-               (v  =~ ("is running" :: String)) ||-               (v  =~ ("start/running" :: String))-             ) (lines out))-    then return Running-    else return None+  (_code,_out,_) <- liftIO $ cmd dat ("/etc/init.d/"++s) ["status"] []+  if _code == ExitSuccess +    then check _out+    else do+      c@(code,out,_) <- liftIO $ cmd dat "sudo" ["service",s,"status"] []+      when (code /= ExitSuccess) $ do+        error $ "service error:" ++ show c+      check out+  where+    check out = +      if or (map (\v ->+                   (v  =~ ("is running" :: String)) ||+                   (v  =~ ("start/running" :: String))+                 ) (lines out))+        then return Running+        else return None  port :: ServerType dat => Int -> ServerExample dat ServerStatus port p = do-  dat <- getServerData-  c@(code,out,_) <- liftIO $ cmd dat "netstat" ["-tanp"] []-  when (code /= ExitSuccess) $ do-    error $ "port error:" ++ show c-  if or (map (\v ->-               (v  =~ ("^tcp[ 6] +[0-9]+ +[0-9]+ :::" <> show p <> " +[^ ]+ +LISTEN")) ||-               (v  =~ ("^tcp[ 6] +[0-9]+ +[0-9]+ [0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+:" <> show p <> " +[^ ]+ +LISTEN"))-             ) (lines out))-    then return Listening-    else return None+  r <- cmdAndChk "port"  Listening None +           "netstat" ["-tanp"] [] +           ["^tcp[ 6] +[0-9]+ +[0-9]+ :::" <> (show p) <> " +[^ ]+ +LISTEN",+            "^tcp[ 6] +[0-9]+ +[0-9]+ [0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+:" <> (show p) <> " +[^ ]+ +LISTEN"]+  case r of+    Left err -> error err+    Right v -> return v  command :: ServerType dat => FilePath -> [String] -> String -> ServerExample dat CommandStatus command c arg inp = do
Test/Hspec/Server/Core.hs view
@@ -1,54 +1,19 @@  module Test.Hspec.Server.Core where -import qualified Test.Hspec.Core.Spec as Hspec+import qualified Test.Hspec as Hspec import qualified Test.HUnit as HUnit-import Control.Monad.Trans.Writer import Control.Monad.IO.Class-import qualified Control.Monad.Trans.State as ST+import Control.Monad.Trans.Reader import Test.Hspec.Server.Type -serverSpecOS :: ServerType dat-           => dat-           -> ServerOS-           -> ServerSpec dat-           -> Hspec.Spec-serverSpecOS serverData' serverOS' sspecs = do-    dat' <- Hspec.runIO $ setup serverData'-    os' <- case serverOS' of-             AutoDetect -> do-               v <- Hspec.runIO $ detectOS dat'-               case v of-                 Just v' -> return v'-                 Nothing -> error "can not detect os"-             _ -> return serverOS'-    Hspec.fromSpecList $ map (unServer (dat',os')) $ execWriter sspecs-  where-    unServer (dat',os') (ServerSpecGroup x y) = Hspec.specGroup x $ map (unServer (dat',os')) y-    unServer (dat',os') (ServerSpecItem x y) = Hspec.specItem x $ -        ST.evalStateT y ServerExampleData {-            serverData = dat'-          , serverOS = os'-         }--serverSpec :: ServerType dat-           => dat-           -> ServerSpec dat-           -> Hspec.Spec-serverSpec serverData' sspecs = do-  serverSpecOS serverData' AutoDetect sspecs- getServerData :: ServerType dat => ServerExample dat dat-getServerData = fmap serverData ST.get--getServerOS :: ServerExample dat ServerOS-getServerOS = fmap serverOS ST.get--it :: ServerType dat => String -> ServerExample dat () -> ServerSpec dat-it label example = tell [ServerSpecItem label example]+getServerData = ask -describe :: ServerType dat => String -> ServerSpec dat -> ServerSpec dat-describe label sspecs = tell [ServerSpecGroup label $ execWriter sspecs]+getServerOS :: ServerType dat => ServerExample dat (Maybe ServerOS)+getServerOS = do +  d <- ask+  return $ stOS d  includes' :: (ServerType dat, Sets s) => s -> s -> ServerExample dat () includes' org ex =@@ -62,3 +27,12 @@   org <- org'   org `includes'` ex +(@>=) :: (ServerType dat, Sets s) => ServerExample dat s -> s -> ServerExample dat ()+(@>=) = includes+infix 1 @>= ++(@==) :: (ServerType dat, Sets s) => ServerExample dat s -> s -> ServerExample dat ()+(@==) org' ex = do+  org <- org'+  liftIO $ Hspec.shouldBe org ex+infix 1 @== 
Test/Hspec/Server/ServerType.hs view
@@ -9,15 +9,20 @@ import Control.Monad import Test.Hspec.Server.Type -data Localhost = Localhost deriving (Show,Eq)+data Localhost = Localhost {+  lOS :: !(Maybe ServerOS)+  }deriving (Show,Eq)  localhost :: Localhost-localhost = Localhost+localhost = Localhost Nothing  instance ServerType Localhost where-  setup a = return a-  name _ = "localhost"-  cmd _ = readProcessWithExitCode+  stSetup a = do+    os' <- detectOS a+    return $ a {lOS = os'}+  stOS = lOS+  stName _ = "localhost"+  stCmd _ = readProcessWithExitCode  data Ssh = Ssh {   sshHostName :: String@@ -25,15 +30,19 @@ , sshConf :: Maybe String , sshPort :: Maybe Int , sshUser :: Maybe String+, sshOS :: !(Maybe ServerOS) } deriving (Show,Eq)  ssh :: String -> Ssh-ssh hostname = Ssh hostname Nothing Nothing Nothing Nothing+ssh hostname = Ssh hostname Nothing Nothing Nothing Nothing Nothing  instance ServerType Ssh where-  setup a = return a-  name = sshHostName-  cmd d c arg i = do+  stSetup a = do+    os' <- detectOS a+    return $ a {sshOS = os'}+  stOS = sshOS+  stName = sshHostName+  stCmd d c arg i = do     readProcessWithExitCode "ssh" (sshOpt ++ [sshHost] ++ [c] ++ arg) i     where       sshOpt =@@ -45,20 +54,23 @@ data Vagrant = Vagrant {    vHostName :: String  , vConf :: Maybe String+ , vOS :: !(Maybe ServerOS) } deriving (Show,Eq)  vagrant :: String -> Vagrant-vagrant hostname = Vagrant hostname Nothing+vagrant hostname = Vagrant hostname Nothing Nothing  instance ServerType Vagrant where-  setup a = do+  stSetup a = do+    os' <- detectOS a     (e,conf,_) <- readProcessWithExitCode "vagrant" ["ssh-config"] []     when (e /= ExitSuccess) $ do       error "vagrant setup error"-    return $ a {vConf = Just conf}-  name = vHostName-  cmd d c arg i = withSystemTempFile "hspec-server" $ \file handle -> do+    return $ a {vConf = Just conf,vOS = os'}+  stOS = vOS+  stName = vHostName+  stCmd d c arg i = withSystemTempFile "hspec-server" $ \file handle -> do     hPutStr handle (fromJust (vConf d))     hClose handle-    readProcessWithExitCode "ssh" (["-F",file,name d,c]++arg) i+    readProcessWithExitCode "ssh" (["-F",file,stName d,c]++arg) i 
Test/Hspec/Server/Type.hs view
@@ -2,9 +2,10 @@ module Test.Hspec.Server.Type where  import System.Exit-import qualified Control.Monad.Trans.State as ST+import Control.Monad.Trans.Reader import Control.Monad.Trans.Writer import qualified Test.Hspec.Core.Spec as Hspec+import Test.Hspec (before)  import Control.Monad import Data.Monoid@@ -29,38 +30,25 @@ type ServerName = String  class ServerType a where-  setup :: a -> IO a-  name :: a -> ServerName-  cmd :: a -> FilePath -> [String] -> String -> IO (ExitCode,String,String)+  stSetup :: a -> IO a+  stOS :: a -> Maybe ServerOS+  stName :: a -> ServerName+  stCmd :: a -> FilePath -> [String] -> String -> IO (ExitCode,String,String) -data ServerExampleData dat = ServerExampleData {-    serverData :: !dat-  , serverOS :: !ServerOS-  }+type ServerExample dat = ReaderT dat IO -type ServerExample dat = ST.StateT (ServerExampleData dat) IO+with :: ServerType dat => dat -> Hspec.SpecWith dat -> Hspec.Spec+with d = before (stSetup d) -instance (ServerType dat) => Hspec.Example (ServerExample dat a) where-  type Arg (ServerExample dat a) = dat+instance (ServerType dat) => Hspec.Example (ServerExample dat ()) where+  type Arg (ServerExample dat ()) = dat   evaluateExample example params action =     Hspec.evaluateExample-      (action $ \dat' -> do-        os <- detectOS dat'-        _ <- ST.evalStateT example ServerExampleData {-            serverData = dat'-          , serverOS = fromJust os-          }-        return ())+      (action $ runReaderT example)       params       ($ ()) -type ServerSpec dat = Writer [ServerSpecTree dat] ()--data ServerSpecTree dat-    = ServerSpecGroup String [ServerSpecTree dat]-    | ServerSpecItem String (ServerExample dat ())--class Show a => Sets a where+class (Eq a ,Show a) => Sets a where   include :: a -> a -> Bool  data ServerStatus =@@ -112,18 +100,18 @@  getStdout :: CommandStatus -> Maybe String getStdout (Stdout code) = Just code-getStdout (CAnd statuss) = listToMaybe $ catMaybes $ map getStdout $ S.toList statuss+getStdout (CAnd statuss) = listToMaybe $ mapMaybe getStdout $ S.toList statuss getStdout _ = Nothing  getStderr :: CommandStatus -> Maybe String getStderr (Stderr code) = Just code-getStderr (CAnd statuss) = listToMaybe $ catMaybes $ map getStdout $ S.toList statuss+getStderr (CAnd statuss) = listToMaybe $ mapMaybe getStdout $ S.toList statuss getStderr _ = Nothing   detectOS :: ServerType dat => dat -> IO (Maybe ServerOS) detectOS dat = do-  v@(code,out,_) <- cmd dat "sh" ["-c","echo $OSTYPE"] []+  v@(code,out,_) <- stCmd dat "bash" ["-c","echo $OSTYPE"] []   when (code /= ExitSuccess) $ do     error $ "detectOS's error;" ++ show v   case listToMaybe (lines out) of@@ -143,7 +131,8 @@  detectLinux :: ServerType dat => dat -> IO (Maybe ServerOS) detectLinux dat = do-  (_code,_out,_) <- cmd dat "cat" ["/etc/lsb-release"] []+  let cmd = stCmd+  c@(_code,_out,_) <- cmd dat "cat" ["/etc/lsb-release"] []   if _code == ExitSuccess     then do       let tag = "DISTRIB_RELEASE="
hspec-server.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                hspec-server-version:             0.2.2+version:             0.3.0 synopsis:            Test Framework for Server's status description:         Hspec-Server is test framework for checking server's status.                      It is inspired by the Ruby library ServerSpec.@@ -49,7 +49,7 @@      build-depends: base                  , hspec-                 -- , hspec-contrib+                 , hspec-contrib                  , hspec-server                  , transformers     Default-Language:   Haskell2010
test/test.hs view
@@ -1,25 +1,23 @@-import Test.Hspec hiding (it,describe)+import Data.Monoid+import Test.Hspec import Test.Hspec.Server--- import Test.Hspec.Contrib.Retry+import Test.Hspec.Contrib.Retry import Control.Monad.IO.Class  main :: IO () main = hspec $ do-  serverSpec localhost $ do-    describe "hoge" $ do+    describe "hoge" $ with localhost $ do       it "package test" $ do-        dat <- getServerData-        os <- liftIO $ detectOS dat-        liftIO $ os `shouldBe` (Just $ Ubuntu "14.04")+        os <- getServerOS+        liftIO $ os `shouldBe` (Just $ Ubuntu "12.04")       it "package test" $ do-        package "zookeeper" `includes` Installed+        package "zookeeper" @>= Installed       it "port test" $ do-        port 2181 `includes` Listening+        port 2181 @>= Listening       it "service test" $ do-        service "cron" `includes` Running-        service "atd" `includes` Running+        service "zookeeper" @>= Running       it "command test" $ do-        command "ls" [] [] `includes` Exit 0-      -- it "retry test" $ do-      --   retryWith 10 $ --currently does not support Retry. I want to use retryWith !!!-      --     command "ls" [] [] `includes` Exit 0+        command "echo" ["hoge"] [] @>=  Exit 0 <> Stdout "hoge\n"+      it "retry test" $ do+        retryWith 10 $+          command "ls" [] [] @>= Exit 0