{-# LANGUAGE OverloadedStrings #-} module B9.Content.ErlangPropListSpec ( spec, ) where import B9.Artifact.Content.ErlTerms import B9.Artifact.Content.ErlangPropList import B9.Text import Data.List import Data.Text () import Test.Hspec import Test.QuickCheck spec :: Spec spec = describe "ErlangPropList" $ do it "parseFromText" $ let v = parseFromText "ok." in v `shouldBe` Right (ErlangPropList (ErlAtom "ok")) it "renterToText" $ let v = renderToText (ErlangPropList (ErlAtom "ok")) in v `shouldBe` Right "ok." it "combines primitives by putting them in a list" $ let p1 = ErlangPropList (ErlList [ErlAtom "a"]) p2 = ErlangPropList (ErlList [ErlNatural 123]) combined = ErlangPropList (ErlList [ErlAtom "a", ErlNatural 123]) in (p1 <> p2) `shouldBe` combined it "combines a list and a primitve by extending the list" $ let (Right l) = parseFromText "[a,b,c]." :: Either String ErlangPropList (Right p) = parseFromText "{ok,value}." (Right combined) = parseFromText "[a,b,c,{ok,value}]." in l <> p `shouldBe` combined it "combines a primitve and a list by extending the list" $ let (Right l) = parseFromText "[a,b,c]." :: Either String ErlangPropList (Right p) = parseFromText "{ok,value}." (Right combined) = parseFromText "[{ok,value},a,b,c]." in p <> l `shouldBe` combined it "merges lists with distinct elements to lists containing the elements of both lists" $ let p1 = ErlangPropList (ErlList [ErlTuple [ErlAtom "k_p1", ErlList [ErlNatural 1]]]) p2 = ErlangPropList (ErlList [ErlTuple [ErlAtom "k_p2", ErlList [ErlNatural 1]]]) expected = ErlangPropList ( ErlList [ ErlTuple [ErlAtom "k_p1", ErlList [ErlNatural 1]], ErlTuple [ErlAtom "k_p2", ErlList [ErlNatural 1]] ] ) in p1 <> p2 `shouldBe` expected it "merges two property lists into a prop list that has the lenght of the left + the right proplist - the number of entries sharing the same key" (property mergedPropListsHaveCorrectLength) data ErlPropListTestData = ErlPropListTestData { plistLeft :: [SimpleErlangTerm], plistRight :: [SimpleErlangTerm], commonKeys :: [SimpleErlangTerm] } deriving (Eq, Ord, Show) mergedPropListsHaveCorrectLength :: ErlPropListTestData -> Bool mergedPropListsHaveCorrectLength (ErlPropListTestData l r common) = let (ErlangPropList (ErlList merged)) = ErlangPropList (ErlList l) <> ErlangPropList (ErlList r) expectedLen = length l + length r - length common in length merged == expectedLen instance Arbitrary ErlPropListTestData where arbitrary = do someKeys <- nub <$> listOf arbitraryPlistKey numLeftOnly <- choose (0, length someKeys - 1) let keysLeftOnly = take numLeftOnly someKeys numCommon <- choose (0, length someKeys - numLeftOnly - 1) let keysCommon = take numCommon (drop numLeftOnly someKeys) let keysRightOnly = drop (numLeftOnly + numCommon) someKeys let numRightOnly = length someKeys - numLeftOnly - numCommon valuesLeft <- vectorOf (numLeftOnly + numCommon) arbitraryPlistValue valuesRight <- vectorOf (numRightOnly + numCommon) arbitraryPlistValue return ErlPropListTestData { plistLeft = zipWith toPair (keysLeftOnly <> keysCommon) valuesLeft, plistRight = zipWith toPair (keysRightOnly <> keysCommon) valuesRight, commonKeys = keysCommon } where toPair a b = ErlTuple [a, b] arbitraryPlist = ErlList <$> listOf arbitraryPlistEntry arbitraryPlistEntry = toPair <$> arbitraryPlistKey <*> arbitraryPlistValue arbitraryPlistKey = arbitraryErlSimpleAtom arbitraryPlistValue = oneof [arbitraryLiteral, arbitraryList, arbitraryPlist, arbitraryTuple] arbitraryTuple = ErlTuple <$> listOf arbitraryPlistValue arbitraryList = ErlList <$> listOf arbitraryPlistValue arbitraryLiteral = oneof [arbitraryPlistKey, arbitraryErlString, arbitraryErlNumber]