@@ -9,7 +9,6 @@ import Data.Binary.Put ( runPut )
9import Data.Binary.Bits
9import Data.Binary.Bits
10import Data.Binary.Bits.Get
10import Data.Binary.Bits.Get
11import Data.Binary.Bits.Put
11import Data.Binary.Bits.Put
12−import Data.Binary.Bits.BitOrder
14import qualified Data.ByteString as B
13import qualified Data.ByteString as B
15import qualified Data.ByteString.Lazy as L
14import qualified Data.ByteString.Lazy as L
@@ -18,8 +17,7 @@ import Control.Applicative
18import Data.Bits
17import Data.Bits
19import Data.Word
18import Data.Word
20import Foreign.Storable
19import Foreign.Storable
21−import Data.Traversable (traverse)
20+import System.Random
22−import Data.Foldable (traverse_)
24import Test.Framework.Providers.QuickCheck2 ( testProperty )
22import Test.Framework.Providers.QuickCheck2 ( testProperty )
25import Test.Framework.Runners.Console ( defaultMain )
23import Test.Framework.Runners.Console ( defaultMain )
@@ -38,10 +36,7 @@ tests =
38 [ testProperty "prop_composite_case" prop_composite_case ]
36 [ testProperty "prop_composite_case" prop_composite_case ]
40 , testGroup "getByteString"
38 , testGroup "getByteString"
41− [ testProperty "prop_getByteString_negative" prop_getByteString_negative
39+ [ testProperty "prop_getByteString_negative" prop_getByteString_negative ]
42− , testProperty "prop_putByteString_getByteString" (prop_putByteString_getByteString :: BitOrder -> B.ByteString -> Property)
43− , testProperty "prop_putByteString_getByteString_many" (prop_putByteString_getByteString_many :: BitOrder -> [B.ByteString] -> Property)
46 , testGroup "getLazyByteString"
41 , testGroup "getLazyByteString"
47 [ testProperty "getLazyByteString == getByteString"
42 [ testProperty "getLazyByteString == getByteString"
@@ -89,10 +84,10 @@ tests =
91 , testGroup "prop_put_with_bitreq"
86 , testGroup "prop_put_with_bitreq"
92− [ testProperty "Word8" (prop_putget_with_bitreq :: BitOrder -> W Word8 -> Property)
87+ [ testProperty "Word8" (prop_putget_with_bitreq :: W Word8 -> Property)
93− , testProperty "Word16" (prop_putget_with_bitreq :: BitOrder -> W Word16 -> Property)
88+ , testProperty "Word16" (prop_putget_with_bitreq :: W Word16 -> Property)
94− , testProperty "Word32" (prop_putget_with_bitreq :: BitOrder -> W Word32 -> Property)
89+ , testProperty "Word32" (prop_putget_with_bitreq :: W Word32 -> Property)
95− , testProperty "Word64" (prop_putget_with_bitreq :: BitOrder -> W Word64 -> Property)
90+ , testProperty "Word64" (prop_putget_with_bitreq :: W Word64 -> Property)
98 , testGroup "prop_putget_list_simple"
93 , testGroup "prop_putget_list_simple"
@@ -117,10 +112,10 @@ tests =
117 , testProperty "Word64" (prop_putget_list_with_bitreq :: W [Word64] -> Property)
112 , testProperty "Word64" (prop_putget_list_with_bitreq :: W [Word64] -> Property)
119 , testGroup "prop_bitget_bytestring_interspersed"
114 , testGroup "prop_bitget_bytestring_interspersed"
120− [ testProperty "Word8" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word8 -> [B.ByteString] -> Property)
115+ [ testProperty "Word8" (prop_bitget_bytestring_interspersed :: W Word8 -> [B.ByteString] -> Property)
121− , testProperty "Word16" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word16 -> [B.ByteString] -> Property)
116+ , testProperty "Word16" (prop_bitget_bytestring_interspersed :: W Word16 -> [B.ByteString] -> Property)
122− , testProperty "Word32" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word32 -> [B.ByteString] -> Property)
117+ , testProperty "Word32" (prop_bitget_bytestring_interspersed :: W Word32 -> [B.ByteString] -> Property)
123− , testProperty "Word64" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word64 -> [B.ByteString] -> Property)
118+ , testProperty "Word64" (prop_bitget_bytestring_interspersed :: W Word64 -> [B.ByteString] -> Property)
125 , testGroup "Simulate programs"
120 , testGroup "Simulate programs"
126 [ testProperty "primitive" prop_primitive
121 [ testProperty "primitive" prop_primitive
@@ -163,28 +158,13 @@ prop_getByteString_negative n =
163 n < 1 ==>
158 n < 1 ==>
164 runGet (runBitGet (getByteString n)) L.empty == B.empty
159 runGet (runBitGet (getByteString n)) L.empty == B.empty
166−prop_putByteString_getByteString :: BitOrder -> B.ByteString -> Property
167−prop_putByteString_getByteString bo bs = property $ bs' == bs
170− w = runPut (runBitPut (withBitOrder bo (putByteString bs)))
171− bs' = runGet (runBitGet (withBitOrder bo (getByteString n))) w
173−prop_putByteString_getByteString_many :: BitOrder -> [B.ByteString] -> Property
174−prop_putByteString_getByteString_many bo bs = property $ bs' == bs
176− n = fmap B.length bs
177− w = runPut (runBitPut (withBitOrder bo (traverse_ putByteString bs)))
178− bs' = runGet (runBitGet (withBitOrder bo (traverse getByteString n))) w
181−prop_putget_with_bitreq :: (BinaryBit a, Num a, Bits a, Ord a) => BitOrder -> W a -> Property
161+prop_putget_with_bitreq :: (BinaryBit a, Num a, Bits a, Ord a) => W a -> Property
182−prop_putget_with_bitreq bo (W w) = property $
162+prop_putget_with_bitreq (W w) = property $
183 -- write all words with as many bits as it's required
163 -- write all words with as many bits as it's required
184 let p = putBits (bitreq w) w
164 let p = putBits (bitreq w) w
185 g = getBits (bitreq w)
165 g = getBits (bitreq w)
186− lbs = runPut (runBitPut (withBitOrder bo p))
166+ lbs = runPut (runBitPut p)
187− w' = runGet (runBitGet (withBitOrder bo g)) lbs
167+ w' = runGet (runBitGet g) lbs
188 in w == w'
168 in w == w'
190-- | Write a list of items. Each item is written with the maximum amount of
170-- | Write a list of items. Each item is written with the maximum amount of
@@ -246,12 +226,12 @@ prop_bitget_with_put_from_binary (W ws) = property $
246 in ws == ws'
226 in ws == ws'
248-- | Write each 'ByteString' with a variable sized value as a separator.
228-- | Write each 'ByteString' with a variable sized value as a separator.
249−prop_bitget_bytestring_interspersed :: (BinaryBit a, Binary a, Num a, Ord a, Bits a) => BitOrder -> W a -> [B.ByteString] -> Property
229+prop_bitget_bytestring_interspersed :: (BinaryBit a, Binary a, Num a, Ord a, Bits a) => W a -> [B.ByteString] -> Property
250−prop_bitget_bytestring_interspersed bo (W ws) bss = property $
230+prop_bitget_bytestring_interspersed (W ws) bss = property $
251 let p = mapM_ (\bs -> putBits (bitreq ws) ws >> putByteString bs) bss
231 let p = mapM_ (\bs -> putBits (bitreq ws) ws >> putByteString bs) bss
252 g = mapM (\bs -> (,) <$> getBits (bitreq ws) <*> getByteString (B.length bs)) bss
232 g = mapM (\bs -> (,) <$> getBits (bitreq ws) <*> getByteString (B.length bs)) bss
253− lbs = runPut (runBitPut (withBitOrder bo p))
233+ lbs = runPut (runBitPut p)
254− r = runGet (runBitGet (withBitOrder bo g)) lbs
234+ r = runGet (runBitGet g) lbs
255 in map (ws,) bss == r
235 in map (ws,) bss == r
257-- | Test failing.
237-- | Test failing.
@@ -261,8 +241,8 @@ prop_fail lbs errMsg0 = forAll (choose (0, 8 * L.length lbs)) $ \len ->
261 expectedBytesConsumed
241 expectedBytesConsumed
262 | bits == 0 = bytes
242 | bits == 0 = bytes
263 | otherwise = bytes + 1
243 | otherwise = bytes + 1
264− p = do _ <- getByteString (fromIntegral bytes)
244+ p = do getByteString (fromIntegral bytes)
265− _ <- getBits (fromIntegral bits) :: BitGet Word8
245+ getBits (fromIntegral bits) :: BitGet Word8
266 fail errMsg0
246 fail errMsg0
267 r = runGetIncremental (runBitGet p) `pushChunks` lbs
247 r = runGetIncremental (runBitGet p) `pushChunks` lbs
268 in case r of
248 in case r of
@@ -288,7 +268,7 @@ prop_bitreq (W w) = property $
288prop_composite_case :: Bool -> W Word16 -> Property
268prop_composite_case :: Bool -> W Word16 -> Property
289prop_composite_case b (W w) = w < 0x8000 ==>
269prop_composite_case b (W w) = w < 0x8000 ==>
290 let p = do putBool b
270 let p = do putBool b
291− putWord16 15 w
271+ putWord16be 15 w
292 g = do v <- getBool
272 g = do v <- getBool
293 case v of
273 case v of
294 True -> getWord16 15
274 True -> getWord16 15
@@ -394,6 +374,11 @@ instance (Arbitrary (W a), Arbitrary (W b), Arbitrary (W c)) => Arbitrary (W (a,
394 arbitrary = ((W .) .) . (,,) <$> arbitraryW <*> arbitraryW <*> arbitraryW
374 arbitrary = ((W .) .) . (,,) <$> arbitraryW <*> arbitraryW <*> arbitraryW
395 shrink (W (a,b,c)) = ((W .) .) . (,,) <$> shrinkW a <*> shrinkW b <*> shrinkW c
375 shrink (W (a,b,c)) = ((W .) .) . (,,) <$> shrinkW a <*> shrinkW b <*> shrinkW c
377+integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
378+integralRandomR (a,b) g = case randomR (fromIntegral a :: Integer,
379+ fromIntegral b :: Integer) g of
380+ (x,g) -> (fromIntegral x, g)
397data Primitive
382data Primitive
398 = Bool Bool
383 = Bool Bool
399 | W8 Int Word8
384 | W8 Int Word8
@@ -402,7 +387,6 @@ data Primitive
402 | W64 Int Word64
387 | W64 Int Word64
403 | BS Int B.ByteString
388 | BS Int B.ByteString
404 | LBS Int L.ByteString
389 | LBS Int L.ByteString
406 | IsEmpty
390 | IsEmpty
407 deriving (Eq, Show)
391 deriving (Eq, Show)
@@ -421,7 +405,6 @@ instance Arbitrary Primitive where
421 , gen W16
405 , gen W16
422 , gen W32
406 , gen W32
423 , gen W64
407 , gen W64
424− , Skip <$> choose (0, 3000)
425 , do n <- choose (0,10)
408 , do n <- choose (0,10)
426 cs <- vector n
409 cs <- vector n
427 return (BS n (B.pack cs))
410 return (BS n (B.pack cs))
@@ -438,19 +421,10 @@ instance Arbitrary Primitive where
438 W16 _ x -> snk W16 x
421 W16 _ x -> snk W16 x
439 W32 _ x -> snk W32 x
422 W32 _ x -> snk W32 x
440 W64 _ x -> snk W64 x
423 W64 _ x -> snk W64 x
441− Skip x -> Skip <$> shrink x
442 BS _ bs -> let ws = B.unpack bs in map (\ws' -> BS (length ws') (B.pack ws')) (shrink ws)
424 BS _ bs -> let ws = B.unpack bs in map (\ws' -> BS (length ws') (B.pack ws')) (shrink ws)
443 LBS _ lbs -> let ws = L.unpack lbs in map (\ws' -> LBS (length ws') (L.pack ws')) (shrink ws)
425 LBS _ lbs -> let ws = L.unpack lbs in map (\ws' -> LBS (length ws') (L.pack ws')) (shrink ws)
444 IsEmpty -> []
426 IsEmpty -> []
446−instance Arbitrary BitOrder where
447− arbitrary = elements [BB, LB, LL, BL]
448− shrink LL = [BB,LB,BL]
454prop_primitive :: Primitive -> Property
428prop_primitive :: Primitive -> Property
455prop_primitive prim = property $
429prop_primitive prim = property $
456 let p = putPrimitive prim
430 let p = putPrimitive prim
@@ -472,10 +446,9 @@ putPrimitive p =
472 case p of
446 case p of
473 Bool b -> putBool b
447 Bool b -> putBool b
474 W8 n x -> putWord8 n x
448 W8 n x -> putWord8 n x
475− W16 n x -> putWord16 n x
449+ W16 n x -> putWord16be n x
476− W32 n x -> putWord32 n x
450+ W32 n x -> putWord32be n x
477− W64 n x -> putWord64 n x
451+ W64 n x -> putWord64be n x
478− Skip n -> skipBits n
479 BS _ bs -> putByteString bs
452 BS _ bs -> putByteString bs
480 LBS _ lbs -> mapM_ putByteString (L.toChunks lbs)
453 LBS _ lbs -> mapM_ putByteString (L.toChunks lbs)
481 IsEmpty -> return ()
454 IsEmpty -> return ()
@@ -488,22 +461,10 @@ getPrimitive p =
488 W16 n _ -> W16 n <$> getWord16 n
461 W16 n _ -> W16 n <$> getWord16 n
489 W32 n _ -> W32 n <$> getWord32 n
462 W32 n _ -> W32 n <$> getWord32 n
490 W64 n _ -> W64 n <$> getWord64 n
463 W64 n _ -> W64 n <$> getWord64 n
491− Skip n -> skipBits n >> return (Skip n)
492 BS n _ -> BS n <$> getByteString n
464 BS n _ -> BS n <$> getByteString n
493 LBS n _ -> LBS n <$> getLazyByteString n
465 LBS n _ -> LBS n <$> getLazyByteString n
494 IsEmpty -> isEmpty >> return IsEmpty
466 IsEmpty -> isEmpty >> return IsEmpty
496−getPrimitiveSize :: Primitive -> Int
497−getPrimitiveSize p = case p of
508verifyProgram :: Int -> Program -> BitGet Bool
469verifyProgram :: Int -> Program -> BitGet Bool
509verifyProgram totalLength ps0 = go 0 ps0
470verifyProgram totalLength ps0 = go 0 ps0
@@ -511,6 +472,13 @@ verifyProgram totalLength ps0 = go 0 ps0
511 go _ [] = return True
472 go _ [] = return True
512 go pos (p:ps) =
473 go pos (p:ps) =
513 case p of
474 case p of
475+ Bool x -> check x getBool >> go (pos+1) ps
476+ W8 n x -> check x (getWord8 n) >> go (pos+n) ps
477+ W16 n x -> check x (getWord16 n) >> go (pos+n) ps
478+ W32 n x -> check x (getWord32 n) >> go (pos+n) ps
479+ W64 n x -> check x (getWord64 n) >> go (pos+n) ps
480+ BS n x -> check x (getByteString n) >> go (pos+(8*n)) ps
481+ LBS n x -> check x (getLazyByteString n) >> go (pos+(8*n)) ps
514 IsEmpty -> do
482 IsEmpty -> do
515 let expected = pos == totalLength
483 let expected = pos == totalLength
516 actual <- isEmpty
484 actual <- isEmpty
@@ -518,7 +486,6 @@ verifyProgram totalLength ps0 = go 0 ps0
518 then go pos ps
486 then go pos ps
519 else error $ "isEmpty returned wrong value, expected "
487 else error $ "isEmpty returned wrong value, expected "
520 ++ show expected ++ " but got " ++ show actual
488 ++ show expected ++ " but got " ++ show actual
521− _ -> check p (getPrimitive p) >> go (pos + getPrimitiveSize p) ps
522 check x g = do
489 check x g = do
524 if x == y
491 if x == y