Browse Source

add run tests

We lacked a test suite that even just tried connecting to a server and
bouncing a few stanzas back and forth. The "runtests" suite does just
that. It connects to 2 accounts on a server (set in a config
file ~/.pontarius-xmpp-tests/pontarius-xmpp-tests.conf) and tries
passing some messages and IQ stanzas back and forth. This should clear
the way for more interesting scenarios.
master
Philipp Balzarek 12 years ago
parent
commit
a5b6900972
  1. 22
      pontarius-xmpp.cabal
  2. 108
      tests/Run.hs
  3. 117
      tests/Run/Payload.hs
  4. 2
      tests/Tests/Arbitrary/Xmpp.hs
  5. 2
      tests/Tests/Parsers.hs
  6. 3
      tests/Tests/Picklers.hs

22
pontarius-xmpp.cabal

@ -168,6 +168,28 @@ Test-Suite doctest
, derive , derive
, quickcheck-instances , quickcheck-instances
Test-Suite runtests
Type: exitcode-stdio-1.0
hs-source-dirs: tests
main-is: Run.hs
other-modules: Run.Payload
GHC-Options: -Wall -threaded
Build-Depends: base
, HUnit
, configurator
, directory
, filepath
, hslogger
, hspec
, hspec-expectations
, mtl
, network
, pontarius-xmpp
, stm
, text
, xml-picklers
, xml-types
benchmark benchmarks benchmark benchmarks
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
build-depends: base build-depends: base

108
tests/Run.hs

@ -0,0 +1,108 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE LambdaCase #-}
module Main where
import Control.Applicative
import Control.Concurrent
import Control.Monad
import qualified Data.Configurator as Conf
import qualified Data.Configurator.Types as Conf
import Data.Maybe
import qualified Data.Text as Text
import Network
import Network.Xmpp
import System.Directory
import System.FilePath
import System.Log.Logger
import System.Timeout
import Test.HUnit
import Test.Hspec.Expectations
import Run.Payload
xmppConfig :: ConnectionDetails -> SessionConfiguration
xmppConfig det = def{sessionStreamConfiguration
= def{connectionDetails = det}
, onConnectionClosed = \sess _ -> do
_ <- reconnect' sess
_ <- sendPresence presenceOnline sess
return ()
}
-- | Load the configuration files
loadConfig :: IO Conf.Config
loadConfig = do
appData <- getAppUserDataDirectory "pontarius-xmpp-tests"
home <- getHomeDirectory
Conf.load [ Conf.Optional $ appData </> "pontarius-xmpp-tests.conf"
, Conf.Optional $ home </> ".pontarius-xmpp-tests.conf"
]
-- | reflect messages to their origin
reflect :: Session -> IO b
reflect sess = forever $ do
m <- getMessage sess
case answerMessage m (messagePayload m) of
Nothing -> return ()
Just am ->
void $ sendMessage am{messageAttributes = messageAttributes m} sess
testAttributes = [( "{org.pontarius.xmpp.test}testattr"
, "testvalue 12321 åäü>"
)]
main :: IO ()
main = void $ do
conf <- loadConfig
uname1 <- Conf.require conf "xmpp.user1"
pwd1 <- Conf.require conf "xmpp.password1"
uname2 <- Conf.require conf "xmpp.user1"
pwd2 <- Conf.require conf "xmpp.password1"
realm <- Conf.require conf "xmpp.realm"
server <- Conf.lookup conf "xmpp.server"
port <- Conf.lookup conf "xmpp.port" :: IO (Maybe Integer)
let conDetails = case server of
Nothing -> UseRealm
Just srv -> case port of
Nothing -> UseSrv srv
Just p -> UseHost srv (PortNumber $ fromIntegral p)
loglevel <- Conf.lookup conf "loglevel" >>= \case
(Nothing :: Maybe Text.Text) -> return ERROR
Just "debug" -> return DEBUG
Just "info" -> return INFO
Just "notice" -> return NOTICE
Just "warning" -> return WARNING
Just "error" -> return ERROR
Just "critical" -> return CRITICAL
Just "alert" -> return ALERT
Just "emergency" -> return EMERGENCY
Just e -> error $ "Log level " ++ (Text.unpack e) ++ " unknown"
updateGlobalLogger "Pontarius.Xmpp" $ setLevel loglevel
Right sess1 <- session realm (simpleAuth uname1 pwd1)
((xmppConfig conDetails))
Right sess2 <- session realm (simpleAuth uname2 pwd2)
((xmppConfig conDetails))
Just jid1 <- getJid sess1
Just jid2 <- getJid sess2
_ <- sendPresence presenceOnline sess1
_ <- forkIO $ reflect sess1
forkIO $ iqResponder sess1
_ <- sendPresence presenceOnline sess2
-- check message responsiveness
infoM "Pontarius.Xmpp" "Running message mirror"
sendMessage message{ messageTo = Just jid1
, messageAttributes = testAttributes
} sess2
resp <- timeout 3000000 $ waitForMessage (\m -> messageFrom m == Just jid1)
sess2
case resp of
Nothing -> assertFailure "Did not receive message answer"
Just am -> messageAttributes am `shouldBe` testAttributes
infoM "Pontarius.Xmpp" "Done running message mirror"
infoM "Pontarius.Xmpp" "Running IQ tests"
testPayload jid1 sess2
infoM "Pontarius.Xmpp" "Done running IQ tests"

117
tests/Run/Payload.hs

@ -0,0 +1,117 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE LambdaCase #-}
module Run.Payload where
import Control.Monad
import Control.Monad.STM
import qualified Data.Text as Text
import Data.XML.Pickle
import Data.XML.Types
import Network.Xmpp
import Network.Xmpp.Internal
import System.Log.Logger
import Test.HUnit hiding (Node)
import Test.Hspec.Expectations
data Payload = Payload
{ payloadCounter :: !Int
, ignoreFlag :: !Bool
, errorFlag :: !Bool
, payloadText :: !Text.Text
} deriving (Eq, Show)
testNS :: Text.Text
testNS = "xmpp:library:test"
payloadP :: PU [Node] Payload
payloadP = xpWrap (\((counter,iFlag, eFlag) , message)
-> Payload counter iFlag eFlag message)
(\(Payload counter iFlag eFlag message)
->((counter,iFlag, eFlag) , message)) $
xpElem (Name "request" (Just testNS) Nothing)
(xp3Tuple
(xpAttr "counter" xpPrim)
(xpAttr "ignoreFlag" xpPrim)
(xpAttr "errorFlag" xpPrim)
)
(xpElemNodes (Name "message" (Just testNS) Nothing)
(xpContent xpId))
invertPayload :: Payload -> Payload
invertPayload (Payload count _iFlag _eFlag message) =
Payload (count + 1) False False (Text.reverse message)
iqResponder :: Session -> IO ()
iqResponder context = do
chan' <- listenIQ Set testNS context
chan <- case chan' of
Left _ -> do
assertFailure "Channel was already taken"
undefined
Right c -> return c
forever $ do
next <- atomically $ chan
let Right payload = unpickleElem payloadP . iqRequestPayload $
iqRequestBody next
let answerPayload = invertPayload payload
let answerBody = pickleElem payloadP answerPayload
unless (ignoreFlag payload) . void $
case errorFlag payload of
False -> answerIQ next (Right $ Just answerBody) []
True -> answerIQ next (Left $ mkStanzaError NotAcceptable) []
testString :: Text.Text
testString = "abc ÄÖ>"
testPayload :: Jid -> Session -> IO ()
testPayload them session = do
infoM "Pontarius.Xmpp" "Testing IQ send/receive"
let pl1 = Payload 1 False False testString
body1 = pickleElem payloadP pl1
resp <- sendIQ' (Just 3000000) (Just them) Set Nothing body1 [] session
case resp of
Left e -> assertFailure $ "Could not send pl1" ++ show e
Right (IQResponseError e) ->
assertFailure $ "Unexpected IQ error" ++ show e
Right (IQResponseResult IQResult{iqResultPayload = Just pl}) -> do
case unpickleElem payloadP pl of
Left e -> assertFailure $ "Error unpickling response p1"
++ ppUnpickleError e
Right r -> do
payloadCounter r `shouldBe` 2
payloadText r `shouldBe` Text.reverse testString
Right (IQResponseResult _) ->
assertFailure "IQ result didn't contain payload"
infoM "Pontarius.Xmpp" "Done testing IQ send/receive"
----------------------
-- Timeout test
----------------------
let pl2 = Payload 2 True False testString
body2 = pickleElem payloadP pl2
infoM "Pontarius.Xmpp" "Testing timeout"
resp <- sendIQ' (Just 1000000) (Just them) Set Nothing body2 [] session
case resp of
Left IQTimeOut -> return ()
Left e -> assertFailure $ "Unexpected send error" ++ show e
Right r -> assertFailure $ "Unexpected IQ answer" ++ show r
infoM "Pontarius.Xmpp" "IQ timed out (as expected)"
----------------------
-- Error test
----------------------
infoM "Pontarius.Xmpp" "Testing IQ error"
let pl3 = Payload 3 False True testString
body3 = pickleElem payloadP pl3
resp <- sendIQ' (Just 3000000) (Just them) Set Nothing body3 [] session
case resp of
Left e -> assertFailure $ "Unexpected send error" ++ show e
Right (IQResponseError e) ->
stanzaErrorCondition (iqErrorStanzaError e) `shouldBe` NotAcceptable
Right r -> assertFailure $ "Received unexpected IQ response" ++ show r
infoM "Pontarius.Xmpp" "Received expected error"

2
tests/Tests/Arbitrary/Xmpp.hs

@ -5,7 +5,7 @@ import Control.Applicative ((<$>), (<*>))
import Data.Char import Data.Char
import Data.Maybe import Data.Maybe
import qualified Data.Text as Text import qualified Data.Text as Text
import Network.Xmpp.Types import Network.Xmpp.Internal hiding (elements)
import Test.QuickCheck import Test.QuickCheck
import Test.QuickCheck.Instances() import Test.QuickCheck.Instances()
import qualified Text.CharRanges as Ranges import qualified Text.CharRanges as Ranges

2
tests/Tests/Parsers.hs

@ -5,7 +5,7 @@
module Tests.Parsers where module Tests.Parsers where
import Control.Applicative ((<$>)) import Control.Applicative ((<$>))
import Network.Xmpp.Types import Network.Xmpp.Internal
import Test.Hspec import Test.Hspec
import Test.Tasty.QuickCheck import Test.Tasty.QuickCheck
import Test.Tasty import Test.Tasty

3
tests/Tests/Picklers.hs

@ -4,8 +4,7 @@ module Tests.Picklers where
import Tests.Arbitrary () import Tests.Arbitrary ()
import Data.XML.Pickle import Data.XML.Pickle
import Network.Xmpp.Marshal import Network.Xmpp.Internal
import Network.Xmpp.Types
import Test.Tasty import Test.Tasty
import Test.Tasty.TH import Test.Tasty.TH
import Test.Tasty.QuickCheck import Test.Tasty.QuickCheck

Loading…
Cancel
Save