Blocking.hs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Blocking where
  3. import Distribution.TestSuite
  4. import Base (simpleTest)
  5. import Control.Concurrent(forkIO)
  6. import System.IO.Uniform.Network
  7. import qualified System.IO.Uniform.Streamline as S
  8. import System.Timeout (timeout)
  9. import Data.ByteString (ByteString)
  10. import qualified Data.ByteString as BS
  11. import qualified Data.ByteString.Char8 as C8
  12. import qualified Data.Attoparsec.ByteString as A
  13. --import Control.Monad.IO.Class (liftIO)
  14. --import Debug.Trace
  15. tests :: IO [Test]
  16. tests = return [
  17. simpleTest "recieveLine"
  18. (successTimeout "A test\n" (S.recieveLine)),
  19. simpleTest "runAttoparsec with successful parser"
  20. (successTimeout "abcde" (parseBS (A.string "abcde"))),
  21. simpleTest "runAttoparsec with failed parser"
  22. (failTimeout "abcde" (parseBS (A.string "c"))),
  23. simpleTest "lazyRecieveLine"
  24. (successTimeout "Another test\n" (concatLine S.lazyRecieveLine)),
  25. simpleTest "lazyReceiveN"
  26. (failTimeout "abcde" (concatLine (S.lazyRecieveN 5))),
  27. simpleTest "recieveTill"
  28. (failTimeout "abcde" (restoreLine $ S.recieveTill "de"))
  29. ]
  30. parseBS :: A.Parser ByteString -> S.Streamline IO ByteString
  31. parseBS p = do
  32. t <- S.runAttoparsec p
  33. case t of
  34. Left e -> return . C8.pack $ e
  35. Right s -> return s
  36. restoreLine :: S.Streamline IO ByteString -> S.Streamline IO ByteString
  37. restoreLine f = do
  38. l <- f
  39. return $ BS.concat [l, "\n"]
  40. concatLine :: S.Streamline IO [ByteString] -> S.Streamline IO ByteString
  41. concatLine f = do
  42. l <- f
  43. return . BS.concat $ l
  44. -- | Tests the given command, by sending a string to an echo and running the command.
  45. -- the command must not block.
  46. successTimeout :: ByteString -> S.Streamline IO ByteString -> IO Progress
  47. successTimeout txt f = do
  48. recv <- bindPort 8888
  49. forkIO $ S.withClient recv $ \_ _ ->
  50. do
  51. l <- f
  52. S.send l
  53. return ()
  54. r' <- timeout 1000000 $ S.withServer "127.0.0.1" 8888 $
  55. do
  56. S.send txt
  57. t <- f
  58. if t == txt
  59. then return . Finished $ Pass
  60. else return . Finished . Fail $ "Strings differ: " -- ++ show txt ++ " <> " ++ show t
  61. closePort recv
  62. case r' of
  63. Just r -> return r
  64. Nothing -> return . Finished . Fail $ "Execution blocked"
  65. -- | Tests the given command, by sending text trough the network and running it.
  66. -- Does not care about the result of the command, just wether it blocks.
  67. failTimeout :: ByteString -> S.Streamline IO ByteString -> IO Progress
  68. failTimeout txt f = do
  69. recv <- bindPort 8888
  70. forkIO $ S.withClient recv $ \_ _ ->
  71. do
  72. f
  73. S.send "\n"
  74. return ()
  75. r' <- timeout 1000000 $ S.withServer "127.0.0.1" 8888 $
  76. do
  77. S.send txt
  78. S.recieveLine
  79. return . Finished $ Pass
  80. closePort recv
  81. case r' of
  82. Just r -> return r
  83. Nothing -> return . Finished . Fail $ "Execution blocked"