content: import Test.QuickCheck
  import Test.Tasty
  import Test.Tasty.QuickCheck
  import qualified Data.Map as M
  import Data.Foldable (foldl', foldMap)
  import Data.Binary (Binary)
  import Pipes hiding (discard)
  import qualified Pipes.Prelude as PP
  import qualified BTree as BT
  
  mapToBLeafs :: M.Map k v -> [BT.BLeaf k v]
  mapToBLeafs = map (\(k,v)->BT.BLeaf k v) . M.toAscList
  
  mapFromBLeafs :: Ord k => [BT.BLeaf k v] -> M.Map k v
  mapFromBLeafs = foldMap (\(BT.BLeaf k v) -> M.singleton k v)
  
  -- | Test lookup correctness of exact-sized input
  testExact :: (Ord k, Eq v, Binary k, Binary v)
            => M.Map k v -> Property
  testExact m = ioProperty $ do
      let len = fromIntegral $ M.size m
      bs <- BT.fromOrderedToByteString 10 len (each $ mapToBLeafs m)
      let Right bt = BT.fromByteString bs
      return $ all (\(k,v)->BT.lookup bt k == Just v) (M.assocs m)
  
  -- | Test lookup correctness of inexact-sized input
  test :: (Ord k, Eq v, Binary k, Binary v)
       => BT.Size -> M.Map k v -> Property
  test size m = ioProperty $ do
      bs <- BT.fromOrderedToByteString 10 size (each $ mapToBLeafs m)
      let Right bt = BT.fromByteString bs
      return $ all (\(k,v)->BT.lookup bt k == Just v) (take (fromIntegral size) $ M.toAscList m)
  
  testWalk :: (Ord k, Eq v, Binary k, Binary v)
           => Positive Int -> M.Map k v -> Property
  testWalk (Positive size) m = ioProperty $ do
      bs <- BT.fromOrderedToByteString 10 (fromIntegral size) (each $ mapToBLeafs m)
      let Right bt = BT.fromByteString bs
          xs = map (\(BT.BLeaf k v) -> (k, v)) $ PP.toList $ void $ BT.walkLeaves bt
      return $ xs == take size (M.toAscList m)
  
  main :: IO ()
  main = defaultMain $ testGroup "tests"
      [ testGroup "lookup"
        [ testProperty "inexact size" (test :: BT.Size -> M.Map Int Int -> Property)
        , testProperty "exact size" (testExact :: M.Map Int Int -> Property)
        ]
      , testGroup "walk"
        [ testProperty "walk" (testWalk :: Positive Int -> M.Map Int Int -> Property)
        ]
      ]
  