I'm trying to test that encode and decode functions (defined in Data.ByteString.Base64.Lazy) are inverse:
import qualified Data.ByteString.Lazy as BL
encoded :: Gen BL.ByteString
encoded = do
body <- concat <$> listOf (group 0)
end <- group =<< choose (0, 2)
return . BL.pack $ body <> end
where
group :: Int -> Gen [Word8]
group pad = do
letters <- vectorOf (4 - pad)
. elements . map (fromIntegral . ord)
$ ['A'..'Z'] <> ['a'..'z'] <> ['0'..'9'] <> ['+','/','=']
return $ letters <> replicate pad 61 -- 61 is ascii for =
prop_encDec = forAll encoded $ \b ->
[b] == (encode <$> rights [decode b])
But QuickCheck discovers a problem there:
=== prop_encDec ===
*** Failed! Falsifiable (after 1 test):
"1yx="
I have investigated that the problem must be related to non-canonical encodings, but I have difficulties understanding what is it and how to deal with it. Can you please explain on this example why decoding “1yx=” and re-encoding produces “1yw=”.