project-m36-0.5.1: test/Relation/Basic.hs
import Test.HUnit
import ProjectM36.Base
import ProjectM36.Relation
import ProjectM36.Error
import ProjectM36.DateExamples
import ProjectM36.TupleSet
import ProjectM36.Attribute hiding (null, attributeNames)
import ProjectM36.DataTypes.Primitive
import ProjectM36.RelationalExpression
import ProjectM36.Tuple
import qualified ProjectM36.DatabaseContext as DBC
import Control.Monad.Trans.Reader
import qualified ProjectM36.Attribute as A
import qualified Data.Map as M
import qualified Data.Vector as V
import qualified Data.Set as S
import System.Exit
testList :: Test
testList = TestList [testRelation "relationTrue" relationTrue, testRelation "relationFalse" relationFalse,
testMkRelation1,
testRename1, testRename2,
testRelation "suppliers" suppliersRel,
testRelation "products" productsRel,
testRelation "supplierProducts" supplierProductsRel,
testMkRelationFromExprsBadAttrs,
testDuplicateAttributes,
testExistingRelationType
]
main :: IO ()
main = do
tcounts <- runTestTT testList
if errors tcounts + failures tcounts > 0 then exitFailure else exitSuccess
testRelation :: String -> Relation -> Test
testRelation testName rel = TestCase $ assertEqual testName relationValidation (Right rel)
where
relationValidation = validateRelation rel
-- run common relation checks
validateRelation :: Relation -> Either RelationalError Relation
validateRelation rel = do
_ <- validateAttrNamesMatchTupleAttrNames rel
validateAttrTypesMatchTupleAttrTypes rel
validateAttrNamesMatchTupleAttrNames :: Relation -> Either RelationalError Relation
validateAttrNamesMatchTupleAttrNames rel@(Relation _ tupSet)
| null invalidSet = Right rel
| otherwise = Left $ AttributeNamesMismatchError S.empty
where
nameCheck tuple = attributeNames rel == tupleAttributeNameSet tuple
invalidSet = filter (not . nameCheck) (asList tupSet)
validateAttrTypesMatchTupleAttrTypes :: Relation -> Either RelationalError Relation
validateAttrTypesMatchTupleAttrTypes rel@(Relation attrs tupSet) = foldr (\tuple acc ->
if tupleAttributes tuple == attrs && tupleAtomCheck tuple then
acc
else
Left $ TupleAttributeTypeMismatchError A.emptyAttributes
) (Right rel) (asList tupSet)
where
tupleAtomCheck tuple = V.all (== True) (attrChecks tuple)
attrChecks tuple = V.map (\attr -> case atomForAttributeName (A.attributeName attr) tuple of
Left _ -> False
Right atom -> (Right $ atomTypeForAtom atom) ==
A.atomTypeForAttributeName (A.attributeName attr) attrs) (attributes rel)
simpleRel :: Relation
simpleRel = case mkRelation attrs tupleSet of
Right rel -> rel
Left _ -> undefined
where
attrs = A.attributesFromList [Attribute "a" TextAtomType, Attribute "b" TextAtomType]
tupleSet = RelationTupleSet [mkRelationTuple attrs (V.fromList [TextAtom "spam", TextAtom "spam2"])]
--rename tests
testRename1 :: Test
testRename1 = TestCase $ assertEqual "attribute invalid" (rename "a" "b" relationTrue) (Left $ AttributeNamesMismatchError (S.singleton "a"))
testRename2 :: Test
testRename2 = TestCase $ assertEqual "attribute in use" (rename "b" "a" simpleRel) (Left $ AttributeNameInUseError "a")
--mkRelation tests
--test tupleset key mismatch failure
testMkRelation1 :: Test
testMkRelation1 = TestCase $ assertEqual "key mismatch" expectedError (mkRelation testAttrs testTupSet) -- the error attribute set is empty due to an optimization- the tuple attrs do not match the atoms' types
where
expectedError = Left (AtomTypeMismatchError TextAtomType IntAtomType)
testAttrs = A.attributesFromList [Attribute "a" TextAtomType]
testTupSet = RelationTupleSet [mkRelationTuple testAttrs $ V.fromList [TextAtom "v"],
mkRelationTuple testAttrs $ V.fromList [IntAtom 2]]
testMkRelationFromExprsBadAttrs :: Test
testMkRelationFromExprsBadAttrs = TestCase $ do
let context = DBC.empty
case runReader (evalRelationalExpr (MakeRelationFromExprs (Just [AttributeAndTypeNameExpr "badAttr1" (PrimitiveTypeConstructor "Int" IntAtomType) ()]) [TupleExpr (M.singleton "badAttr2" (NakedAtomExpr (IntAtom 1)))])) (mkRelationalExprState context) of
Left err -> assertEqual "tuple type mismatch" (TupleAttributeTypeMismatchError (A.attributesFromList [Attribute "badAttr2" IntAtomType])) err
Right _ -> assertFailure "expected tuple type mismatch"
--creating an empty relation with duplicate attribute names should fail
testDuplicateAttributes :: Test
testDuplicateAttributes = TestCase $ do
let eRel = mkRelation attrs emptyTupleSet
attrs = attributesFromList [Attribute "a" IntAtomType, Attribute "a" TextAtomType]
assertEqual "duplicate attribute names" (Left (DuplicateAttributeNamesError (S.singleton "a"))) eRel
testExistingRelationType :: Test
testExistingRelationType = TestCase $ do
let typeResult = runReader (typeForRelationalExpr (ExistingRelation relationTrue)) (RelationalExprStateElems DBC.empty)
assertEqual "ExistingRelation with tuples type" (Right relationFalse) typeResult