hypher-0.1.3: tests/IntegrationTests.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleInstances, TemplateHaskell #-}
module Main where
import Control.Monad (void, join)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Data.Monoid (Monoid, mappend)
import Data.Int (Int64)
import Data.Maybe (fromJust)
import qualified Data.Aeson as J
import qualified Data.ByteString as S
import qualified Data.HashMap.Lazy as M
import qualified Data.HashSet as HS
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Vector as V
import Control.Exception (handle)
import Test.Framework.TH (defaultMainGenerator)
import Test.Framework.Providers.HUnit (testCase)
import Test.HUnit.Base hiding (Test, Node)
import Database.Neo4j
import qualified Database.Neo4j.Batch as B
import qualified Database.Neo4j.Graph as G
import qualified Database.Neo4j.Transactional.Cypher as TC
(<>) :: Monoid a => a -> a -> a
(<>) = mappend
-- Get the string of a exception raised by an action
getException :: IO a -> IO (Maybe Neo4jException)
getException action = handle (return . Just) $ do
_ <- action
return Nothing
assertException :: Neo4jException -> IO a -> Assertion
assertException exExc action = do
resExc <- getException action
checkExc resExc
where --checkExc :: (Exception e, Show e) => Maybe e -> Assertion
checkExc Nothing = assertFailure $ "Expected exception " <> show exExc <> " but none raised"
checkExc (Just e) = assertEqual "" exExc e
-- | handy assertEqual inside a Neo4j monad
neo4jEqual :: (Show a, Eq a) => a -> a -> Neo4j ()
neo4jEqual a b = liftIO $ assertEqual "" a b
-- | handy assertBool inside a Neo4j monad
neo4jBool :: Bool -> Neo4j ()
neo4jBool f = liftIO $ assertBool "Expected true" f
main :: IO ()
main = $(defaultMainGenerator)
-- TODO: Is it possible to avoid so many type declarations for literals when constructing properties??
-- | Dummy properties
someProperties :: Properties
someProperties = M.fromList ["mytext" |: ("mytext" :: T.Text),
"textarrayprop" |: ["a" :: T.Text, "", "adeu"],
"int" |: (-12 :: Int64),
"intarray" |: [1 :: Int64, 2],
"double" |: (-12.23 :: Double),
"doublearray" |: [0.1, -12.23 :: Double],
"bool" |: False,
"aboolproparray" |: [False, True]
]
-- | Default Neo4j port
port :: Port
port = 7474
-- | Default Neo4j host
host :: Hostname
host = "localhost"
someOtherProperties :: Properties
someOtherProperties = M.fromList ["hola" |: ("adeu" :: T.Text), "proparray" |: ["a" :: T.Text, "", "adeu"]]
anotherProperties :: Properties
anotherProperties = M.empty
myRelType :: T.Text
myRelType = "MYREL"
-- | Test connecting to a non-existing server
case_NoConnection :: Assertion
case_NoConnection = assertException expException $ withConnection "localhost" 77 $ createNode someProperties
where expException = Neo4jHttpException "FailedConnectionException2 \"localhost\" 77 False connect: does\
\ not exist (Connection refused)"
-- | Test get and create a node
case_CreateGetDeleteNode :: Assertion
case_CreateGetDeleteNode = withConnection host port $ do
n <- createNode someProperties
newN <- getNode n
neo4jEqual (Just n) newN
deleteNode n
-- | Test delete and get a node
case_CreateDeleteGetNode :: Assertion
case_CreateDeleteGetNode = withConnection host port $ do
n <- createNode someProperties
deleteNode n
newN <- getNode n
neo4jEqual Nothing newN
-- | Test double delete
case_DoubleDeleteNode :: Assertion
case_DoubleDeleteNode = withConnection host port $ do
n <- createNode someProperties
deleteNode n
deleteNode n
-- | Test get node by id
case_GetNodeById :: Assertion
case_GetNodeById = withConnection host port $ do
n <- createNode someProperties
newN <- getNode (nodeId n)
neo4jEqual (Just n) newN
deleteNode n
-- | Test get node with unexisting id
case_GetUnexistingNodeById :: Assertion
case_GetUnexistingNodeById = withConnection host port $ do
newN <- getNode ("unexistingnode" :: S.ByteString)
neo4jEqual Nothing newN
-- | Test delete node by id
case_DeleteNodeById :: Assertion
case_DeleteNodeById = withConnection host port $ do
n <- createNode someProperties
deleteNode (nodeId n)
-- | Test delete unexisting node by id
case_DeleteUnexistingNodeById :: Assertion
case_DeleteUnexistingNodeById = withConnection host port $ deleteNode ("unexistingnode" :: S.ByteString)
-- | Refresh node properties from the DB
case_getNodeProperties :: Assertion
case_getNodeProperties = withConnection host port $ do
n <- createNode someProperties
props <- getProperties n
neo4jEqual someProperties props
deleteNode n
-- | Get node properties from a deleted node
case_getDeletedNodeProperties :: Assertion
case_getDeletedNodeProperties = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
getProperties n
-- | Get a property from a node
case_getNodeProperty :: Assertion
case_getNodeProperty = withConnection host port $ do
n <- createNode someProperties
prop <- getProperty n "intarray"
neo4jEqual (M.lookup "intarray" someProperties) prop
deleteNode n
-- | Get an unexisting property from a node
case_getNodeUnexistingProperty :: Assertion
case_getNodeUnexistingProperty = withConnection host port $ do
n <- createNode someProperties
prop <- getProperty n "noproperty"
neo4jEqual Nothing prop
deleteNode n
-- | Get a property from an unexisting node
case_getUnexistingNodeProperty :: Assertion
case_getUnexistingNodeProperty = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
_ <- getProperty n "noproperty"
return ()
-- | Get change the properties of a node
case_changeNodeProperties :: Assertion
case_changeNodeProperties = withConnection host port $ do
n <- createNode someProperties
newN <- setProperties n otherProperties
neo4jEqual otherProperties (getNodeProperties newN)
renewN <- getNode n
neo4jEqual otherProperties (getNodeProperties $ fromJust renewN)
deleteNode newN
where otherProperties = M.insert "newbool" (newval True) someProperties
-- | Get change the properties of a node that doesn't exist
case_changeUnexistingNodeProperties :: Assertion
case_changeUnexistingNodeProperties = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
setProperties n someProperties
-- | Change a property of a node
case_changeNodeProperty :: Assertion
case_changeNodeProperty = withConnection host port $ do
n <- createNode someProperties
newN <- setProperty n otherValName otherVal
neo4jEqual otherProperties (getNodeProperties newN)
renewN <- getNode n
neo4jEqual otherProperties (getNodeProperties $ fromJust renewN)
deleteNode newN
where otherProperties = M.insert otherValName otherVal someProperties
otherValName = "int"
otherVal = newval False
-- | Change an array property of a node to empty
case_changeNodePropertyToEmpty :: Assertion
case_changeNodePropertyToEmpty = withConnection host port $ do
n <- createNode someProperties
newN <- setProperty n otherValName otherVal
neo4jEqual otherProperties (getNodeProperties newN)
renewN <- getNode n
neo4jEqual otherProperties (getNodeProperties $ fromJust renewN)
deleteNode newN
where otherProperties = M.insert otherValName otherVal someProperties
otherValName = "intarray"
otherVal = newval ([] :: [Int64])
-- | Set an unexisting property of a node
case_changeNodeUnexistingProperty :: Assertion
case_changeNodeUnexistingProperty = withConnection host port $ do
n <- createNode someProperties
newN <- setProperty n otherValName otherVal
neo4jEqual otherProperties (getNodeProperties newN)
renewN <- getNode n
neo4jEqual otherProperties (getNodeProperties $ fromJust renewN)
deleteNode newN
where otherProperties = M.insert otherValName otherVal someProperties
otherValName = "mynewbool"
otherVal = newval False
-- | Set property of an unexisting node
case_changeUnexistingNodeProperty :: Assertion
case_changeUnexistingNodeProperty = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
_ <- setProperty n otherValName otherVal
return ()
where otherValName = "mynewbool"
otherVal = newval False
-- | Delete node properties
case_deleteNodeProperties :: Assertion
case_deleteNodeProperties = withConnection host port $ do
n <- createNode someProperties
newN <- deleteProperties n
neo4jEqual M.empty (getNodeProperties newN)
renewN <- getNode n
neo4jEqual M.empty (getNodeProperties $ fromJust renewN)
deleteNode newN
-- | Delete unexisting node properties
case_deleteUnexistingNodeProperties :: Assertion
case_deleteUnexistingNodeProperties = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
_ <- deleteProperties n
return ()
-- | Delete a node property
case_deleteNodeProperty :: Assertion
case_deleteNodeProperty = withConnection host port $ do
n <- createNode someProperties
newN <- deleteProperty n valName
neo4jEqual otherProperties (getNodeProperties newN)
renewN <- getNode n
neo4jEqual otherProperties (getNodeProperties $ fromJust renewN)
deleteNode newN
where otherProperties = M.delete valName someProperties
valName = "int"
-- | Delete an unexisting property from a node
case_deleteNodeUnexistingProperty :: Assertion
case_deleteNodeUnexistingProperty = withConnection host port $ do
n <- createNode someProperties
newN <- deleteProperty n valName
neo4jEqual otherProperties (getNodeProperties newN)
renewN <- getNode n
neo4jEqual otherProperties (getNodeProperties $ fromJust renewN)
deleteNode newN
where otherProperties = M.delete valName someProperties
valName = "noproperty"
-- | Delete a property from an unexisting node
case_deleteUnexistingNodeProperty :: Assertion
case_deleteUnexistingNodeProperty = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
_ <- deleteProperty n valName
return ()
where valName = "noproperty"
setupRelTests :: Neo4j (Node, Node, Relationship)
setupRelTests = do
nodeFrom <- createNode anotherProperties
nodeTo <- createNode someOtherProperties
r <- createRelationship myRelType someProperties nodeFrom nodeTo
return (nodeFrom, nodeTo, r)
teardownRelTests :: Node -> Node -> Relationship -> Neo4j()
teardownRelTests f t r = do
deleteRelationship r
deleteNode f
deleteNode t
-- | Delete a node with a relationship
case_deleteNodeWithRelationship :: Assertion
case_deleteNodeWithRelationship = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNonOrphanNodeDeletionException $ runNodeIdentifier nodeFrom
assertException expException $ withConnection host port $ deleteNode nodeFrom
withConnection host port $ teardownRelTests nodeFrom nodeTo r
-- | Test get and create a relationship
case_CreateGetDeleteRelationship :: Assertion
case_CreateGetDeleteRelationship = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- getRelationship r
neo4jEqual (Just r) newN
teardownRelTests nodeFrom nodeTo r
-- | Test get all relationship properties
case_allRelationshipProperties :: Assertion
case_allRelationshipProperties = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
rs <- allRelationshipTypes
neo4jBool $ myRelType `elem` rs
teardownRelTests nodeFrom nodeTo r
-- | Test get the start and end of a relationship
case_relationshipFromTo :: Assertion
case_relationshipFromTo = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
nfrom <- getRelationshipFrom r
neo4jEqual nodeFrom nfrom
nto <- getRelationshipTo r
neo4jEqual nodeTo nto
teardownRelTests nodeFrom nodeTo r
-- | Test get the start of relationship that doesn't exist any more
case_nonExistingRelationshipFrom :: Assertion
case_nonExistingRelationshipFrom = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runNodeIdentifier nodeFrom
assertException expException $ withConnection host port $ do
deleteRelationship r
deleteNode nodeFrom
n <- getRelationshipFrom r
neo4jEqual nodeFrom n -- Doing this to force the evaluation of n (the exception is thrown after parsing)
return ()
withConnection host port $ teardownRelTests nodeFrom nodeTo r
-- | Test get the end of relationship that doesn't exist any more
case_nonExistingRelationshipTo :: Assertion
case_nonExistingRelationshipTo = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runNodeIdentifier nodeTo
assertException expException $ withConnection host port $ do
deleteRelationship r
deleteNode nodeTo
n <- getRelationshipTo r
neo4jEqual nodeTo n -- Doing this to force the evaluation of n (the exception is thrown after parsing)
return ()
withConnection host port $ teardownRelTests nodeFrom nodeTo r
-- | Create relationship with missing node from
case_CreateRelationshipMissingFrom :: Assertion
case_CreateRelationshipMissingFrom = do
(nodeFrom, nodeTo) <- withConnection host port $ do
nodeFrom <- createNode anotherProperties
nodeTo <- createNode someOtherProperties
return (nodeFrom, nodeTo)
let expException = Neo4jNoEntityException $ runNodeIdentifier nodeFrom
assertException expException $ withConnection host port $ do
deleteNode nodeFrom
_ <- createRelationship myRelType someProperties nodeFrom nodeTo
return ()
withConnection host port $ deleteNode nodeTo
-- | Create relationship with missing node to
case_CreateRelationshipMissingTo :: Assertion
case_CreateRelationshipMissingTo = do
(nodeFrom, nodeTo) <- withConnection host port $ do
nodeFrom <- createNode anotherProperties
nodeTo <- createNode someOtherProperties
return (nodeFrom, nodeTo)
let expException = Neo4jNoEntityException $ runNodeIdentifier nodeTo
assertException expException $ withConnection host port $ do
deleteNode nodeTo
_ <- createRelationship myRelType someProperties nodeFrom nodeTo
return ()
withConnection host port $ deleteNode nodeFrom
-- | Test delete and get a relationship
case_CreateDeleteGetRelationship :: Assertion
case_CreateDeleteGetRelationship = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
deleteRelationship r
newN <- getRelationship r
neo4jEqual Nothing newN
teardownRelTests nodeFrom nodeTo r
-- | Test double delete
case_DoubleDeleteRelationship :: Assertion
case_DoubleDeleteRelationship = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
deleteRelationship r
deleteRelationship r
teardownRelTests nodeFrom nodeTo r
-- | Test get relationship by id
case_GetRelationshipById :: Assertion
case_GetRelationshipById = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- getRelationship (relId r)
neo4jEqual (Just r) newN
teardownRelTests nodeFrom nodeTo r
-- | Test get relationship with unexisting id
case_GetUnexistingRelationshipById :: Assertion
case_GetUnexistingRelationshipById = withConnection host port $ do
newN <- getRelationship ("unexistingrelationship" :: S.ByteString)
neo4jEqual Nothing newN
-- | Test delete relationship by id
case_DeleteRelationshipById :: Assertion
case_DeleteRelationshipById = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
deleteRelationship (relId r)
teardownRelTests nodeFrom nodeTo r
-- | Test delete unexisting relationship by id
case_DeleteUnexistingRelationshipById :: Assertion
case_DeleteUnexistingRelationshipById = withConnection host port $
deleteRelationship ("unexistingrelationship" :: S.ByteString)
-- | Refresh relationship properties from the DB
case_getRelationshipProperties :: Assertion
case_getRelationshipProperties = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
props <- getProperties r
neo4jEqual someProperties props
teardownRelTests nodeFrom nodeTo r
-- | Get relationship properties from a deleted node
case_getDeletedRelationshipProperties :: Assertion
case_getDeletedRelationshipProperties = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runRelIdentifier r
assertException expException $ withConnection host port $ do
deleteRelationship r
deleteNode nodeFrom
deleteNode nodeTo
getProperties r
-- | Get a property from a relationship
case_getRelationshipProperty :: Assertion
case_getRelationshipProperty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
prop <- getProperty r "intarray"
neo4jEqual (M.lookup "intarray" someProperties) prop
teardownRelTests nodeFrom nodeTo r
-- | Get an unexisting property from a relationship
case_getRelationshipUnexistingProperty :: Assertion
case_getRelationshipUnexistingProperty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
prop <- getProperty r "noproperty"
neo4jEqual Nothing prop
teardownRelTests nodeFrom nodeTo r
-- | Get a property from an unexisting relationship
case_getUnexistingRelationshipProperty :: Assertion
case_getUnexistingRelationshipProperty = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runRelIdentifier r
assertException expException $ withConnection host port $ do
teardownRelTests nodeFrom nodeTo r
_ <- getProperty r "noproperty"
return ()
-- | Get change the properties of a relationship
case_changeRelationshipProperties :: Assertion
case_changeRelationshipProperties = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- setProperties r otherProperties
neo4jEqual otherProperties (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual otherProperties (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
where otherProperties = M.insert "newbool" (newval True) someProperties
-- | Get change the properties of a relationship that doesn't exist
case_changeUnexistingRelationshipProperties :: Assertion
case_changeUnexistingRelationshipProperties = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runRelIdentifier r
assertException expException $ withConnection host port $ do
deleteRelationship r
deleteNode nodeFrom
deleteNode nodeTo
setProperties r someProperties
-- | Change a property of a relationship
case_changeRelationshipProperty :: Assertion
case_changeRelationshipProperty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- setProperty r otherValName otherVal
neo4jEqual otherProperties (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual otherProperties (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
where otherProperties = M.insert otherValName otherVal someProperties
otherValName = "int"
otherVal = newval False
-- | Change an array property of a relationship to empty
case_changeRelationshipPropertyToEmpty :: Assertion
case_changeRelationshipPropertyToEmpty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- setProperty r otherValName otherVal
neo4jEqual otherProperties (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual otherProperties (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
where otherProperties = M.insert otherValName otherVal someProperties
otherValName = "intarray"
otherVal = newval ([] :: [Int64])
-- | Set an unexisting property of a relationship
case_changeRelationshipUnexistingProperty :: Assertion
case_changeRelationshipUnexistingProperty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- setProperty r otherValName otherVal
neo4jEqual otherProperties (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual otherProperties (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
where otherProperties = M.insert otherValName otherVal someProperties
otherValName = "mynewbool"
otherVal = newval False
-- | Set property of an unexisting node
case_changeUnexistingRelationshipProperty :: Assertion
case_changeUnexistingRelationshipProperty = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runRelIdentifier r
assertException expException $ withConnection host port $ do
deleteRelationship r
_ <- setProperty r otherValName otherVal
return ()
withConnection host port $ teardownRelTests nodeFrom nodeTo r
where otherValName = "mynewbool"
otherVal = newval False
-- | Delete relationship properties
case_deleteRelationshipProperties :: Assertion
case_deleteRelationshipProperties = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- deleteProperties r
neo4jEqual M.empty (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual M.empty (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
-- | Delete unexisting relationship properties
case_deleteUnexistingRelationshipProperties :: Assertion
case_deleteUnexistingRelationshipProperties = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runRelIdentifier r
assertException expException $ withConnection host port $ do
deleteRelationship r
_ <- deleteProperties r
return ()
withConnection host port $ teardownRelTests nodeFrom nodeTo r
-- | Delete a relationship property
case_deleteRelationshipProperty :: Assertion
case_deleteRelationshipProperty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- deleteProperty r valName
neo4jEqual otherProperties (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual otherProperties (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
where otherProperties = M.delete valName someProperties
valName = "int"
-- | Delete an unexisting property from a relationship
case_deleteRelationshipUnexistingProperty :: Assertion
case_deleteRelationshipUnexistingProperty = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
newN <- deleteProperty r valName
neo4jEqual otherProperties (getRelProperties newN)
renewN <- getRelationship r
neo4jEqual otherProperties (getRelProperties $ fromJust renewN)
teardownRelTests nodeFrom nodeTo newN
where otherProperties = M.delete valName someProperties
valName = "noproperty"
-- | Delete a property from an unexisting relationship
case_deleteUnexistingRelationshipProperty :: Assertion
case_deleteUnexistingRelationshipProperty = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runRelIdentifier r
assertException expException $ withConnection host port $ do
deleteRelationship r
_ <- deleteProperty r valName
return ()
withConnection host port $ teardownRelTests nodeFrom nodeTo r
where valName = "noproperty"
-- | Get relationships for a node
case_GetNodeRelationships :: Assertion
case_GetNodeRelationships = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
-- test getting relationships for the origin node
rsAny <- getRelationships nodeFrom Any []
neo4jEqual [r] rsAny
rsOutgoing <- getRelationships nodeFrom Outgoing []
neo4jEqual [r] rsOutgoing
rsIncoming <- getRelationships nodeFrom Incoming []
neo4jEqual [] rsIncoming
-- test getting relationships for the destination node
rsAnyTo <- getRelationships nodeTo Any []
neo4jEqual [r] rsAnyTo
rsOutgoingTo <- getRelationships nodeTo Outgoing []
neo4jEqual [] rsOutgoingTo
rsIncomingTo <- getRelationships nodeTo Incoming []
neo4jEqual [r] rsIncomingTo
teardownRelTests nodeFrom nodeTo r
-- | Get relationships for an unexisting node
case_GetUnexistingNodeRelationships :: Assertion
case_GetUnexistingNodeRelationships = do
(nodeFrom, nodeTo, r) <- withConnection host port setupRelTests
let expException = Neo4jNoEntityException $ runNodeIdentifier nodeFrom
assertException expException $ withConnection host port $ do
teardownRelTests nodeFrom nodeTo r
_ <- getRelationships nodeFrom Any []
return ()
-- | Get relationships for a node with multiple relationships
case_GetNodeRelationshipsMultiple :: Assertion
case_GetNodeRelationshipsMultiple = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
r2 <- createRelationship myRelType someOtherProperties nodeTo nodeFrom
rsAny <- getRelationships nodeFrom Any []
neo4jBool (r `elem` rsAny)
neo4jBool (r2 `elem` rsAny)
neo4jEqual 2 (length rsAny)
rsOutgoing <- getRelationships nodeFrom Outgoing []
neo4jEqual [r] rsOutgoing
rsIncoming <- getRelationships nodeFrom Incoming []
neo4jEqual [r2] rsIncoming
deleteRelationship r2
teardownRelTests nodeFrom nodeTo r
-- | Get relationships for a node with a type filter
case_GetNodeRelationshipsWithType :: Assertion
case_GetNodeRelationshipsWithType = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
rsAny <- getRelationships nodeFrom Any [myRelType]
neo4jEqual [r] rsAny
teardownRelTests nodeFrom nodeTo r
-- | Get relationships for a node with an unexisting type filter
case_GetNodeRelationshipsWithUnexistingType :: Assertion
case_GetNodeRelationshipsWithUnexistingType = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
rsAny <- getRelationships nodeFrom Any ["notype"]
neo4jEqual [] rsAny
teardownRelTests nodeFrom nodeTo r
-- | Get relationships for a node with a type filter with multiple elements
case_GetNodeRelationshipsWithTypes :: Assertion
case_GetNodeRelationshipsWithTypes = withConnection host port $ do
(nodeFrom, nodeTo, r) <- setupRelTests
-- Create another relationship with another type
r2 <- createRelationship type2 anotherProperties nodeTo nodeFrom
rsAny <- getRelationships nodeFrom Any [myRelType, type2, "notype"]
neo4jBool (r `elem` rsAny)
neo4jBool (r2 `elem` rsAny)
neo4jEqual 2 (length rsAny)
deleteRelationship r2
teardownRelTests nodeFrom nodeTo r
where type2 = "reltype2"
-- | Get all labels in the DB (We don't have control of all the labels the DB has)
case_getLabels :: Assertion
case_getLabels = withConnection host port $ do
n <- createNode someProperties
addLabels [lbl] n
lbls <- allLabels
neo4jBool $ lbl `elem` lbls
deleteNode n
where lbl = "label1"
-- | Get labels for a node it doesn't have any
case_getNodeLabelsWithNone :: Assertion
case_getNodeLabelsWithNone = withConnection host port $ do
n <- createNode someProperties
lbls <- getLabels n
neo4jEqual [] lbls
deleteNode n
-- | Get labels for an unexisting node
case_getUnexistingNodeLabels :: Assertion
case_getUnexistingNodeLabels = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
_ <- getLabels n
return ()
-- | Add labels to a node and get them
case_getAddAndGetNodeLabels :: Assertion
case_getAddAndGetNodeLabels = withConnection host port $ do
n <- createNode someProperties
addLabels [lbl1, lbl2] n
addLabels [lbl3] n
lbls <- getLabels n
neo4jEqual 3 (length lbls)
neo4jBool $ all (`elem` lbls) [lbl1, lbl2, lbl3]
deleteNode n
where lbl1 = "mylabel1"
lbl2 = "mylabel2"
lbl3 = "mylabel3"
-- | Add labels to an unexisting node
case_addUnexistingNodeLabels :: Assertion
case_addUnexistingNodeLabels = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
addLabels ["mylabel"] n
-- | Change node labels
case_changeNodeLabels :: Assertion
case_changeNodeLabels = withConnection host port $ do
n <- createNode someProperties
addLabels [lbl1, lbl2] n
changeLabels [lbl3] n
lbls <- getLabels n
neo4jEqual [lbl3] lbls
deleteNode n
where lbl1 = "mylabel1"
lbl2 = "mylabel2"
lbl3 = "otherlabel"
-- | Change node labels to empty
case_changeNodeLabelsToEmpty :: Assertion
case_changeNodeLabelsToEmpty = withConnection host port $ do
n <- createNode someProperties
addLabels [lbl1, lbl2] n
changeLabels [] n
lbls <- getLabels n
neo4jEqual [] lbls
deleteNode n
where lbl1 = "mylabel1"
lbl2 = "mylabel2"
-- | Change labels for an unexisting node
case_changeUnexistingNodeLabels :: Assertion
case_changeUnexistingNodeLabels = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
changeLabels ["mylabel"] n
-- | Remove a label from a node
case_removeNodeLabel :: Assertion
case_removeNodeLabel = withConnection host port $ do
n <- createNode someProperties
addLabels [lbl1, lbl2] n
removeLabel lbl1 n
lbls <- getLabels n
neo4jEqual [lbl2] lbls
deleteNode n
where lbl1 = "mylabel1"
lbl2 = "mylabel2"
-- | Remove an unexisting label from a node (nothing should happen)
case_removeNodeUnexistingLabel :: Assertion
case_removeNodeUnexistingLabel = withConnection host port $ do
n <- createNode someProperties
addLabels [lbl1] n
removeLabel "nolabel" n
lbls <- getLabels n
neo4jEqual [lbl1] lbls
deleteNode n
where lbl1 = "mylabel1"
-- | Remove label for an unexisting node
case_removeUnexistingNodeLabel :: Assertion
case_removeUnexistingNodeLabel = do
n <- withConnection host port $ createNode someProperties
let expException = Neo4jNoEntityException $ runNodeIdentifier n
assertException expException $ withConnection host port $ do
deleteNode n
removeLabel "mylabel" n
-- | Get all nodes with a label
case_allNodesWithLabel :: Assertion
case_allNodesWithLabel = withConnection host port $ do
n1 <- createNode someProperties
n2 <- createNode someProperties
n3 <- createNode someProperties
addLabels [lbl1, lbl2] n1
addLabels [lbl2] n2
addLabels [lbl1] n3
ns <- getNodesByLabelAndProperty lbl1 Nothing
neo4jEqual 2 (length ns)
neo4jBool $ all (`elem` ns) [n1, n3]
ns2 <- getNodesByLabelAndProperty "nolbl" Nothing
neo4jEqual [] ns2
mapM_ deleteNode [n1, n2, n3]
where lbl1 = "lbl1"
lbl2 = "lbl2"
-- | Get all nodes with a label and a property
case_allNodesWithLabelAndProperty :: Assertion
case_allNodesWithLabelAndProperty = withConnection host port $ do
n1 <- createNode someProperties
n2 <- createNode someProperties
n3 <- createNode anotherProperties
addLabels [lbl1, lbl2] n1
addLabels [lbl2] n2
addLabels [lbl1] n3
ns <- getNodesByLabelAndProperty lbl1 $ Just ("doublearray", newval [0.1, -12.23 :: Double])
neo4jEqual [n1] ns
ns2 <- getNodesByLabelAndProperty lbl1 $ Just ("doublearray", newval [0.1, -12.22 :: Double])
neo4jEqual [] ns2
mapM_ deleteNode [n1, n2, n3]
where lbl1 = "lbl1"
lbl2 = "lbl2"
-- | Create, get and destroy index
case_createGetDropIndex :: Assertion
case_createGetDropIndex = withConnection host port $ do
dropIndex lbl prop1
dropIndex lbl prop2
dropIndex lbl2 prop1
dropIndex lbl2 prop2
idx1 <- createIndex lbl prop1
idx2 <- createIndex lbl prop2
idx3 <- createIndex lbl2 prop1
idx4 <- createIndex lbl2 prop2
idxs <- getIndexes lbl
neo4jBool $ all (`elem` idxs) [idx1, idx2]
neo4jBool $ all (not . (`elem` idxs)) [idx3, idx4]
idxs2 <- getIndexes lbl2
neo4jBool $ all (not . (`elem` idxs2)) [idx1, idx2]
neo4jBool $ all (`elem` idxs2) [idx3, idx4]
dropIndex lbl prop1
dropIndex lbl prop2
dropIndex lbl2 prop1
dropIndex lbl2 prop2
idxs3 <- getIndexes lbl
idxs4 <- getIndexes lbl2
neo4jBool $ all (not . (`elem` idxs3)) [idx1, idx2]
neo4jBool $ all (not . (`elem` idxs4)) [idx3, idx4]
where lbl = "mylabel11"
lbl2 = "mylabel2"
prop1 = "myprop"
prop2 = "myprop2"
-- | Test batch, create a node and get it again
case_batchCreateGetNode :: Assertion
case_batchCreateGetNode = withConnection host port $ do
g <- B.runBatch $ do
n <- B.createNode someProperties
B.getNode n
neo4jEqual 1 (length $ G.getNodes g)
neo4jBool $ someProperties `elem` map getNodeProperties (G.getNodes g)
deleteNode (head $ G.getNodes g)
-- | Test batch, create two nodes in a batch
case_batchCreate2Nodes :: Assertion
case_batchCreate2Nodes = withConnection host port $ do
g <- B.runBatch $ do
_ <- B.createNode someProperties
B.createNode anotherProperties
neo4jEqual 2 (length $ G.getNodes g)
neo4jBool $ someProperties `elem` map getNodeProperties (G.getNodes g)
neo4jBool $ anotherProperties `elem` map getNodeProperties (G.getNodes g)
mapM_ deleteNode (G.getNodes g)
-- | Test batch, create and delete
case_batchCreateDeleteNode :: Assertion
case_batchCreateDeleteNode = withConnection host port $ do
g <- B.runBatch $ do
n <- B.createNode someProperties
B.deleteNode n
neo4jEqual 0 (length $ G.getNodes g)
-- | Test batch, create two nodes and two relationships between them
case_batchCreateRelationships :: Assertion
case_batchCreateRelationships = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
_ <- B.createRelationship "type1" someOtherProperties n1 n2
B.createRelationship "type2" someProperties n2 n1
neo4jEqual 2 (length $ G.getNodes g)
neo4jEqual 2 (length $ G.getRelationships g)
neo4jBool $ someOtherProperties `elem` map getRelProperties (G.getRelationships g)
neo4jBool $ someProperties `elem` map getRelProperties (G.getRelationships g)
neo4jBool $ "type1" `elem` map getRelType (G.getRelationships g)
neo4jBool $ "type2" `elem` map getRelType (G.getRelationships g)
let r1 : r2 : [] = G.getRelationships g
neo4jEqual (G.getRelationshipNodeFrom r1 g) (G.getRelationshipNodeTo r2 g)
neo4jEqual (G.getRelationshipNodeFrom r2 g) (G.getRelationshipNodeTo r1 g)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, create and delete a relationship
case_batchCreateDelRelationships :: Assertion
case_batchCreateDelRelationships = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
r <- B.createRelationship "type1" someOtherProperties n1 n2
B.deleteRelationship r
neo4jEqual 2 (length $ G.getNodes g)
neo4jEqual 0 (length $ G.getRelationships g)
mapM_ deleteRelationship (G.getRelationships g)
mapM_ deleteNode (G.getNodes g)
-- | Test batch getRelationshipFrom
case_batchRelationshipNodeFrom :: Assertion
case_batchRelationshipNodeFrom = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
B.createRelationship "type1" someOtherProperties n1 n2
g2 <- B.runBatch $ B.getRelationshipFrom (head $ G.getRelationships g)
neo4jEqual 1 (length $ G.getNodes g2)
neo4jEqual 0 (length $ G.getRelationships g2)
neo4jBool $ someProperties `elem` map getNodeProperties (G.getNodes g2)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch getRelationshipTo
case_batchRelationshipNodeTo :: Assertion
case_batchRelationshipNodeTo = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
B.createRelationship "type1" someOtherProperties n1 n2
g2 <- B.runBatch $ B.getRelationshipTo (head $ G.getRelationships g)
neo4jEqual 1 (length $ G.getNodes g2)
neo4jEqual 0 (length $ G.getRelationships g2)
neo4jBool $ anotherProperties `elem` map getNodeProperties (G.getNodes g2)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, get all relationships with filter
case_batchGetRelationships :: Assertion
case_batchGetRelationships = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
_ <- B.createRelationship "type1" someOtherProperties n1 n2
B.createRelationship "type2" someProperties n2 n1
g2 <- B.runBatch $ do
let n = head $ G.getNodes g
B.getRelationships n Any ["type1", "type2"]
neo4jEqual 2 (length $ G.getRelationships g2)
neo4jBool $ someOtherProperties `elem` map getRelProperties (G.getRelationships g2)
neo4jBool $ someProperties `elem` map getRelProperties (G.getRelationships g2)
neo4jBool $ "type1" `elem` map getRelType (G.getRelationships g2)
neo4jBool $ "type2" `elem` map getRelType (G.getRelationships g2)
mapM_ deleteRelationship (G.getRelationships g)
mapM_ deleteNode (G.getNodes g)
-- | Test batch, set properties
case_batchSetProperties :: Assertion
case_batchSetProperties = withConnection host port $ do
let newProperties = M.fromList ["croqueta" |: ("2" :: T.Text)]
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
r <- B.createRelationship "type1" someOtherProperties n1 n2
_ <- B.setProperties n1 newProperties
B.setProperties r newProperties
neo4jEqual 2 (length $ G.getNodes g)
neo4jEqual 1 (length $ G.getRelationships g)
neo4jBool $ newProperties `elem` map getRelProperties (G.getRelationships g)
neo4jBool $ newProperties `elem` map getNodeProperties (G.getNodes g)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, set property
case_batchSetProperty :: Assertion
case_batchSetProperty = withConnection host port $ do
let key = "hola"
let val = newval False
let newSomeProperties = M.insert key val someProperties
let newSomeOtherProperties = M.insert key val someOtherProperties
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
r <- B.createRelationship "type1" someOtherProperties n1 n2
_ <- B.setProperty n1 key val
B.setProperty r key val
neo4jEqual 2 (length $ G.getNodes g)
neo4jEqual 1 (length $ G.getRelationships g)
neo4jBool $ newSomeProperties `elem` map getNodeProperties (G.getNodes g)
neo4jBool $ newSomeOtherProperties `elem` map getRelProperties (G.getRelationships g)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, delete properties
case_batchDeleteProperties :: Assertion
case_batchDeleteProperties = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
r <- B.createRelationship "type1" someOtherProperties n1 n2
_ <- B.deleteProperties n1
B.deleteProperties r
neo4jEqual 2 (length $ G.getNodes g)
neo4jEqual 1 (length $ G.getRelationships g)
neo4jBool $ emptyProperties `elem` map getRelProperties (G.getRelationships g)
neo4jBool $ emptyProperties `elem` map getNodeProperties (G.getNodes g)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, delete property
case_batchDeleteProperty :: Assertion
case_batchDeleteProperty= withConnection host port $ do
let key = "mytext"
let newSomeProperties = M.delete key someProperties
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
r <- B.createRelationship "type1" someProperties n1 n2
_ <- B.deleteProperty n1 key
B.deleteProperty r key
neo4jEqual 2 (length $ G.getNodes g)
neo4jEqual 1 (length $ G.getRelationships g)
neo4jBool $ newSomeProperties `elem` map getNodeProperties (G.getNodes g)
neo4jBool $ newSomeProperties `elem` map getRelProperties (G.getRelationships g)
_ <- B.runBatch $ do
mapM_ B.deleteRelationship (G.getRelationships g)
mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, delete an unknown property, it should raise an exception
case_batchDeleteUnknownProperty :: Assertion
case_batchDeleteUnknownProperty= do
n <- withConnection host port $ createNode someProperties
let excMsg = "Node[" <> TE.decodeUtf8 (nodeId n) <>"] does not have a property \"" <> prop <> "\""
let expException = Neo4jNoSuchProperty excMsg
assertException expException $ withConnection host port $ do
g <- B.runBatch $ B.deleteProperty n prop
neo4jEqual G.empty g -- Doing this to force evaluation
withConnection host port $ deleteNode n
where prop = "noprop" :: T.Text
-- | Test batch, set add labels
case_batchAddLabels :: Assertion
case_batchAddLabels = withConnection host port $ do
let label1 = "label1"
let label2 = "label2"
let label3 = "label3"
let labelset = HS.fromList [label1, label2, label3]
g <- B.runBatch $ do
n1 <- B.createNode someProperties
_ <- B.createNode anotherProperties
_ <- B.addLabels [label1, label2] n1
B.addLabels [label3] n1
neo4jEqual 2 (length $ G.getNodes g)
neo4jBool $ labelset `elem` map (`G.getNodeLabels` g) (G.getNodes g)
neo4jBool $ HS.empty `elem` map (`G.getNodeLabels` g) (G.getNodes g)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, change labels
case_batchChangeLabels :: Assertion
case_batchChangeLabels = withConnection host port $ do
let label1 = "label1"
let label2 = "label2"
let label3 = "label3"
let labelset = HS.fromList [label2]
g <- B.runBatch $ do
n1 <- B.createNode someProperties
_ <- B.addLabels [label1, label2, label3] n1
B.changeLabels [label2] n1
neo4jBool $ labelset `elem` map (`G.getNodeLabels` g) (G.getNodes g)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, remove label
case_batchRemoveLabel :: Assertion
case_batchRemoveLabel = withConnection host port $ do
let label1 = "label1"
let label2 = "label2"
let label3 = "label3"
let labelset = HS.fromList [label2, label3]
g <- B.runBatch $ do
n1 <- B.createNode someProperties
_ <- B.addLabels [label1, label2, label3] n1
B.removeLabel label1 n1
neo4jBool $ labelset `elem` map (`G.getNodeLabels` g) (G.getNodes g)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes g)
return ()
-- | Test batch, get all nodes with a label
case_batchAllNodesWithLabel :: Assertion
case_batchAllNodesWithLabel = withConnection host port $ do
gp <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode someProperties
n3 <- B.createNode someProperties
_ <- B.addLabels [lbl1, lbl2] n1
_ <- B.addLabels [lbl2] n2
B.addLabels [lbl1] n3
g <- B.runBatch $ B.getNodesByLabelAndProperty lbl1 Nothing
neo4jEqual 2 (length $ G.getNodes g)
neo4jBool $ all (`elem` G.getNodes gp) (G.getNodes g)
gempty <- B.runBatch $ B.getNodesByLabelAndProperty "nolbl" Nothing
neo4jEqual [] (G.getNodes gempty)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where lbl1 = "la21bl1"
lbl2 = "la21bl2"
-- | Test batch, get all nodes with a label and a property
case_batchAllNodesWithLabelAndProperty :: Assertion
case_batchAllNodesWithLabelAndProperty = withConnection host port $ do
gp <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode someProperties
n3 <- B.createNode anotherProperties
_ <- B.addLabels [lbl1, lbl2] n1
_ <- B.addLabels [lbl2] n2
B.addLabels [lbl1] n3
g <- B.runBatch $ B.getNodesByLabelAndProperty lbl1 $ Just ("doublearray", newval [0.1, -12.23 :: Double])
neo4jEqual 1 (length $ G.getNodes g)
neo4jBool $ all (`elem` G.getNodes gp) (G.getNodes g)
g2 <- B.runBatch $ B.getNodesByLabelAndProperty lbl1 $ Just ("doublearray", newval [0.1, -12.22 :: Double])
neo4jEqual [] (G.getNodes g2)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where lbl1 = "lbl1"
lbl2 = "lbl2"
-- | Test cypher basic test
case_cypherBasic :: Assertion
case_cypherBasic = withConnection host port $ do
-- create initial data
gp <- B.runBatch $ do
n1 <- B.createNode $ M.fromList ["name" |: ("I" :: T.Text)]
n2 <- B.createNode $ M.fromList ["name" |: ("you" :: T.Text)]
B.createRelationship "know" M.empty n1 n2
-- actual test
res <- TC.loneQuery query params
neo4jBool $ TC.isSuccess res
neo4jEqual ["TYPE(r)"] (TC.cols $ TC.fromSuccess res)
neo4jBool $ ["know"] `elem` (TC.vals $ TC.fromSuccess res)
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "MATCH (x {name: {startName}})-[r]-(friend) WHERE friend.name = {name} RETURN TYPE(r)"
params = M.fromList [("startName", TC.newparam ("I" :: T.Text)), ("name", TC.newparam ("you" :: T.Text))]
-- | Test cypher create a node
case_cypherCreateNode :: Assertion
case_cypherCreateNode = withConnection host port $ do
res <- TC.loneQuery query params
let gp = (head . TC.graph) (TC.fromSuccess res)
let props = M.fromList ["name" |: ("Andres" :: T.Text)]
neo4jEqual 1 (length $ G.getNodes gp)
neo4jBool $ props `elem` map getNodeProperties (G.getNodes gp)
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "CREATE (n:Person { name : {name} }) RETURN n"
params = M.fromList [("name", TC.newparam ("Andres" :: T.Text))]
-- | Test cypher create a node with multiple properties
case_cypherCreateNodeMultipleProperties :: Assertion
case_cypherCreateNodeMultipleProperties = withConnection host port $ do
res <- TC.loneQuery query params
neo4jBool $ TC.isSuccess res
let gp = (head . TC.graph) (TC.fromSuccess res)
neo4jEqual 1 (length $ G.getNodes gp)
neo4jBool $ props `elem` map getNodeProperties (G.getNodes gp)
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "CREATE (n:Person { props }) RETURN n"
props = M.fromList ["name" |: ("Michael" :: T.Text), "position" |: ("Developer" :: T.Text),
"awesome" |: True, "children" |: (3 :: Int64)]
params = M.fromList [("props", TC.ParamProperties props)]
-- | Test cypher set all properties on a node
case_cypherSetAllNodeProperties :: Assertion
case_cypherSetAllNodeProperties = withConnection host port $ do
res <- TC.loneQuery query params
neo4jBool $ TC.isSuccess res
let gp = (head . TC.graph) (TC.fromSuccess res)
neo4jEqual 1 (length $ G.getNodes gp)
neo4jBool $ props `elem` map getNodeProperties (G.getNodes gp)
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "CREATE (n:Person { name: 'this property is to be deleted' } ) SET n = { props } RETURN n"
props = M.fromList ["name" |: ("Michael" :: T.Text), "position" |: ("Developer" :: T.Text),
"awesome" |: True, "children" |: (3 :: Int64)]
params = M.fromList [("props", TC.ParamProperties props)]
-- | Test cypher basic query
case_cypherBasicQuery :: Assertion
case_cypherBasicQuery = withConnection host port $ do
-- create initial data
gp <- B.runBatch $ do
n1 <- B.createNode $ M.fromList ["name" |: ("I" :: T.Text)]
n2 <- B.createNode $ M.fromList ["name" |: ("you" :: T.Text)]
n3 <- B.createNode $ M.fromList ["name" |: ("him" :: T.Text), "age" |: (25 :: Int64)]
_ <- B.createRelationship "know" M.empty n1 n2
B.createRelationship "know" M.empty n1 n3
-- actual test
res <- TC.loneQuery query params
neo4jBool $ TC.isSuccess res
neo4jEqual ["type(r)", "n.name", "n.age"] (TC.cols $ TC.fromSuccess res)
neo4jBool $ ["know", "him", J.Number 25] `elem` (TC.vals $ TC.fromSuccess res)
neo4jBool $ ["know", "you", J.Null] `elem` (TC.vals $ TC.fromSuccess res)
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "MATCH (x {name: 'I'})-[r]->(n) RETURN type(r), n.name, n.age"
params = M.empty
-- | Test cypher basic query get relationships
case_cypherBasicQueryGetRels :: Assertion
case_cypherBasicQueryGetRels = withConnection host port $ do
-- create initial data
gp <- B.runBatch $ do
n1 <- B.createNode $ M.fromList ["name" |: ("I" :: T.Text)]
n2 <- B.createNode $ M.fromList ["name" |: ("you" :: T.Text)]
n3 <- B.createNode $ M.fromList ["name" |: ("him" :: T.Text), "age" |: (25 :: Int64)]
B.createRelationship "KNOW" M.empty n1 n2
B.createRelationship "KNOW" M.empty n1 n3
-- actual test
res <- TC.loneQuery query params
TC.loneQuery "MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE n,r" M.empty
neo4jBool $ TC.isSuccess res
let row1 = (head . TC.graph . TC.fromSuccess) res
let row2 = (head . tail . TC.graph . TC.fromSuccess) res
neo4jEqual 1 (length $ G.getRelationships row1)
neo4jEqual 1 (length $ G.getRelationships row2)
neo4jBool $ all (\r -> getRelType r == "KNOW") (G.getRelationships row1)
neo4jBool $ all (\r -> getRelType r == "KNOW") (G.getRelationships row2)
neo4jEqual ["r"] (TC.cols $ TC.fromSuccess res)
-- cleanup
return ()
where query = "MATCH (x {name: 'I'})-[r]->(n) RETURN r"
params = M.empty
-- | Test cypher nested results
case_cypherNestedResults :: Assertion
case_cypherNestedResults = withConnection host port $ do
-- create initial data
gp <- B.runBatch $ do
n1 <- B.createNode $ M.fromList ["name" |: ("I" :: T.Text)]
n2 <- B.createNode $ M.fromList ["name" |: ("you" :: T.Text)]
B.createRelationship "know" M.empty n1 n2
-- actual test
res <- TC.loneQuery query params
neo4jBool $ TC.isSuccess res
neo4jEqual ["collect(n.name)"] (TC.cols $ TC.fromSuccess res)
let v = case (head $ head $ TC.vals $ TC.fromSuccess res) of
J.Array vec -> vec
_ -> V.empty
neo4jBool $ "you" `V.elem` v
neo4jBool $ "I" `V.elem` v
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "MATCH (n) WHERE n.name in ['I', 'you'] RETURN collect(n.name)"
params = M.empty
-- | Test lone transaction cypher basic query
case_loneTransactionBasicQuery :: Assertion
case_loneTransactionBasicQuery = withConnection host port $ do
-- create initial data
gp <- B.runBatch $ do
n1 <- B.createNode $ M.fromList ["name" |: ("I" :: T.Text)]
n2 <- B.createNode $ M.fromList ["name" |: ("you" :: T.Text)]
n3 <- B.createNode $ M.fromList ["name" |: ("him" :: T.Text), "age" |: (25 :: Int64)]
_ <- B.createRelationship "know" M.empty n1 n2
B.createRelationship "know" M.empty n1 n3
-- actual test
res <- TC.loneQuery query params
neo4jBool $ TC.isSuccess res
neo4jEqual ["type(r)", "n.name", "n.age"] (TC.cols $ TC.fromSuccess res)
neo4jBool $ ["know", "him", J.Number 25] `elem` (TC.vals $ TC.fromSuccess res)
neo4jBool $ ["know", "you", J.Null] `elem` (TC.vals $ TC.fromSuccess res)
neo4jEqual TC.emptyStats (TC.stats $ TC.fromSuccess res)
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "MATCH (x {name: 'I'})-[r]->(n) RETURN type(r), n.name, n.age"
params = M.empty
-- | Test cypher errors in a transaction
case_cypherTransactionError :: Assertion
case_cypherTransactionError = withConnection host port $ do
-- create initial data
gp <- B.runBatch $ B.createNode $ M.fromList ["age" |: (26 :: Int64)]
-- actual test
res <- TC.loneQuery query params
neo4jEqual (Left ("Neo.ClientError.Statement.ArithmeticError","/ by zero")) res
-- cleanup
_ <- B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
return ()
where query = "MATCH (x) WHERE has(x.age) RETURN x.age / 0"
params = M.empty
-- | Test a cypher transaction
case_cypherTransaction :: Assertion
case_cypherTransaction = withConnection host port $ do
res <- TC.runTransaction $ do
result <- TC.cypher "CREATE (pere: PERSON {age: {age}}) \
\CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
voidIO $ assertEqual "" ["pere", "pau", "p1", "pere.age"] (TC.cols result)
voidIO $ assertEqual "" (TC.Stats True 2 0 2 1 0 2 0 0 0 0 0) (TC.stats result)
let vals = TC.vals result
voidIO $ assertEqual "" 1 (length vals)
voidIO $ assertEqual "" 4 (length $ head vals)
voidIO $ assertEqual "" (J.Number 78.0) (head vals !! 3)
voidIO $ assertEqual "" 1 (length $ TC.graph result)
voidIO $ assertEqual "" 1 (length $ G.getRelationships (head $ TC.graph result))
voidIO $ assertEqual "" 2 (length $ G.getNodes (head $ TC.graph result))
return result
neo4jBool $ TC.isSuccess res
let (Right tresult) = res
let gp = head $ TC.graph tresult
void $ B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
void $ B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
where voidIO x = void $ liftIO x
-- | Test a cypher transaction with a explicit commit
case_cypherTransactionExplicitCommit :: Assertion
case_cypherTransactionExplicitCommit = withConnection host port $ do
res <- TC.runTransaction $ do
result <- TC.cypher "CREATE (pere: PERSON {age: {age}}) CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
void $ TC.cypher "CREATE (pep: PERSON {age: 55})" M.empty
TC.commit
return result
neo4jBool $ TC.isSuccess res
let (Right result) = res
voidIO $ assertEqual "" ["pere", "pau", "p1", "pere.age"] (TC.cols result)
voidIO $ assertEqual "" (TC.Stats True 2 0 2 1 0 2 0 0 0 0 0) (TC.stats result)
let vals = TC.vals result
voidIO $ assertEqual "" 1 (length vals)
voidIO $ assertEqual "" 4 (length $ head vals)
voidIO $ assertEqual "" (J.Number 78.0) (head vals !! 3)
voidIO $ assertEqual "" 1 (length $ TC.graph result)
voidIO $ assertEqual "" 1 (length $ G.getRelationships (head $ TC.graph result))
voidIO $ assertEqual "" 2 (length $ G.getNodes (head $ TC.graph result))
let gp = head $ TC.graph result
void $ B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
void $ B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
where voidIO x = void $ liftIO x
-- | Test a cypher transaction with a keepalive
case_cypherTransactionKeepAlive :: Assertion
case_cypherTransactionKeepAlive = withConnection host port $ do
res <- TC.runTransaction $ do
TC.keepalive
void $ TC.cypher "CREATE (pep: PERSON {age: 55})" M.empty
TC.keepalive
result <- TC.cypher "CREATE (pere: PERSON {age: {age}}) CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
return result
neo4jBool $ TC.isSuccess res
let (Right result) = res
voidIO $ assertEqual "" ["pere", "pau", "p1", "pere.age"] (TC.cols result)
voidIO $ assertEqual "" (TC.Stats True 2 0 2 1 0 2 0 0 0 0 0) (TC.stats result)
let vals = TC.vals result
voidIO $ assertEqual "" 1 (length vals)
voidIO $ assertEqual "" 4 (length $ head vals)
voidIO $ assertEqual "" (J.Number 78.0) (head vals !! 3)
voidIO $ assertEqual "" 1 (length $ TC.graph result)
voidIO $ assertEqual "" 1 (length $ G.getRelationships (head $ TC.graph result))
voidIO $ assertEqual "" 2 (length $ G.getNodes (head $ TC.graph result))
let gp = head $ TC.graph result
void $ B.runBatch $ mapM_ B.deleteRelationship (G.getRelationships gp)
void $ B.runBatch $ mapM_ B.deleteNode (G.getNodes gp)
where voidIO x = void $ liftIO x
-- | Test a cypher transaction with an error
case_cypherErrorInTransaction :: Assertion
case_cypherErrorInTransaction = withConnection host port $ do
res <- TC.runTransaction $ do
-- query with wrong syntax
void $ TC.cypher "i" M.empty
TC.cypher "CREATE (pere: PERSON {age: {age}}) CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
neo4jBool $ not $ TC.isSuccess res
neo4jEqual (Left ("Neo.ClientError.Statement.InvalidSyntax",
"Invalid input 'i': expected <init> (line 1, column 1)\n\"i\"\n ^")) res
-- | Test a cypher rollback transaction
case_cypherTransactionRollback :: Assertion
case_cypherTransactionRollback = withConnection host port $ do
void $ TC.runTransaction $ do
void $ TC.cypher "CREATE (pepe: PERSON {age: 55})" M.empty
result <- TC.cypher "CREATE (pere: PERSON {age: {age}}) CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
TC.rollback
return result
-- | Test a cypher rollback and leave transaction
case_cypherTransactionRollbackAndLeave :: Assertion
case_cypherTransactionRollbackAndLeave = withConnection host port $ do
res <- TC.runTransaction $ do
void $ TC.cypher "CREATE (pepe: PERSON {age: 55})" M.empty
result <- TC.cypher "CREATE (pere: PERSON {age: {age}}) CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
TC.rollbackAndLeave "My message"
TC.commit
TC.rollback
return result
neo4jEqual (Left ("Rollback", "My message")) res
-- | Test issuing a commits after a rollback
case_cypherTransactionEnded :: Assertion
case_cypherTransactionEnded = assertException expException $ withConnection host port $ do
void $ TC.runTransaction $ do
void $ TC.cypher "CREATE (pepe: PERSON {age: 55})" M.empty
result <- TC.cypher "CREATE (pere: PERSON {age: {age}}) CREATE (pau: PERSON {props}) \
\CREATE p1 = (pere)-[:KNOWS]->(pau) RETURN pere, pau, p1, pere.age" $
M.fromList [("age", TC.newparam (78 :: Int64)),
("props", TC.ParamProperties $ M.fromList["age" |: (99 :: Int64)])]
TC.rollback
TC.commit
return result
where expException = TransactionEndedExc
-- | Test graph union op
case_graphUnion :: Assertion
case_graphUnion = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
void $ B.addLabels ["a"] n1
_ <- B.createRelationship "type1" someOtherProperties n1 n2
B.createRelationship "type2" someProperties n2 n1
g2 <- B.runBatch $ do
n1 <- B.createNode someOtherProperties
n2 <- B.createNode anotherProperties
void $ B.addLabels ["b"] n1
_ <- B.createRelationship "type1" someOtherProperties n1 n2
B.createRelationship "type2" someProperties n2 n1
let g3 = g `G.union` g2
neo4jEqual 4 (length $ G.getNodes g3)
neo4jEqual 4 (length $ G.getRelationships g3)
neo4jBool $ someOtherProperties `elem` map getRelProperties (G.getRelationships g3)
neo4jBool $ someProperties `elem` map getRelProperties (G.getRelationships g3)
neo4jBool $ someOtherProperties `elem` map getNodeProperties (G.getNodes g3)
neo4jBool $ someProperties `elem` map getNodeProperties (G.getNodes g3)
neo4jBool $ "type1" `elem` map getRelType (G.getRelationships g3)
neo4jBool $ "type2" `elem` map getRelType (G.getRelationships g3)
neo4jBool $ "a" `elem` (join $ map (HS.toList . (flip G.getNodeLabels g3)) (G.getNodes g3))
neo4jBool $ "b" `elem` (join $ map (HS.toList . (flip G.getNodeLabels g3)) (G.getNodes g3))
mapM_ deleteRelationship (G.getRelationships g3)
mapM_ deleteNode (G.getNodes g3)
-- | Test graph difference op
case_graphDifference :: Assertion
case_graphDifference = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
void $ B.addLabels ["a"] n1
_ <- B.createRelationship "type1" someOtherProperties n1 n2
B.createRelationship "type2" someProperties n2 n1
let g2 = g `G.difference` g
neo4jEqual 0 (length $ G.getRelationships g2)
neo4jEqual 0 (length $ G.getNodes g2)
let subGraph = G.deleteNode (head $ G.getNodes g) g
let g3 = g `G.difference` (G.deleteRelationship (head $ G.getRelationships subGraph) subGraph)
neo4jEqual 1 (length $ G.getRelationships g3)
neo4jEqual 1 (length $ G.getNodes g3)
-- | Test graph intersection op
case_graphIntersection :: Assertion
case_graphIntersection = withConnection host port $ do
g <- B.runBatch $ do
n1 <- B.createNode someProperties
n2 <- B.createNode anotherProperties
void $ B.addLabels ["a"] n1
_ <- B.createRelationship "type1" someOtherProperties n1 n2
B.createRelationship "type2" someProperties n2 n1
g2 <- B.runBatch $ do
B.createNode someProperties
let g3 = G.addNode (head $ G.getNodes g) g2
let g4 = g `G.intersection` (G.addRelationship (head $ G.getRelationships g) g3)
neo4jEqual 1 (length $ G.getRelationships g4)
neo4jEqual 1 (length $ G.getNodes g4)
neo4jEqual (head $ G.getRelationships g) (head $ G.getRelationships g4)
neo4jEqual (head $ G.getNodes g) (head $ G.getNodes g4)