@@ -1,33 +1,43 @@
1−{-# LANGUAGE CPP, FlexibleInstances, FlexibleContexts, TupleSections #-}
1+module Main where
3−module Main ( main ) where
5−import Data.Binary ( Binary(..) )
3+import Data.Binary ( encode, Binary(..) )
6−import Data.Binary.Get ( runGet, runGetIncremental, pushChunks, Decoder(..) )
4+import Data.Binary.Get ( runGet )
7import Data.Binary.Put ( runPut )
5import Data.Binary.Put ( runPut )
9−import Data.Binary.Bits
7+import qualified Data.Binary.Get as BG ( getWord8, getWord16be, getWord32be, getWord64be )
10−import Data.Binary.Bits.Get
8+import qualified Data.Binary.Put as BP ( putWord8, putWord16be, putWord32be, putWord64be )
11−import Data.Binary.Bits.Put
12−import Data.Binary.Bits.BitOrder
14−import qualified Data.ByteString as B
10+import Bits
15−import qualified Data.ByteString.Lazy as L
17−import Control.Applicative
18import Data.Bits
12import Data.Bits
19import Data.Word
14import Data.Word
20import Foreign.Storable
15import Foreign.Storable
21−import Data.Traversable (traverse)
16+import System.Random
22−import Data.Foldable (traverse_)
17+import System
22+import Test.Framework.Options ( TestOptions'(..) )
24import Test.Framework.Providers.QuickCheck2 ( testProperty )
23import Test.Framework.Providers.QuickCheck2 ( testProperty )
25−import Test.Framework.Runners.Console ( defaultMain )
24+import Test.Framework.Runners.Console ( defaultMainWithOpts )
25+import Test.Framework.Runners.Options ( RunnerOptions'(..) )
26import Test.Framework ( Test, testGroup )
26import Test.Framework ( Test, testGroup )
27import Test.QuickCheck
27import Test.QuickCheck
29−main :: IO ()
29+main = do
30−main = defaultMain tests
30+ args <- getArgs
31+ defaultMainWithOpts tests (setMaxTestCases (if null args then 1024 else read (head args)))
33+ -- increase the number of test cases
36+ { ropt_test_options = Just $
38+ { topt_maximum_generated_tests = Just n
32tests :: [Test]
42tests :: [Test]
@@ -37,196 +47,101 @@ tests =
37 , testGroup "Custom test cases"
47 , testGroup "Custom test cases"
38 [ testProperty "prop_composite_case" prop_composite_case ]
48 [ testProperty "prop_composite_case" prop_composite_case ]
40− , testGroup "getByteString"
41− [ 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"
47− [ testProperty "getLazyByteString == getByteString"
48− prop_getLazyByteString_equal_to_ByteString
49− , testProperty "getLazyByteString == getByteString (with shift)"
50− prop_getLazyByteString_equal_to_ByteString2
53− , testGroup "isEmpty"
54− [ testProperty "prop_isEmptyOfEmptyEmpty" prop_isEmptyOfEmptyEmpty
55− , testProperty "prop_isEmptyOfNonEmptyEmpty" prop_isEmptyOfNonEmptyEmpty
56− , testProperty "prop_isEmptyOfConsumedEmpty" prop_isEmptyOfConsumedEmpty
57− , testProperty "prop_isEmptyOfNotConsumedNotEmpty" prop_isEmptyOfNotConsumedNotEmpty
61− [ testProperty "monadic fail" prop_fail ]
63 , testGroup "prop_bitput_with_get_from_binary"
50 , testGroup "prop_bitput_with_get_from_binary"
64− [ testProperty "Word8" (prop_bitput_with_get_from_binary :: W [Word8] -> Property)
51+ [ testProperty "Word8" (prop_bitput_with_get_from_binary :: [Word8] -> Property)
65− , testProperty "Word16" (prop_bitput_with_get_from_binary :: W [Word16] -> Property)
52+ , testProperty "Word16" (prop_bitput_with_get_from_binary :: [Word16] -> Property)
66− , testProperty "Word32" (prop_bitput_with_get_from_binary :: W [Word32] -> Property)
53+ , testProperty "Word32" (prop_bitput_with_get_from_binary :: [Word32] -> Property)
67− , testProperty "Word64" (prop_bitput_with_get_from_binary :: W [Word64] -> Property)
54+ , testProperty "Word64" (prop_bitput_with_get_from_binary :: [Word64] -> Property)
70 , testGroup "prop_bitget_with_put_from_binary"
57 , testGroup "prop_bitget_with_put_from_binary"
71− [ testProperty "Word8" (prop_bitget_with_put_from_binary :: W [Word8] -> Property)
58+ [ testProperty "Word8" (prop_bitget_with_put_from_binary :: [Word8] -> Property)
72− , testProperty "Word16" (prop_bitget_with_put_from_binary :: W [Word16] -> Property)
59+ , testProperty "Word16" (prop_bitget_with_put_from_binary :: [Word16] -> Property)
73− , testProperty "Word32" (prop_bitget_with_put_from_binary :: W [Word32] -> Property)
60+ , testProperty "Word32" (prop_bitget_with_put_from_binary :: [Word32] -> Property)
74− , testProperty "Word64" (prop_bitget_with_put_from_binary :: W [Word64] -> Property)
61+ , testProperty "Word64" (prop_bitget_with_put_from_binary :: [Word64] -> Property)
77 , testGroup "prop_compare_put_with_naive"
64 , testGroup "prop_compare_put_with_naive"
78− [ testProperty "Word8" (prop_compare_put_with_naive :: W [Word8] -> Property)
65+ [ testProperty "Word8" (prop_compare_put_with_naive :: [Word8] -> Property)
79− , testProperty "Word16" (prop_compare_put_with_naive :: W [Word16] -> Property)
66+ , testProperty "Word16" (prop_compare_put_with_naive :: [Word16] -> Property)
80− , testProperty "Word32" (prop_compare_put_with_naive :: W [Word32] -> Property)
67+ , testProperty "Word32" (prop_compare_put_with_naive :: [Word32] -> Property)
81− , testProperty "Word64" (prop_compare_put_with_naive :: W [Word64] -> Property)
68+ , testProperty "Word64" (prop_compare_put_with_naive :: [Word64] -> Property)
84 , testGroup "prop_compare_get_with_naive"
71 , testGroup "prop_compare_get_with_naive"
85− [ testProperty "Word8" (prop_compare_get_with_naive:: W [Word8] -> Property)
72+ [ testProperty "Word8" (prop_compare_get_with_naive:: [Word8] -> Property)
86− , testProperty "Word16" (prop_compare_get_with_naive:: W [Word16] -> Property)
73+ , testProperty "Word16" (prop_compare_get_with_naive:: [Word16] -> Property)
87− , testProperty "Word32" (prop_compare_get_with_naive:: W [Word32] -> Property)
74+ , testProperty "Word32" (prop_compare_get_with_naive:: [Word32] -> Property)
88− , testProperty "Word64" (prop_compare_get_with_naive:: W [Word64] -> Property)
75+ , testProperty "Word64" (prop_compare_get_with_naive:: [Word64] -> Property)
91 , testGroup "prop_put_with_bitreq"
78 , testGroup "prop_put_with_bitreq"
92− [ testProperty "Word8" (prop_putget_with_bitreq :: BitOrder -> W Word8 -> Property)
79+ [ testProperty "Word8" (prop_putget_with_bitreq :: Word8 -> Property)
93− , testProperty "Word16" (prop_putget_with_bitreq :: BitOrder -> W Word16 -> Property)
80+ , testProperty "Word16" (prop_putget_with_bitreq :: Word16 -> Property)
94− , testProperty "Word32" (prop_putget_with_bitreq :: BitOrder -> W Word32 -> Property)
81+ , testProperty "Word32" (prop_putget_with_bitreq :: Word32 -> Property)
95− , testProperty "Word64" (prop_putget_with_bitreq :: BitOrder -> W Word64 -> Property)
82+ , testProperty "Word64" (prop_putget_with_bitreq :: Word64 -> Property)
98 , testGroup "prop_putget_list_simple"
85 , testGroup "prop_putget_list_simple"
99− [ testProperty "Bool" (prop_putget_list_simple :: W [Bool] -> Property)
86+ [ testProperty "Bool" (prop_putget_list_simple :: [Bool] -> Property)
100− , testProperty "Word8" (prop_putget_list_simple :: W [Word8] -> Property)
87+ , testProperty "Word8" (prop_putget_list_simple :: [Word8] -> Property)
101− , testProperty "Word16" (prop_putget_list_simple :: W [Word16] -> Property)
88+ , testProperty "Word16" (prop_putget_list_simple :: [Word16] -> Property)
102− , testProperty "Word32" (prop_putget_list_simple :: W [Word32] -> Property)
89+ , testProperty "Word32" (prop_putget_list_simple :: [Word32] -> Property)
103− , testProperty "Word64" (prop_putget_list_simple :: W [Word64] -> Property)
90+ , testProperty "Word64" (prop_putget_list_simple :: [Word64] -> Property)
106− , testGroup "prop_putget_applicative_with_bitreq"
107− [ testProperty "Word8" (prop_putget_applicative_with_bitreq :: W [(Word8,Word8,Word8)] -> Property)
108− , testProperty "Word16" (prop_putget_applicative_with_bitreq :: W [(Word16,Word16,Word16)] -> Property)
109− , testProperty "Word32" (prop_putget_applicative_with_bitreq :: W [(Word32,Word32,Word32)] -> Property)
110− , testProperty "Word64" (prop_putget_applicative_with_bitreq :: W [(Word64,Word64,Word64)] -> Property)
113 , testGroup "prop_putget_list_with_bitreq"
93 , testGroup "prop_putget_list_with_bitreq"
114− [ testProperty "Word8" (prop_putget_list_with_bitreq :: W [Word8] -> Property)
94+ [ testProperty "Word8" (prop_putget_list_with_bitreq :: [Word8] -> Property)
115− , testProperty "Word16" (prop_putget_list_with_bitreq :: W [Word16] -> Property)
95+ , testProperty "Word16" (prop_putget_list_with_bitreq :: [Word16] -> Property)
116− , testProperty "Word32" (prop_putget_list_with_bitreq :: W [Word32] -> Property)
96+ , testProperty "Word32" (prop_putget_list_with_bitreq :: [Word32] -> Property)
117− , testProperty "Word64" (prop_putget_list_with_bitreq :: W [Word64] -> Property)
97+ , testProperty "Word64" (prop_putget_list_with_bitreq :: [Word64] -> Property)
119− , testGroup "prop_bitget_bytestring_interspersed"
120− [ testProperty "Word8" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word8 -> [B.ByteString] -> Property)
121− , testProperty "Word16" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word16 -> [B.ByteString] -> Property)
122− , testProperty "Word32" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word32 -> [B.ByteString] -> Property)
123− , testProperty "Word64" (prop_bitget_bytestring_interspersed :: BitOrder -> W Word64 -> [B.ByteString] -> Property)
125− , testGroup "Simulate programs"
126− [ testProperty "primitive" prop_primitive
127− , testProperty "many primitives in sequence" prop_program
131−prop_isEmptyOfEmptyEmpty :: Bool
101+{-
132−prop_isEmptyOfEmptyEmpty = runGet (runBitGet isEmpty) L.empty
102+ -- these tests use the R structure
134−prop_isEmptyOfNonEmptyEmpty :: L.ByteString -> Property
104+ -- quickCheck prop_Word32_from_2_Word16
135−prop_isEmptyOfNonEmptyEmpty bs =
105+ -- quickCheck prop_Word32_from_Word8_and_Word16
136− not (L.null bs) ==> not (runGet (runBitGet isEmpty) bs)
106+-}
138−prop_isEmptyOfConsumedEmpty :: L.ByteString -> Property
139−prop_isEmptyOfConsumedEmpty bs =
141− runGet (runBitGet (getByteString n >> isEmpty)) bs
142− where n = fromIntegral $ L.length bs
144−prop_isEmptyOfNotConsumedNotEmpty :: L.ByteString -> Int -> Property
145−prop_isEmptyOfNotConsumedNotEmpty bs n =
146− (fromIntegral n) < L.length bs && not (L.null bs) ==>
147− not (runGet (runBitGet (getByteString n >> isEmpty)) bs)
149−prop_getLazyByteString_equal_to_ByteString :: L.ByteString -> Int -> Property
150−prop_getLazyByteString_equal_to_ByteString bs n =
151− (fromIntegral n) <= L.length bs ==>
152− runGet (runBitGet (getLazyByteString (fromIntegral n))) bs ==
153− (L.fromChunks . (:[]) $ runGet (runBitGet (getByteString n)) bs)
155−prop_getLazyByteString_equal_to_ByteString2 :: L.ByteString -> Int -> Property
156−prop_getLazyByteString_equal_to_ByteString2 bs n =
157− (L.length bs > 1) && (fromIntegral n) < L.length bs ==>
158− runGet (runBitGet (getWord8 2 >> getLazyByteString (fromIntegral n))) bs ==
159− (L.fromChunks . (:[]) $ runGet (runBitGet (getWord8 2 >> getByteString n)) bs)
161−prop_getByteString_negative :: Int -> Property
162−prop_getByteString_negative n =
164− 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
108+prop_putget_with_bitreq :: (BinaryBit a, Num a, Bits a, Ord a) => a -> Property
182−prop_putget_with_bitreq bo (W w) = property $
109+prop_putget_with_bitreq w = property $
183 -- write all words with as many bits as it's required
110 -- write all words with as many bits as it's required
184 let p = putBits (bitreq w) w
111 let p = putBits (bitreq w) w
185 g = getBits (bitreq w)
112 g = getBits (bitreq w)
186− lbs = runPut (runBitPut (withBitOrder bo p))
113+ lbs = runPut (runBitPut p)
187− w' = runGet (runBitGet (withBitOrder bo g)) lbs
114+ w' = runGet (runBitGetSimple g) lbs
188 in w == w'
115 in w == w'
190-- | Write a list of items. Each item is written with the maximum amount of
117-- | Write a list of items. Each item is written with the maximum amount of
191-- bits, i.e. 8 for Word8, 16 for Word16, etc.
118-- bits, i.e. 8 for Word8, 16 for Word16, etc.
192−prop_putget_list_simple :: (BinaryBit a, Eq a, Storable a) => W [a] -> Property
119+prop_putget_list_simple :: (BinaryBit a, Eq a, Storable a) => [a] -> Property
193−prop_putget_list_simple (W ws) = property $
120+prop_putget_list_simple ws = property $
194 let s = sizeOf (head ws) * 8
121 let s = sizeOf (head ws) * 8
195− p = mapM_ (putBits s) ws
122+ p = mapM_ (\v -> putBits s v) ws
196 g = mapM (const (getBits s)) ws
123 g = mapM (const (getBits s)) ws
197 lbs = runPut (runBitPut p)
124 lbs = runPut (runBitPut p)
198− ws' = runGet (runBitGet g) lbs
125+ ws' = runGet (runBitGetSimple g) lbs
199 in ws == ws'
126 in ws == ws'
201-- | Write a list of items. Each item is written with exactly as many bits
128-- | Write a list of items. Each item is written with exactly as many bits
202-- as required. Then read it back.
129-- as required. Then read it back.
203−prop_putget_list_with_bitreq :: (BinaryBit a, Num a, Bits a, Ord a) => W [a] -> Property
130+prop_putget_list_with_bitreq :: (BinaryBit a, Num a, Bits a, Ord a) => [a] -> Property
204−prop_putget_list_with_bitreq (W ws) = property $
131+prop_putget_list_with_bitreq ws = property $
205 -- write all words with as many bits as it's required
132 -- write all words with as many bits as it's required
206 let p = mapM_ (\v -> putBits (bitreq v) v) ws
133 let p = mapM_ (\v -> putBits (bitreq v) v) ws
207 g = mapM getBits bitlist
134 g = mapM getBits bitlist
208 lbs = runPut (runBitPut p)
135 lbs = runPut (runBitPut p)
209− ws' = runGet (runBitGet g) lbs
136+ ws' = runGet (runBitGetSimple g) lbs
210 in ws == ws'
137 in ws == ws'
212 bitlist = map bitreq ws
139 bitlist = map bitreq ws
214−prop_putget_applicative_with_bitreq :: (BinaryBit a, Num a, Bits a, Ord a) => W [(a,a,a)] -> Property
215−prop_putget_applicative_with_bitreq (W ts) = property $
216− let p = mapM_ (\(a,b,c) -> do putBits (bitreq a) a
217− putBits (bitreq b) b
218− putBits (bitreq c) c) ts
219− g = mapM (\(a,b,c) -> (,,) <$> getBits a <*> getBits b <*> getBits c) bitlist
220− lbs = runPut (runBitPut p)
221− ts' = runGet (runBitGet g) lbs
224− bitlist = map (\(a,b,c) -> (bitreq a, bitreq b, bitreq c)) ts
226-- | Write bits using this library, and read them back using the binary
141-- | Write bits using this library, and read them back using the binary
227-- library.
142-- library.
228−prop_bitput_with_get_from_binary :: (BinaryBit a, Binary a, Storable a, Eq a) => W [a] -> Property
143+prop_bitput_with_get_from_binary :: (BinaryBit a, Binary a, Storable a, Eq a) => [a] -> Property
229−prop_bitput_with_get_from_binary (W ws) = property $
144+prop_bitput_with_get_from_binary ws = property $
230 let s = sizeOf (head ws) * 8
145 let s = sizeOf (head ws) * 8
231 p = mapM_ (putBits s) ws
146 p = mapM_ (putBits s) ws
232 g = mapM (const get) ws
147 g = mapM (const get) ws
@@ -236,88 +151,61 @@ prop_bitput_with_get_from_binary (W ws) = property $
237-- | Write bits using the binary library, and read them back using this
152-- | Write bits using the binary library, and read them back using this
238-- library.
153-- library.
239−prop_bitget_with_put_from_binary :: (BinaryBit a, Binary a, Storable a, Eq a) => W [a] -> Property
154+prop_bitget_with_put_from_binary :: (BinaryBit a, Binary a, Storable a, Eq a) => [a] -> Property
240−prop_bitget_with_put_from_binary (W ws) = property $
155+prop_bitget_with_put_from_binary ws = property $
241 let s = sizeOf (head ws) * 8
156 let s = sizeOf (head ws) * 8
242 p = mapM_ put ws
157 p = mapM_ put ws
243 g = mapM (const (getBits s)) ws
158 g = mapM (const (getBits s)) ws
244 lbs = runPut p
159 lbs = runPut p
245− ws' = runGet (runBitGet g) lbs
160+ ws' = runGet (runBitGetSimple g) lbs
246 in ws == ws'
161 in ws == ws'
248−-- | 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
250−prop_bitget_bytestring_interspersed bo (W ws) bss = property $
251− let p = mapM_ (\bs -> putBits (bitreq ws) ws >> putByteString bs) bss
252− g = mapM (\bs -> (,) <$> getBits (bitreq ws) <*> getByteString (B.length bs)) bss
253− lbs = runPut (runBitPut (withBitOrder bo p))
254− r = runGet (runBitGet (withBitOrder bo g)) lbs
255− in map (ws,) bss == r
258−prop_fail :: L.ByteString -> String -> Property
259−prop_fail lbs errMsg0 = forAll (choose (0, 8 * L.length lbs)) $ \len ->
260− let (bytes,bits) = len `divMod` 8
261− expectedBytesConsumed
263− | otherwise = bytes + 1
264− p = do _ <- getByteString (fromIntegral bytes)
265− _ <- getBits (fromIntegral bits) :: BitGet Word8
267− r = runGetIncremental (runBitGet p) `pushChunks` lbs
269− Fail remainingBS pos errMsg ->
270− and [ L.fromChunks [remainingBS] == L.drop expectedBytesConsumed lbs
271− , pos == expectedBytesConsumed
276−-- | number of bits required to write @v@
163+-- number of bits required to write 'v'
277−bitreq :: (Num b, Num a, Bits a, Ord a) => a -> b
164+bitreq :: (Num b, Bits a, Ord a) => a -> b
278bitreq v = fromIntegral . head $ [ req | (req, top) <- bittable, v <= top ]
165bitreq v = fromIntegral . head $ [ req | (req, top) <- bittable, v <= top ]
280−bittable :: (Bits a, Num a) => [(Integer, a)]
167+bittable :: Bits a => [(Integer, a)]
281bittable = [ (fromIntegral x, (1 `shiftL` x) - 1) | x <- [1..64] ]
168bittable = [ (fromIntegral x, (1 `shiftL` x) - 1) | x <- [1..64] ]
283−prop_bitreq :: W Word64 -> Property
170+prop_bitreq :: Word64 -> Property
284−prop_bitreq (W w) = property $
171+prop_bitreq w = property $
285 ( w == 0 && bitreq w == 1 )
172 ( w == 0 && bitreq w == 1 )
286− || bitreq w == bitreq (w `shiftR` 1) + 1
173+ || bitreq w == (bitreq (w `shiftR` 1)) + 1
288−prop_composite_case :: Bool -> W Word16 -> Property
175+prop_composite_case :: Bool -> Word16 -> Property
289−prop_composite_case b (W w) = w < 0x8000 ==>
176+prop_composite_case b w = w < 0x8000 ==>
290 let p = do putBool b
177 let p = do putBool b
291− putWord16 15 w
178+ putWord16be 15 w
292 g = do v <- getBool
179 g = do v <- getBool
293 case v of
180 case v of
294− True -> getWord16 15
181+ True -> getWord16be 15
295 False -> do
182 False -> do
296 msb <- getWord8 7
183 msb <- getWord8 7
297 lsb <- getWord8 8
184 lsb <- getWord8 8
298 return ((fromIntegral msb `shiftL` 8) .|. fromIntegral lsb)
185 return ((fromIntegral msb `shiftL` 8) .|. fromIntegral lsb)
299 lbs = runPut (runBitPut p)
186 lbs = runPut (runBitPut p)
300− w' = runGet (runBitGet g) lbs
187+ w' = runGet (runBitGetSimple g) lbs
301 in w == w'
188 in w == w'
303−prop_compare_put_with_naive :: (Bits a, BinaryBit a, Ord a, Num a) => W [a] -> Property
191+prop_compare_put_with_naive :: (Bits a, BinaryBit a, Ord a) => [a] -> Property
304−prop_compare_put_with_naive (W ws) = property $
192+prop_compare_put_with_naive ws = property $
305 let pn = mapM_ (\v -> naive_put (bitreq v) v) ws
193 let pn = mapM_ (\v -> naive_put (bitreq v) v) ws
306 p = mapM_ (\v -> putBits (bitreq v) v) ws
194 p = mapM_ (\v -> putBits (bitreq v) v) ws
307 lbs_n = runPut (runBitPut pn)
195 lbs_n = runPut (runBitPut pn)
308 lbs = runPut (runBitPut p)
196 lbs = runPut (runBitPut p)
309 in lbs_n == lbs
197 in lbs_n == lbs
311−prop_compare_get_with_naive :: (Bits a, BinaryBit a, Ord a, Num a) => W [a] -> Property
199+prop_compare_get_with_naive :: (Bits a, BinaryBit a, Ord a, Num a) => [a] -> Property
312−prop_compare_get_with_naive (W ws) = property $
200+prop_compare_get_with_naive ws = property $
313 let gn = mapM (\v -> naive_get (bitreq v)) ws
201 let gn = mapM (\v -> naive_get (bitreq v)) ws
314 g = mapM (\v -> getBits (bitreq v)) ws
202 g = mapM (\v -> getBits (bitreq v)) ws
315 p = mapM_ (\v -> naive_put (bitreq v) v) ws
203 p = mapM_ (\v -> naive_put (bitreq v) v) ws
316 lbs = runPut (runBitPut p)
204 lbs = runPut (runBitPut p)
317− rn = runGet (runBitGet gn) lbs
205+ rn = runGet (runBitGetSimple gn) lbs
318− r = runGet (runBitGet g ) lbs
206+ r = runGet (runBitGetSimple g ) lbs
319 -- we must help our compiler to resolve the types of 'gn' and 'g'
207 -- we must help our compiler to resolve the types of 'gn' and 'g'
320− _types = rn == ws && r == ws
208+ types = rn == ws && r == ws
321 in rn == r
209 in rn == r
323-- | Write one bit at a time until the full word has been written
211-- | Write one bit at a time until the full word has been written
@@ -335,6 +223,27 @@ naive_get n0 =
335 True -> loop (n-1) ((acc `shiftL` 1) + 1)
223 True -> loop (n-1) ((acc `shiftL` 1) + 1)
336 in loop n0 0
224 in loop n0 0
227+prop_Word32_from_Word8_and_Word16 :: Word8 -> Word16 -> Property
228+prop_Word32_from_Word8_and_Word16 w8 w16 = property $
229+ let p = RWord32be 24
230+ w' = runGet (get p) lbs
233+ lbs = runPut (putWord8 w8 >> putWord16be w16)
234+ w0 = ((fromIntegral w8) `shiftL` 16) .|. fromIntegral w16
236+prop_Word32_from_2_Word16 :: Word16 -> Word16 -> Property
237+prop_Word32_from_2_Word16 w1 w2 = property $
238+ let p = RWord32be 32
239+ w' = runGet (get p) lbs
243+ w0 = ((fromIntegral w1) `shiftL` 16) .|. fromIntegral w2
338shrinker :: (Num a, Ord a, Bits a) => a -> [a]
247shrinker :: (Num a, Ord a, Bits a) => a -> [a]
339shrinker 0 = []
248shrinker 0 = []
340shrinker w = [ w `shiftR` 1 -- try to make everything roughly half size
249shrinker w = [ w `shiftR` 1 -- try to make everything roughly half size
@@ -346,187 +255,27 @@ shrinker w = [ w `shiftR` 1 -- try to make everything roughly half size
347 n = bitreq w
256 n = bitreq w
349−data W a = W { unW :: a } deriving (Show, Eq, Ord)
351−arbitraryW :: (Arbitrary (W a)) => Gen a
352−arbitraryW = unW <$> arbitrary
354−shrinkW :: (Arbitrary (W a)) => a -> [a]
355−shrinkW x = unW <$> shrink (W x)
357−instance Arbitrary (W Bool) where
258+instance Arbitrary Word8 where
358− arbitrary = W <$> arbitrary
359− shrink = map W <$> shrink . unW
361−instance Arbitrary (W Word8) where
362− arbitrary = W <$> choose (minBound, maxBound)
259+ arbitrary = choose (minBound, maxBound)
363− shrink = map W . shrinker . unW
260+ shrink = shrinker
365−instance Arbitrary (W Word16) where
366− arbitrary = W <$> choose (minBound, maxBound)
367− shrink = map W . shrinker . unW
369−instance Arbitrary (W Word32) where
370− arbitrary = W <$> choose (minBound, maxBound)
371− shrink = map W . shrinker . unW
373−instance Arbitrary (W Word64) where
374− arbitrary = W <$> choose (minBound, maxBound)
375− shrink = map W . shrinker . unW
377−instance Arbitrary B.ByteString where
378− arbitrary = B.pack <$> arbitrary
379− shrink bs = B.pack <$> shrink (B.unpack bs)
381−instance Arbitrary L.ByteString where
382− arbitrary = L.fromChunks <$> arbitrary
383− shrink bs = L.fromChunks <$> shrink (L.toChunks bs)
385−instance (Arbitrary (W a)) => Arbitrary (W [a]) where
386− arbitrary = W . map unW <$> arbitrary
387− shrink = map (W . map unW) <$> mapM shrink . map W . unW
389−instance (Arbitrary (W a), Arbitrary (W b)) => Arbitrary (W (a,b)) where
390− arbitrary = (W .) . (,) <$> arbitraryW <*> arbitraryW
391− shrink (W (a,b)) = (W .) . (,) <$> shrinkW a <*> shrinkW b
393−instance (Arbitrary (W a), Arbitrary (W b), Arbitrary (W c)) => Arbitrary (W (a,b,c)) where
394− arbitrary = ((W .) .) . (,,) <$> arbitraryW <*> arbitraryW <*> arbitraryW
395− shrink (W (a,b,c)) = ((W .) .) . (,,) <$> shrinkW a <*> shrinkW b <*> shrinkW c
403− | BS Int B.ByteString
404− | LBS Int L.ByteString
409−type Program = [Primitive]
411−instance Arbitrary Primitive where
414− let (maxBits, _) = (\w -> (finiteBitSize w, c undefined w)) undefined
415− bits <- choose (0, maxBits)
416− n <- choose (0, fromIntegral (2^bits-1))
419− [ Bool <$> arbitrary
424− , Skip <$> choose (0, 3000)
425− , do n <- choose (0,10)
427− return (BS n (B.pack cs))
428− , do n <- choose (0,10)
430− return (LBS n (L.pack cs))
434− let snk c x = map (\x' -> c (bitreq x') x') (shrinker x) in
436− Bool b -> if b then [Bool False] else []
438− W16 _ x -> snk W16 x
439− W32 _ x -> snk W32 x
440− 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)
443− LBS _ lbs -> let ws = L.unpack lbs in map (\ws' -> LBS (length ws') (L.pack ws')) (shrink ws)
446−instance Arbitrary BitOrder where
447− arbitrary = elements [BB, LB, LL, BL]
448− shrink LL = [BB,LB,BL]
454−prop_primitive :: Primitive -> Property
455−prop_primitive prim = property $
456− let p = putPrimitive prim
457− g = getPrimitive prim
458− lbs = runPut (runBitPut p)
459− r = runGet (runBitGet g) lbs
462−prop_program :: Program -> Property
262+instance Arbitrary Word16 where
463−prop_program program = property $
263+ arbitrary = choose (minBound, maxBound)
464− let p = mapM_ putPrimitive program
264+ shrink = shrinker
465− g = verifyProgram (8 * fromIntegral (L.length lbs)) program
265+
466− lbs = runPut (runBitPut p)
266+instance Arbitrary Word32 where
467− r = runGet (runBitGet g) lbs
267+ arbitrary = choose (minBound, maxBound)
468− in r
268+ shrink = shrinker
470−putPrimitive :: Primitive -> BitPut ()
270+instance Arbitrary Word64 where
471−putPrimitive p =
271+ arbitrary = choose (minBound, maxBound)
472− case p of
272+ shrink = shrinker
473− Bool b -> putBool b
273+
474− W8 n x -> putWord8 n x
274+integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
475− W16 n x -> putWord16 n x
275+integralRandomR (a,b) g = case randomR (fromIntegral a :: Integer,
476− W32 n x -> putWord32 n x
276+ fromIntegral b :: Integer) g of
477− W64 n x -> putWord64 n x
277+ (x,g) -> (fromIntegral x, g)
478− Skip n -> skipBits n
479− BS _ bs -> putByteString bs
480− LBS _ lbs -> mapM_ putByteString (L.toChunks lbs)
481− IsEmpty -> return ()
483−getPrimitive :: Primitive -> BitGet Primitive
486− Bool _ -> Bool <$> getBool
487− W8 n _ -> W8 n <$> getWord8 n
488− W16 n _ -> W16 n <$> getWord16 n
489− W32 n _ -> W32 n <$> getWord32 n
490− W64 n _ -> W64 n <$> getWord64 n
491− Skip n -> skipBits n >> return (Skip n)
492− BS n _ -> BS n <$> getByteString n
493− LBS n _ -> LBS n <$> getLazyByteString n
494− IsEmpty -> isEmpty >> return IsEmpty
496−getPrimitiveSize :: Primitive -> Int
497−getPrimitiveSize p = case p of
508−verifyProgram :: Int -> Program -> BitGet Bool
509−verifyProgram totalLength ps0 = go 0 ps0
511− go _ [] = return True
515− let expected = pos == totalLength
517− if expected == actual
519− else error $ "isEmpty returned wrong value, expected "
520− ++ show expected ++ " but got " ++ show actual
521− _ -> check p (getPrimitive p) >> go (pos + getPrimitiveSize p) ps
526− else error $ "Roundtrip error: Expected "
527− ++ show x ++ " but got " ++ show y
530instance Random Word where
279instance Random Word where
531 randomR = integralRandomR
280 randomR = integralRandomR
532 random = randomR (minBound,maxBound)
281 random = randomR (minBound,maxBound)
@@ -546,4 +295,3 @@ instance Random Word32 where
546instance Random Word64 where
295instance Random Word64 where
547 randomR = integralRandomR
296 randomR = integralRandomR
548 random = randomR (minBound,maxBound)
297 random = randomR (minBound,maxBound)