This repository has been archived by the owner on Jan 19, 2022. It is now read-only.
/
ApiExtensionsSpec.groovy
236 lines (191 loc) · 9.12 KB
/
ApiExtensionsSpec.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package org.grails.datastore.gorm.neo4j
import grails.gorm.tests.GormDatastoreSpec
import grails.gorm.tests.Person
import grails.gorm.tests.Pet
import org.neo4j.graphdb.Direction
import org.neo4j.graphdb.ReturnableEvaluator
import org.neo4j.graphdb.StopEvaluator
import org.neo4j.graphdb.TraversalPosition
import org.neo4j.graphdb.Traverser
import org.neo4j.graphdb.Node
import spock.lang.IgnoreRest
import grails.gorm.tests.PetType
import org.neo4j.graphdb.GraphDatabaseService
import org.neo4j.tooling.GlobalGraphOperations
import org.neo4j.visualization.asciidoc.AsciidocHelper
import org.neo4j.graphdb.traversal.TraversalDescription
import org.neo4j.kernel.Traversal
import org.neo4j.graphdb.Path
/**
* check the traverser extension
*/
class ApiExtensionsSpec extends GormDatastoreSpec {
def "test static traversing"() {
given:
new Person(lastName: "person1").save()
new Person(lastName: "person2").save()
when:
def traverserResult = Person.traverseStatic(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE,
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH)
def size = traverserResult.size()
then:
size == Person.traverseStatic(StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE,
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH).size()
size+1 == Person.traverseStatic(Traverser.Order.BREADTH_FIRST,
{ TraversalPosition p -> false },
{ TraversalPosition p -> true },
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH).size()
size+1 == Person.traverseStatic(
{ TraversalPosition p -> false },
{ TraversalPosition p -> true },
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH, GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.BOTH).size()
size+1 == Person.traverseStatic(
{ TraversalPosition p -> false },
{ TraversalPosition p -> true } ).size()
//println AsciidocHelper.createGraphViz("title", session.nativeInterface, "abc");
/*Node subReferenceNode = ((Neo4jDatastore)session.datastore).subReferenceNodes[Person.class.name]
Traversal.description().depthFirst()
.relationships(GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING)
.relationships(GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING)
.traverse(subReferenceNode).each { Path p ->
println p
}*/
Person.count() == Person.traverseStatic(
{ return false },
{ TraversalPosition p -> return p.currentNode().getProperty("__type__", null) == Person.name },
GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING,
GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING,
).size()
// +2: referenceNode + self (aka subreferenceNode)
Person.count()+2 == Person.traverseStatic(
{ TraversalPosition p -> false },
{ TraversalPosition p -> true },
GrailsRelationshipTypes.SUBREFERENCE, Direction.OUTGOING,
GrailsRelationshipTypes.SUBSUBREFERENCE, Direction.OUTGOING,
GrailsRelationshipTypes.INSTANCE, Direction.OUTGOING,
).size()
}
def "test instance based traversing"() {
given:
def person = new Person(lastName: "person1")
person.save()
new Person(lastName: "person2").save()
when:
def traverserResult = person.traverse(Traverser.Order.BREADTH_FIRST, StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE,
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH)
def size = traverserResult.size()
then:
size == person.traverse(StopEvaluator.END_OF_GRAPH, ReturnableEvaluator.ALL_BUT_START_NODE,
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size()
size+1 == person.traverse(Traverser.Order.BREADTH_FIRST,
{ TraversalPosition p -> false },
{ TraversalPosition p -> true },
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size()
size+1 == person.traverse(
{ TraversalPosition p -> false },
{ TraversalPosition p -> true },
GrailsRelationshipTypes.INSTANCE, Direction.BOTH, GrailsRelationshipTypes.SUBREFERENCE, Direction.BOTH).size()
size+1 == person.traverse(
{ TraversalPosition p -> false },
{ TraversalPosition p -> true } ).size()
Person.count() == person.traverse(
{ TraversalPosition p -> false },
{ TraversalPosition p -> p.currentNode().getProperty("__type__",null) == Person.name } ).size()
1 == person.traverse(
{ TraversalPosition p -> true },
{ TraversalPosition p -> true } ).size()
}
def "test createInstanceForNode"() {
given:
def person = new Person(lastName: 'person1')
person.save()
def pet = new Pet(name: 'pet')
person.save()
when: "retrieve a instance only by id"
def instance = Pet.createInstanceForNode(person.id)
then:
instance instanceof Person
instance.lastName == 'person1'
when: "look up non-existing id"
instance = Pet.createInstanceForNode(999)
then:
instance == null
}
def "test handling of non-declared properties"() {
when:
def person = new Person(lastName:'person1').save()
person['notDeclaredProperty'] = 'someValue' // n.b. the 'dot' notation is not valid for undeclared properties
person['emptyArray'] = []
person['someIntArray'] = [1,2,3]
person['someStringArray'] = ['a', 'b', 'c']
person['someDoubleArray'] = [0.9, 1.0, 1.1]
session.flush()
session.clear()
person = Person.get(person.id)
then:
person['notDeclaredProperty'] == 'someValue'
person['lastName'] == 'person1' // declared properties are also available via map semantics
person['someIntArray'] == [1,2,3]
person['someStringArray'] == ['a', 'b', 'c']
person['someDoubleArray'] == [0.9, 1.0, 1.1]
}
def "test handling of non-declared properties using dot notation"() {
when:
def person = new Person(lastName:'person1').save(flush:true)
session.clear()
person = Person.load(person.id)
person.notDeclaredProperty = 'someValue' // n.b. the 'dot' notation is not valid for undeclared properties
person.emptyArray = []
person.someIntArray = [1,2,3]
person.someStringArray = ['a', 'b', 'c']
person.someDoubleArray= [0.9, 1.0, 1.1]
session.flush()
session.clear()
person = Person.get(person.id)
then:
person.notDeclaredProperty == 'someValue'
person.lastName == 'person1' // declared properties are also available via map semantics
person.someIntArray == [1,2,3]
person.someStringArray == ['a', 'b', 'c']
person.emptyArray == []
person.someDoubleArray == [0.9, 1.0, 1.1]
}
def "test handling of non-declared properties on transient instance"() {
when:
def person = new Person(lastName:'person1')
person['notDeclaredProperty'] = 'someValue'
then:
thrown(IllegalStateException)
}
def "test handling of non-declared properties that do not match valid types in neo4j"() {
when:
def person = new Person(lastName:'person1')
person['notDeclaredProperty'] = new Date()
then:
thrown(IllegalStateException)
}
def "test cypher queries"() {
setup:
new Person(lastName:'person1').save()
new Person(lastName:'person2').save()
session.flush()
session.clear()
when:
def result = Person.cypherStatic("start n=node({this}) match n-[:SUBSUBREFERENCE]->subRef-[:INSTANCE]->m where m.lastName='person1' return m")
then:
result.iterator().size()==1
}
def "test instance based cypher query"() {
setup:
def person = new Person(firstName: "Bob", lastName: "Builder")
def petType = new PetType(name: "snake")
def pet = new Pet(name: "Fred", type: petType, owner: person)
person.addToPets(pet)
person.save(flush: true)
session.clear()
when:
def result = person.cypher("start n=node({this}) match n-[:pets]->m return m")
then:
result.iterator().size() == 1
}
}