{-# LANGUAGE DeriveGeneric, FlexibleInstances, FlexibleContexts, TypeOperators, DeriveAnyClass #-} import Test.HUnit import ProjectM36.Tupleable import ProjectM36.Atomable import ProjectM36.Attribute import ProjectM36.Error import Data.Binary import ProjectM36.Base import Control.DeepSeq (NFData) import GHC.Generics import qualified Data.Vector as V import qualified Data.Map as M import qualified Data.Text as T import qualified Data.Set as S import System.Exit import Data.Proxy {-# ANN module ("Hlint: ignore Use newtype instead of data" :: String) #-} data Test1T = Test1C { attrA :: Integer } deriving (Generic, Eq, Show) data Test2T = Test2C { attrB :: Integer, attrC :: Integer } deriving (Generic, Eq, Show) data Test3T = Test3C Integer deriving (Generic, Eq, Show) data Test4T = Test4C deriving (Generic, Eq, Show) data Test5T = Test5C1 Integer | Test5C2 Integer deriving (Generic, Eq, Show) data Test6T = Test6C T.Text Integer Double deriving (Generic, Eq, Show) data Test7A = Test7AC Integer deriving (Generic, Show, Eq, Binary, NFData, Atomable) data Test7T = Test7C Test7A deriving (Generic, Show, Eq) data Test8T = Test8C deriving (Generic, Show, Eq) data Test9T = Test9C { attr9A :: Integer, attr9B :: T.Text, attr9C :: Double } deriving (Generic, Show, Eq) instance Tupleable Test1T instance Tupleable Test2T instance Tupleable Test3T instance Tupleable Test4T --instance Tupleable Test5T -- should fail at compile time- sum types not supported instance Tupleable Test6T instance Tupleable Test7T instance Tupleable Test8T instance Tupleable Test9T main :: IO () main = do tcounts <- runTestTT testList if errors tcounts + failures tcounts > 0 then exitFailure else exitSuccess testList :: Test testList = TestList [testADT1, testADT2, testADT3, testADT4, testADT6, testADT7, testADT8, testInsertExpr, testDefineExpr, testUpdateExpr, testUpdateExprEmptyAttrs, testDeleteExpr, testUpdateExprWrongAttr, testReorderedTuple] testADT1 :: Test testADT1 = TestCase $ assertEqual "one record constructor" (Right example) (fromTuple (toTuple example)) where example = Test1C {attrA = 3} testADT2 :: Test testADT2 = TestCase $ do let example = Test2C { attrB = 4, attrC = 6 } assertEqual "two record constructor" (Right example) (fromTuple (toTuple example)) --this was a tricky case that was throwing the undefined exception because of insufficient laziness in the :*: matching- see ProjectM36.Tupleable let expectedAttributes = attributesFromList [Attribute "attrB" IntegerAtomType, Attribute "attrC" IntegerAtomType] assertEqual "two record constructor toAttributes" expectedAttributes (toAttributes (Proxy :: Proxy Test2T)) testADT3 :: Test testADT3 = TestCase $ assertEqual "one arg constructor" (Right example) (fromTuple (toTuple example)) where example = Test3C 4 testADT4 :: Test testADT4 = TestCase $ assertEqual "zero arg constructor" (Right example) (fromTuple (toTuple example)) where example = Test4C --testADT5 should not compile testADT6 :: Test testADT6 = TestCase $ assertEqual "mixed types" (Right example) (fromTuple (toTuple example)) where example = Test6C "testo" 3 4.0 testADT7 :: Test testADT7 = TestCase $ do let example = Test7C (Test7AC 3) assertEqual "atom type" (Right example) (fromTuple (toTuple example)) let expectedAttrs = V.singleton (Attribute "" (ConstructedAtomType "Test7A" M.empty)) assertEqual "adt atomtype" expectedAttrs (toAttributes (Proxy :: Proxy Test7T)) testADT8 :: Test testADT8 = TestCase $ assertEqual "single value" (Right example) (fromTuple (toTuple example)) where example = Test8C testInsertExpr :: Test testInsertExpr = TestCase $ assertEqual "insert expr" expected (toInsertExpr [Test9C { attr9A = 4, attr9B = "a", attr9C = 3.4}] "rv") where expected = Right (Insert "rv" (MakeStaticRelation attrs tuples)) attrs = attributesFromList [Attribute "attr9A" IntegerAtomType, Attribute "attr9B" TextAtomType, Attribute "attr9C" DoubleAtomType] tuples = RelationTupleSet [RelationTuple attrs (V.fromList [IntegerAtom 4, TextAtom "a", DoubleAtom 3.4])] testDefineExpr :: Test testDefineExpr = TestCase $ assertEqual "define expr" expected actual where expected = Define "rv" (map NakedAttributeExpr attrs) attrs = [Attribute "attr9A" IntegerAtomType, Attribute "attr9B" TextAtomType, Attribute "attr9C" DoubleAtomType] actual = toDefineExpr (Proxy :: Proxy Test9T) "rv" testUpdateExpr :: Test testUpdateExpr = TestCase $ do let expected = Right (Update "rv" updateMap restriction) updateMap = M.fromList [("attr9B", NakedAtomExpr (TextAtom "b")), ("attr9C", NakedAtomExpr (DoubleAtom 5.5))] restriction = AttributeEqualityPredicate "attr9A" (NakedAtomExpr (IntegerAtom 5)) actual = toUpdateExpr "rv" ["attr9A"] Test9C {attr9A = 5, attr9B = "b", attr9C = 5.5} assertEqual "update expr1" expected actual testUpdateExprEmptyAttrs :: Test testUpdateExprEmptyAttrs = TestCase $ do let expected = Left EmptyAttributesError actual = toUpdateExpr "rv" [] Test9C {attr9A = 5, attr9B = "b", attr9C = 5.5} assertEqual "update with empty attrs" expected actual testUpdateExprWrongAttr :: Test testUpdateExprWrongAttr = TestCase $ do --currently, passing in the wrong attribute replaces the whole relvar with a single tuple- is this what we want? let expected = Left (NoSuchAttributeNamesError (S.singleton "nonexistentattr")) actual = toUpdateExpr "rv" ["nonexistentattr"] Test9C {attr9A = 5, attr9B = "b", attr9C = 5.5} assertEqual "update with wrong attr" expected actual testDeleteExpr :: Test testDeleteExpr = TestCase $ do let expected = Right (Delete "rv" (AndPredicate (AttributeEqualityPredicate "attr9A" (NakedAtomExpr (IntegerAtom 5))) (AttributeEqualityPredicate "attr9B" (NakedAtomExpr (TextAtom "b"))))) actual = toDeleteExpr "rv" ["attr9A", "attr9B"] Test9C {attr9A = 5, attr9B = "b", attr9C = 5.5} assertEqual "delete expr" expected actual --discovered in #184 by ruhatch testReorderedTuple :: Test testReorderedTuple = TestCase $ do let tupleRev :: RelationTuple -> RelationTuple tupleRev (RelationTuple v1 v2) = RelationTuple (V.reverse v1) (V.reverse v2) expected = Test2C {attrB = 3, attrC = 4} actual = fromTuple . tupleRev . toTuple $ expected assertEqual "reordered tuple" (Right expected) actual