tahoe-chk-0.1.0.2: test/SpecZFEC.hs
module SpecZFEC (
tests,
prop_encode_decode_roundtrip,
) where
import Test.Tasty (
TestTree,
testGroup,
)
import Test.Tasty.HUnit (
assertBool,
testCase,
)
import Control.Monad.IO.Class (liftIO)
import qualified Data.ByteString as BS
import Hedgehog
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Test.Tasty.Hedgehog
import Tahoe.CHK (zfec, zunfec)
tests :: TestTree
tests =
testGroup
"ZFEC"
[ testProperty "data round-trips through encode/decode" prop_encode_decode_roundtrip
, test_encode
, test_decode
]
test_encode :: TestTree
test_encode = testCase "ZFEC.encode" $ do
let k = 3
n = 10
x = 131073
plaintext = BS.replicate x 73
encoded <- liftIO $ zfec k n plaintext
assertBool "It encoded" (and $ (x `div` k ==) . BS.length <$> encoded)
test_decode :: TestTree
test_decode = testCase "ZFEC.decode" $ do
let k = 3
n = 10
x = 131073 `div` k
encoded = replicate k (BS.replicate x 31)
plaintext <- liftIO $ zunfec k n (zip [0 ..] encoded)
assertBool "It decoded" $ BS.length plaintext == 131073
{- | Given any `k` output blocks from @'ZFEC.encode' k n plaintext@, @'decode'
k n@ will reproduce the @plaintext@ input.
-}
prop_encode_decode_roundtrip :: Property
prop_encode_decode_roundtrip = property $ do
k <- forAll $ Gen.int (Range.linear 1 254)
n <- forAll $ (k +) <$> Gen.int (Range.linear 1 (255 - k))
-- Ensure the plaintext has an allowed length.
plaintextLength <- forAll $ (k *) <$> Gen.integral (Range.linear 1 32)
plaintext <- forAll $ Gen.bytes (Range.singleton plaintextLength)
encodedBlocks <- evalIO $ zfec k n plaintext
let tagged = zip [0 ..] encodedBlocks
annotateShow encodedBlocks
available <- forAll $ Gen.shuffle tagged
decodedPlaintext <- evalIO $ zunfec k n (take k available)
diff plaintext (==) decodedPlaintext