|
@@ -4,13 +4,10 @@ module LimitedInput where
|
|
|
|
|
|
import Distribution.TestSuite
|
|
|
import Base (simpleTest)
|
|
|
-import System.IO.Error
|
|
|
import System.IO.Uniform.ByteString
|
|
|
import qualified System.IO.Uniform.Streamline as S
|
|
|
-import System.Timeout (timeout)
|
|
|
import Data.ByteString (ByteString)
|
|
|
import qualified Data.ByteString as BS
|
|
|
-import qualified Data.ByteString.Char8 as C8
|
|
|
import qualified Data.Attoparsec.ByteString as A
|
|
|
import Control.Monad
|
|
|
|
|
@@ -21,33 +18,40 @@ tests = return [
|
|
|
simpleTest "runAttoparsec" $ recvTest False "abcedefghijklmnopqrstuvwxyz" 3 $ runParser parseAlphabet,
|
|
|
simpleTest "recieveLine" $ recvTest True "A test\n" 3 S.recieveLine,
|
|
|
simpleTest "recieveN" $ recvTest True "A test\n" 3 $ S.recieveN 30,
|
|
|
- simpleTest "runAttoparsec" $ recvTest True "abcedefghijklmnopqrstuvwxyz" 3 $ runParser parseAlphabet
|
|
|
+ simpleTest "runAttoparsec" $ recvTest True "abcedefghijklmnopqrstuvwxyz" 3 $ runParser parseAlphabet,
|
|
|
+ simpleTest "Attoparsec failure gets pushed back" attoparsecPushBack
|
|
|
]
|
|
|
|
|
|
recvTest :: Bool -> ByteString -> Int -> S.Streamline IO ByteString -> IO Progress
|
|
|
-recvTest readFirst input limit f = do
|
|
|
- r <- tryIOError $ test readFirst
|
|
|
- case r of
|
|
|
- Left e -> return . Finished . Fail $ "IO error: " ++ show e
|
|
|
- Right v -> return v
|
|
|
- where
|
|
|
- test recv = do
|
|
|
- to <- timeout 1000000 $ do
|
|
|
- (r, _) <- withByteStringIO input $ \t -> do
|
|
|
- S.withTarget t $ do
|
|
|
- when recv $ S.recieveN 1 >> return ()
|
|
|
- S.limitInput limit
|
|
|
- f
|
|
|
- let extra = if readFirst then 1 else 0
|
|
|
- if BS.length r <= limit + extra
|
|
|
- then return . Finished $ Pass
|
|
|
- else return . Finished . Fail $ "Got too much text: " ++ show r
|
|
|
- case to of
|
|
|
- Nothing -> return . Finished . Fail $ "Execution blocked"
|
|
|
- Just v -> return v
|
|
|
+recvTest readFirst input limit f = fstIO $ withByteStringIO input $ \t -> S.withTarget t $ do
|
|
|
+ when readFirst $ S.recieveN 1 >> return ()
|
|
|
+ S.limitInput limit
|
|
|
+ r <- f
|
|
|
+ let extra = if readFirst then 1 else 0
|
|
|
+ if BS.length r <= limit + extra
|
|
|
+ then return . Finished $ Pass
|
|
|
+ else return . Finished . Fail $ "Got too much text: " ++ show r
|
|
|
+
|
|
|
+fstIO :: IO (a, b) -> IO a
|
|
|
+fstIO f = fst <$> f
|
|
|
+
|
|
|
+alphabet :: ByteString
|
|
|
+alphabet = "abcedefghijklmnopqrstuvwxyz"
|
|
|
|
|
|
parseAlphabet :: A.Parser ByteString
|
|
|
-parseAlphabet = A.string "abcedefghijklmnopqrstuvwxyz"
|
|
|
+parseAlphabet = A.string alphabet
|
|
|
+
|
|
|
+parseNotAlphabet :: A.Parser ByteString
|
|
|
+parseNotAlphabet = A.string . BS.reverse $ alphabet
|
|
|
|
|
|
runParser :: A.Parser ByteString -> S.Streamline IO ByteString
|
|
|
runParser p = fst <$> S.runAttoparsecAndReturn p
|
|
|
+
|
|
|
+attoparsecPushBack :: IO Progress
|
|
|
+attoparsecPushBack = fstIO $ withByteStringIO alphabet $ \t -> S.withTarget t $ do
|
|
|
+ S.runAttoparsec parseNotAlphabet
|
|
|
+ abc <- S.recieveN 3
|
|
|
+ if abc == "abc"
|
|
|
+ then return . Finished $ Pass
|
|
|
+ else return . Finished . Fail $ "Read wrong data: " ++ show abc
|
|
|
+
|