Main.hs (2326B)
1 {-# OPTIONS_GHC -fno-warn-missing-signatures #-} 2 {-# LANGUAGE OverloadedStrings #-} 3 {-# LANGUAGE PackageImports #-} 4 5 module Main where 6 7 import qualified Data.ByteString as BS 8 import qualified "ppad-base64" Data.ByteString.Base64 as B64 9 import qualified "base64-bytestring" Data.ByteString.Base64 as R0 10 import Test.Tasty 11 import qualified Test.Tasty.QuickCheck as Q 12 import qualified Test.Tasty.HUnit as H 13 14 newtype BS = BS BS.ByteString 15 deriving (Eq, Show) 16 17 bytes :: Int -> Q.Gen BS.ByteString 18 bytes k = do 19 l <- Q.chooseInt (0, k) 20 v <- Q.vectorOf l Q.arbitrary 21 pure (BS.pack v) 22 23 instance Q.Arbitrary BS where 24 arbitrary = do 25 b <- bytes 1024 26 pure (BS b) 27 28 decode_inverts_encode :: BS -> Bool 29 decode_inverts_encode (BS bs) = case B64.decode (B64.encode bs) of 30 Nothing -> False 31 Just b -> b == bs 32 33 encode_matches_reference :: BS -> Bool 34 encode_matches_reference (BS bs) = 35 let us = B64.encode bs 36 r0 = R0.encode bs 37 in us == r0 38 39 decode_matches_reference :: BS -> Bool 40 decode_matches_reference (BS bs) = 41 let enc = R0.encode bs 42 us = B64.decode enc 43 r0 = R0.decode enc 44 in case us of 45 Nothing -> case r0 of 46 Left _ -> True 47 _ -> False 48 Just du -> case r0 of 49 Left _ -> False 50 Right d0 -> du == d0 51 52 case_rfc_vectors :: TestTree 53 case_rfc_vectors = H.testCase "RFC 4648 \167 10 vectors" $ do 54 let vectors = [ 55 ("", "") 56 , ("f", "Zg==") 57 , ("fo", "Zm8=") 58 , ("foo", "Zm9v") 59 , ("foob", "Zm9vYg==") 60 , ("fooba", "Zm9vYmE=") 61 , ("foobar", "Zm9vYmFy") 62 ] 63 check (input, expected) = do 64 H.assertEqual ("encode " <> show input) 65 expected (B64.encode input) 66 H.assertEqual ("decode " <> show expected) 67 (Just input) (B64.decode expected) 68 mapM_ check vectors 69 70 main :: IO () 71 main = defaultMain $ 72 testGroup "ppad-base64" [ 73 testGroup "property tests" [ 74 Q.testProperty "decode . encode ~ id" $ 75 Q.withMaxSuccess 5000 decode_inverts_encode 76 , Q.testProperty "encode matches reference" $ 77 Q.withMaxSuccess 5000 encode_matches_reference 78 , Q.testProperty "decode matches reference" $ 79 Q.withMaxSuccess 5000 decode_matches_reference 80 ] 81 , testGroup "unit tests" [ 82 case_rfc_vectors 83 ] 84 ]