1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.neo4j.server.rest.web;
21
22 import static org.hamcrest.Matchers.containsString;
23 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
24 import static org.hamcrest.Matchers.hasKey;
25 import static org.hamcrest.Matchers.is;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertNull;
30 import static org.junit.Assert.assertThat;
31 import static org.junit.Assert.assertTrue;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.when;
34
35 import java.io.File;
36 import java.io.IOException;
37 import java.io.UnsupportedEncodingException;
38 import java.net.URI;
39 import java.net.URISyntaxException;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45
46 import javax.ws.rs.core.HttpHeaders;
47 import javax.ws.rs.core.Response;
48 import javax.ws.rs.core.Response.Status;
49 import javax.ws.rs.core.UriInfo;
50
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.neo4j.helpers.collection.MapUtil;
55 import org.neo4j.server.ServerTestUtils;
56 import org.neo4j.server.database.Database;
57 import org.neo4j.server.database.DatabaseBlockedException;
58 import org.neo4j.server.rest.domain.GraphDbHelper;
59 import org.neo4j.server.rest.domain.JsonHelper;
60 import org.neo4j.server.rest.domain.JsonParseException;
61 import org.neo4j.server.rest.domain.TraverserReturnType;
62 import org.neo4j.server.rest.repr.BadInputException;
63 import org.neo4j.server.rest.repr.RelationshipRepresentationTest;
64 import org.neo4j.server.rest.repr.formats.JsonFormat;
65 import org.neo4j.server.rest.web.DatabaseActions.RelationshipDirection;
66 import org.neo4j.server.rest.web.RestfulGraphDatabase.AmpersandSeparatedCollection;
67
68 public class RestfulGraphDatabaseTest
69 {
70 private static final String BASE_URI = "http://neo4j.org/";
71 private RestfulGraphDatabase service;
72 private Database database;
73 private GraphDbHelper helper;
74 private EntityOutputFormat output;
75 private String databasePath;
76
77 @Before
78 public void doBefore() throws IOException
79 {
80 databasePath = ServerTestUtils.createTempDir().getAbsolutePath();
81 database = new Database( ServerTestUtils.EMBEDDED_GRAPH_DATABASE_FACTORY, databasePath );
82 helper = new GraphDbHelper( database );
83 output = new EntityOutputFormat( new JsonFormat(), URI.create( BASE_URI ), null );
84 service = new RestfulGraphDatabase( uriInfo(), database, new JsonFormat(), output );
85 }
86
87 @After
88 public void shutdownDatabase() throws IOException
89 {
90 this.database.shutdown();
91 org.apache.commons.io.FileUtils.forceDelete( new File(databasePath) );
92 }
93
94 private UriInfo uriInfo()
95 {
96 UriInfo mockUriInfo = mock( UriInfo.class );
97 try
98 {
99 when( mockUriInfo.getBaseUri() ).thenReturn( new URI( BASE_URI ) );
100 } catch ( URISyntaxException e )
101 {
102 throw new RuntimeException( e );
103 }
104
105 return mockUriInfo;
106 }
107
108 private static String entityAsString( Response response )
109 {
110 byte[] bytes = (byte[]) response.getEntity();
111 try
112 {
113 return new String( bytes, "UTF-8" );
114 } catch ( UnsupportedEncodingException e )
115 {
116 throw new RuntimeException( "Could not decode UTF-8", e );
117 }
118 }
119
120 @Test
121 public void shouldRespondWith201LocationHeaderAndNodeRepresentationInJSONWhenEmptyNodeCreated() throws Exception
122 {
123 Response response = service.createNode( null );
124
125 assertEquals( 201, response.getStatus() );
126 assertNotNull( response.getMetadata().get( "Location" ).get( 0 ) );
127 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
128 String json = entityAsString( response );
129
130 Map<String, Object> map = JsonHelper.jsonToMap( json );
131
132 assertNotNull( map );
133
134 assertTrue( map.containsKey( "self" ) );
135 }
136
137 @Test
138 public void shouldRespondWith201LocationHeaderAndNodeRepresentationInJSONWhenPopulatedNodeCreated() throws Exception
139 {
140 Response response = service.createNode( "{\"foo\" : \"bar\"}" );
141
142 assertEquals( 201, response.getStatus() );
143 assertNotNull( response.getMetadata().get( "Location" ).get( 0 ) );
144 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
145 String json = entityAsString( response );
146
147 Map<String, Object> map = JsonHelper.jsonToMap( json );
148
149 assertNotNull( map );
150
151 assertTrue( map.containsKey( "self" ) );
152
153 @SuppressWarnings("unchecked")
154 Map<String, Object> data = (Map<String, Object>) map.get( "data" );
155
156 assertEquals( "bar", data.get( "foo" ) );
157 }
158
159 @Test
160 @SuppressWarnings("unchecked")
161 public void shouldRespondWith201LocationHeaderAndNodeRepresentationInJSONWhenPopulatedNodeCreatedWithArrays() throws Exception
162 {
163 Response response = service.createNode( "{\"foo\" : [\"bar\", \"baz\"] }" );
164
165 assertEquals( 201, response.getStatus() );
166 assertNotNull( response.getMetadata().get( "Location" ).get( 0 ) );
167 String json = entityAsString( response );
168
169 Map<String, Object> map = JsonHelper.jsonToMap( json );
170
171 assertNotNull( map );
172
173 Map<String, Object> data = (Map<String, Object>) map.get( "data" );
174
175 List<String> foo = (List<String>) data.get( "foo" );
176 assertNotNull( foo );
177 assertEquals( 2, foo.size() );
178 }
179
180 @Test
181 public void shouldRespondWith400WhenNodeCreatedWithUnsupportedPropertyData() throws DatabaseBlockedException
182 {
183 Response response = service.createNode( "{\"foo\" : {\"bar\" : \"baz\"}}" );
184
185 assertEquals( 400, response.getStatus() );
186 }
187
188 @Test
189 public void shouldRespondWith400WhenNodeCreatedWithInvalidJSON() throws DatabaseBlockedException
190 {
191 Response response = service.createNode( "this:::isNot::JSON}" );
192
193 assertEquals( 400, response.getStatus() );
194 }
195
196 @Test
197 public void shouldRespondWith200AndNodeRepresentationInJSONWhenNodeRequested() throws Exception
198 {
199 Response response = service.getNode( helper.createNode() );
200 assertEquals( 200, response.getStatus() );
201 String json = entityAsString( response );
202 Map<String, Object> map = JsonHelper.jsonToMap( json );
203 assertNotNull( map );
204 assertTrue( map.containsKey( "self" ) );
205 }
206
207 @Test
208 public void shouldRespondWith404WhenRequestedNodeDoesNotExist() throws Exception
209 {
210 Response response = service.getNode( 9000000000000L );
211 assertEquals( 404, response.getStatus() );
212 }
213
214 @Test
215 public void shouldRespondWith204AfterSettingPropertiesOnExistingNode() throws Exception
216 {
217 Response response = service.setAllNodeProperties( helper.createNode(),
218 "{\"foo\" : \"bar\", \"a-boolean\": true, \"boolean-array\": [true, false, false]}" );
219 assertEquals( 204, response.getStatus() );
220 }
221
222 @Test
223 public void shouldRespondWith404WhenSettingPropertiesOnNodeThatDoesNotExist() throws Exception
224 {
225 Response response = service.setAllNodeProperties( 9000000000000L, "{\"foo\" : \"bar\"}" );
226 assertEquals( 404, response.getStatus() );
227 }
228
229 @Test
230 public void shouldRespondWith400WhenTransferringCorruptJsonPayload() throws Exception
231 {
232 Response response = service.setAllNodeProperties( helper.createNode(),
233 "{\"foo\" : bad-json-here \"bar\"}" );
234 assertEquals( 400, response.getStatus() );
235 }
236
237 @Test
238 public void shouldRespondWith400WhenTransferringIncompatibleJsonPayload() throws Exception
239 {
240 Response response = service.setAllNodeProperties( helper.createNode(),
241 "{\"foo\" : {\"bar\" : \"baz\"}}" );
242 assertEquals( 400, response.getStatus() );
243 }
244
245 @Test
246 public void shouldRespondWith200ForGetNodeProperties() throws Exception
247 {
248 long nodeId = helper.createNode();
249 Map<String, Object> properties = new HashMap<String, Object>();
250 properties.put( "foo", "bar" );
251 helper.setNodeProperties( nodeId, properties );
252 Response response = service.getAllNodeProperties( nodeId );
253 assertEquals( 200, response.getStatus() );
254 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
255 }
256
257 @Test
258 public void shouldRespondWith204ForGetNoNodeProperties() throws Exception
259 {
260 long nodeId = helper.createNode();
261 Response response = service.getAllNodeProperties( nodeId );
262 assertEquals( 204, response.getStatus() );
263 }
264
265 @Test
266 public void shouldGetPropertiesForGetNodeProperties() throws Exception
267 {
268 long nodeId = helper.createNode();
269 Map<String, Object> properties = new HashMap<String, Object>();
270 properties.put( "foo", "bar" );
271 properties.put( "number", 15 );
272 properties.put( "double", 15.7 );
273 helper.setNodeProperties( nodeId, properties );
274 Response response = service.getAllNodeProperties( nodeId );
275 String jsonBody = entityAsString( response );
276 Map<String, Object> readProperties = JsonHelper.jsonToMap( jsonBody );
277 assertEquals( properties, readProperties );
278 }
279
280 @Test
281 public void shouldRespondWith204OnSuccessfulDelete() throws DatabaseBlockedException
282 {
283 long id = helper.createNode();
284
285 Response response = service.deleteNode( id );
286
287 assertEquals( 204, response.getStatus() );
288 }
289
290 @Test
291 public void shouldRespondWith409IfNodeCannotBeDeleted() throws DatabaseBlockedException
292 {
293 long id = helper.createNode();
294 helper.createRelationship( "LOVES", id, helper.createNode() );
295
296 Response response = service.deleteNode( id );
297
298 assertEquals( 409, response.getStatus() );
299 }
300
301 @Test
302 public void shouldRespondWith404IfNodeToBeDeletedDoesNotExist() throws DatabaseBlockedException
303 {
304 long nonExistentId = 999999;
305 Response response = service.deleteNode( nonExistentId );
306
307 assertEquals( 404, response.getStatus() );
308 }
309
310 @Test
311 public void shouldRespondWith204ForSetNodeProperty() throws DatabaseBlockedException
312 {
313 long nodeId = helper.createNode();
314 String key = "foo";
315 String json = "\"bar\"";
316 Response response = service.setNodeProperty( nodeId, key, json );
317 assertEquals( 204, response.getStatus() );
318 }
319
320 @Test
321 public void shouldSetRightValueForSetNodeProperty() throws DatabaseBlockedException
322 {
323 long nodeId = helper.createNode();
324 String key = "foo";
325 String value = "bar";
326 String json = "\"" + value + "\"";
327 service.setNodeProperty( nodeId, key, json );
328 Map<String, Object> readProperties = helper.getNodeProperties( nodeId );
329 assertEquals( Collections.singletonMap( key, value ), readProperties );
330 }
331
332 @Test
333 public void shouldRespondWith404ForSetNodePropertyOnNonExistingNode() throws DatabaseBlockedException
334 {
335 String key = "foo";
336 String json = "\"bar\"";
337 Response response = service.setNodeProperty( 999999, key, json );
338 assertEquals( 404, response.getStatus() );
339 }
340
341 @Test
342 public void shouldRespondWith400ForSetNodePropertyWithInvalidJson() throws DatabaseBlockedException
343 {
344 String key = "foo";
345 String json = "{invalid json";
346 Response response = service.setNodeProperty( 999999, key, json );
347 assertEquals( 400, response.getStatus() );
348 }
349
350 @Test
351 public void shouldRespondWith404ForGetNonExistentNodeProperty() throws DatabaseBlockedException
352 {
353 long nodeId = helper.createNode();
354 Response response = service.getNodeProperty( nodeId, "foo" );
355 assertEquals( 404, response.getStatus() );
356 }
357
358 @Test
359 public void shouldRespondWith404ForGetNodePropertyOnNonExistentNode() throws DatabaseBlockedException
360 {
361 long nodeId = 999999;
362 Response response = service.getNodeProperty( nodeId, "foo" );
363 assertEquals( 404, response.getStatus() );
364 }
365
366 @Test
367 public void shouldRespondWith200ForGetNodeProperty() throws DatabaseBlockedException
368 {
369 long nodeId = helper.createNode();
370 String key = "foo";
371 Object value = "bar";
372 helper.setNodeProperties( nodeId, Collections.singletonMap( key, value ) );
373 Response response = service.getNodeProperty( nodeId, "foo" );
374 assertEquals( 200, response.getStatus() );
375 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
376 }
377
378 @Test
379 public void shouldReturnCorrectValueForGetNodeProperty() throws Exception
380 {
381 long nodeId = helper.createNode();
382 String key = "foo";
383 Object value = "bar";
384 helper.setNodeProperties( nodeId, Collections.singletonMap( key, value ) );
385 Response response = service.getNodeProperty( nodeId, "foo" );
386 assertEquals( JsonHelper.createJsonFrom( value ), entityAsString( response ) );
387 }
388
389 @Test
390 public void shouldRespondWith201AndLocationWhenRelationshipIsCreatedWithoutProperties() throws DatabaseBlockedException
391 {
392 long startNode = helper.createNode();
393 long endNode = helper.createNode();
394 Response response = service.createRelationship( startNode, "{\"to\" : \"" + BASE_URI
395 + endNode
396 + "\", \"type\" : \"LOVES\"}" );
397 assertEquals( 201, response.getStatus() );
398 assertNotNull( response.getMetadata().get( "Location" ).get( 0 ) );
399 }
400
401 @Test
402 public void shouldRespondWith201AndLocationWhenRelationshipIsCreatedWithProperties() throws DatabaseBlockedException
403 {
404 long startNode = helper.createNode();
405 long endNode = helper.createNode();
406 Response response = service.createRelationship( startNode,
407 "{\"to\" : \"" + BASE_URI + endNode
408 + "\", \"type\" : \"LOVES\", \"properties\" : {\"foo\" : \"bar\"}}" );
409 assertEquals( 201, response.getStatus() );
410 assertNotNull( response.getMetadata().get( "Location" ).get( 0 ) );
411 }
412
413 @Test
414 public void shouldReturnRelationshipRepresentationWhenCreatingRelationship() throws Exception
415 {
416 long startNode = helper.createNode();
417 long endNode = helper.createNode();
418 Response response = service.createRelationship( startNode,
419 "{\"to\" : \"" + BASE_URI + endNode
420 + "\", \"type\" : \"LOVES\", \"data\" : {\"foo\" : \"bar\"}}" );
421 Map<String, Object> map = JsonHelper.jsonToMap( entityAsString( response ) );
422 assertNotNull( map );
423 assertTrue( map.containsKey( "self" ) );
424 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
425
426 @SuppressWarnings("unchecked")
427 Map<String, Object> data = (Map<String, Object>) map.get( "data" );
428
429 assertEquals( "bar", data.get( "foo" ) );
430 }
431
432 @Test
433 public void shouldRespondWith404WhenTryingToCreateRelationshipFromNonExistentNode() throws DatabaseBlockedException
434 {
435 long nodeId = helper.createNode();
436 Response response = service.createRelationship( nodeId * 1000,
437 "{\"to\" : \"" + BASE_URI + nodeId
438 + "\", \"type\" : \"LOVES\"}" );
439 assertEquals( 404, response.getStatus() );
440 }
441
442 @Test
443 public void shouldRespondWith400WhenTryingToCreateRelationshipToNonExistentNode() throws DatabaseBlockedException
444 {
445 long nodeId = helper.createNode();
446 Response response = service.createRelationship( nodeId, "{\"to\" : \"" + BASE_URI
447 + (nodeId * 1000)
448 + "\", \"type\" : \"LOVES\"}" );
449 assertEquals( 400, response.getStatus() );
450 }
451
452 @Test
453 public void shouldRespondWith400WhenTryingToCreateRelationshipToStartNode() throws DatabaseBlockedException
454 {
455 long nodeId = helper.createNode();
456 Response response = service.createRelationship( nodeId, "{\"to\" : \"" + BASE_URI + nodeId
457 + "\", \"type\" : \"LOVES\"}" );
458 assertEquals( 400, response.getStatus() );
459 }
460
461 @Test
462 public void shouldRespondWith400WhenTryingToCreateRelationshipWithBadJson() throws DatabaseBlockedException
463 {
464 long startNode = helper.createNode();
465 long endNode = helper.createNode();
466 Response response = service.createRelationship( startNode,
467 "{\"to\" : \"" + BASE_URI + endNode
468 + "\", \"type\" ***and junk*** : \"LOVES\"}" );
469 assertEquals( 400, response.getStatus() );
470 }
471
472 @Test
473 public void shouldRespondWith400WhenTryingToCreateRelationshipWithUnsupportedProperties() throws DatabaseBlockedException
474 {
475 long startNode = helper.createNode();
476 long endNode = helper.createNode();
477 Response response = service.createRelationship( startNode,
478 "{\"to\" : \"" + BASE_URI + endNode
479 + "\", \"type\" : \"LOVES\", \"data\" : {\"foo\" : {\"bar\" : \"baz\"}}}" );
480 assertEquals( 400, response.getStatus() );
481 }
482
483 @Test
484 public void shouldRespondWith204ForRemoveNodeProperties() throws DatabaseBlockedException
485 {
486 long nodeId = helper.createNode();
487 Map<String, Object> properties = new HashMap<String, Object>();
488 properties.put( "foo", "bar" );
489 properties.put( "number", 15 );
490 helper.setNodeProperties( nodeId, properties );
491 Response response = service.deleteAllNodeProperties( nodeId );
492 assertEquals( 204, response.getStatus() );
493 }
494
495 @Test
496 public void shouldBeAbleToRemoveNodeProperties() throws DatabaseBlockedException
497 {
498 long nodeId = helper.createNode();
499 Map<String, Object> properties = new HashMap<String, Object>();
500 properties.put( "foo", "bar" );
501 properties.put( "number", 15 );
502 helper.setNodeProperties( nodeId, properties );
503 service.deleteAllNodeProperties( nodeId );
504 assertEquals( true, helper.getNodeProperties( nodeId ).isEmpty() );
505 }
506
507 @Test
508 public void shouldRespondWith404ForRemoveNodePropertiesForNonExistingNode() throws DatabaseBlockedException
509 {
510 long nodeId = 999999;
511 Response response = service.deleteAllNodeProperties( nodeId );
512 assertEquals( 404, response.getStatus() );
513 }
514
515 @Test
516 public void shouldBeAbleToRemoveNodeProperty() throws DatabaseBlockedException
517 {
518 long nodeId = helper.createNode();
519 Map<String, Object> properties = new HashMap<String, Object>();
520 properties.put( "foo", "bar" );
521 properties.put( "number", 15 );
522 helper.setNodeProperties( nodeId, properties );
523 service.deleteNodeProperty( nodeId, "foo" );
524 assertEquals( Collections.singletonMap( "number", (Object) new Integer( 15 ) ), helper.getNodeProperties( nodeId ) );
525 }
526
527 @Test
528 public void shouldGet404WhenRemovingNonExistingProperty() throws DatabaseBlockedException
529 {
530 long nodeId = helper.createNode();
531 Map<String, Object> properties = new HashMap<String, Object>();
532 properties.put( "foo", "bar" );
533 properties.put( "number", 15 );
534 helper.setNodeProperties( nodeId, properties );
535 Response response = service.deleteNodeProperty( nodeId, "baz" );
536 assertEquals( 404, response.getStatus() );
537 }
538
539 @Test
540 public void shouldGet404WhenRemovingPropertyFromNonExistingNode() throws DatabaseBlockedException
541 {
542 long nodeId = 999999;
543 Response response = service.deleteNodeProperty( nodeId, "foo" );
544 assertEquals( 404, response.getStatus() );
545 }
546
547 @Test
548 public void shouldGet200WhenRetrievingARelationshipFromANode() throws DatabaseBlockedException
549 {
550 long relationshipId = helper.createRelationship( "BEATS" );
551 Response response = service.getRelationship( relationshipId );
552 assertEquals( 200, response.getStatus() );
553 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
554 }
555
556 @Test
557 public void shouldGet404WhenRetrievingRelationshipThatDoesNotExist() throws DatabaseBlockedException
558 {
559 Response response = service.getRelationship( 999999 );
560 assertEquals( 404, response.getStatus() );
561 }
562
563 @Test
564 public void shouldRespondWith200AndDataForGetRelationshipProperties() throws Exception
565 {
566 long relationshipId = helper.createRelationship( "knows" );
567 Map<String, Object> properties = new HashMap<String, Object>();
568 properties.put( "foo", "bar" );
569 helper.setRelationshipProperties( relationshipId, properties );
570 Response response = service.getAllRelationshipProperties( relationshipId );
571 assertEquals( 200, response.getStatus() );
572 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
573 Map<String, Object> readProperties = JsonHelper.jsonToMap( entityAsString( response ) );
574 assertEquals( properties, readProperties );
575 }
576
577 @Test
578 public void shouldRespondWith204ForGetNoRelationshipProperties() throws DatabaseBlockedException
579 {
580 long relationshipId = helper.createRelationship( "knows" );
581 Response response = service.getAllRelationshipProperties( relationshipId );
582 assertEquals( 204, response.getStatus() );
583 }
584
585 @Test
586 public void shouldGet200WhenSuccessfullyRetrievedPropertyOnRelationship() throws DatabaseBlockedException, PropertyValueException
587 {
588
589 long relationshipId = helper.createRelationship( "knows" );
590 Map<String, Object> properties = new HashMap<String, Object>();
591 properties.put( "some-key", "some-value" );
592 helper.setRelationshipProperties( relationshipId, properties );
593
594 Response response = service.getRelationshipProperty( relationshipId, "some-key" );
595
596 assertEquals( 200, response.getStatus() );
597 assertEquals( "some-value", JsonHelper.jsonToSingleValue( entityAsString( response ) ) );
598 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
599 }
600
601 @Test
602 public void shouldGet404WhenCannotResolveAPropertyOnRelationship() throws DatabaseBlockedException
603 {
604 long relationshipId = helper.createRelationship( "knows" );
605 Response response = service.getRelationshipProperty( relationshipId, "some-key" );
606 assertEquals( 404, response.getStatus() );
607 }
608
609 @Test
610 public void shouldGet204WhenRemovingARelationship() throws DatabaseBlockedException
611 {
612 long relationshipId = helper.createRelationship( "KNOWS" );
613
614 Response response = service.deleteRelationship( relationshipId );
615 assertEquals( 204, response.getStatus() );
616 }
617
618 @Test
619 public void shouldGet404WhenRemovingNonExistentRelationship() throws DatabaseBlockedException
620 {
621 long relationshipId = helper.createRelationship( "KNOWS" );
622
623 Response response = service.deleteRelationship( relationshipId + 1 * 1000 );
624 assertEquals( 404, response.getStatus() );
625 }
626
627 @Test
628 public void shouldRespondWith200AndListOfRelationshipRepresentationsWhenGettingRelationshipsForANode() throws DatabaseBlockedException, JsonParseException
629 {
630 long nodeId = helper.createNode();
631 helper.createRelationship( "LIKES", nodeId, helper.createNode() );
632 helper.createRelationship( "LIKES", helper.createNode(), nodeId );
633 helper.createRelationship( "HATES", nodeId, helper.createNode() );
634
635 Response response = service.getNodeRelationships( nodeId, RelationshipDirection.all,
636 new AmpersandSeparatedCollection( "" ) );
637 assertEquals( 200, response.getStatus() );
638 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
639 verifyRelReps( 3, entityAsString( response ) );
640
641 response = service.getNodeRelationships( nodeId, RelationshipDirection.in,
642 new AmpersandSeparatedCollection( "" ) );
643 assertEquals( 200, response.getStatus() );
644 verifyRelReps( 1, entityAsString( response ) );
645
646 response = service.getNodeRelationships( nodeId, RelationshipDirection.out,
647 new AmpersandSeparatedCollection( "" ) );
648 assertEquals( 200, response.getStatus() );
649 verifyRelReps( 2, entityAsString( response ) );
650
651 response = service.getNodeRelationships( nodeId, RelationshipDirection.out,
652 new AmpersandSeparatedCollection( "LIKES&HATES" ) );
653 assertEquals( 200, response.getStatus() );
654 verifyRelReps( 2, entityAsString( response ) );
655
656 response = service.getNodeRelationships( nodeId, RelationshipDirection.all,
657 new AmpersandSeparatedCollection( "LIKES" ) );
658 assertEquals( 200, response.getStatus() );
659 verifyRelReps( 2, entityAsString( response ) );
660 }
661
662 @Test
663 public void shouldNotReturnDuplicatesIfSameTypeSpecifiedMoreThanOnce() throws DatabaseBlockedException, PropertyValueException
664 {
665 long nodeId = helper.createNode();
666 helper.createRelationship( "LIKES", nodeId, helper.createNode() );
667 Response response = service.getNodeRelationships( nodeId, RelationshipDirection.all,
668 new AmpersandSeparatedCollection( "LIKES&LIKES" ) );
669 Collection<?> array = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
670 assertEquals( 1, array.size() );
671 }
672
673 private void verifyRelReps( int expectedSize, String entity ) throws JsonParseException
674 {
675 List<Map<String, Object>> relreps = JsonHelper.jsonToList( entity );
676 assertEquals( expectedSize, relreps.size() );
677 for ( Map<String, Object> relrep : relreps )
678 {
679 RelationshipRepresentationTest.verifySerialisation( relrep );
680 }
681 }
682
683 @Test
684 public void shouldRespondWith200AndEmptyListOfRelationshipRepresentationsWhenGettingRelationshipsForANodeWithoutRelationships()
685 throws DatabaseBlockedException, JsonParseException
686 {
687 long nodeId = helper.createNode();
688
689 Response response = service.getNodeRelationships( nodeId, RelationshipDirection.all,
690 new AmpersandSeparatedCollection( "" ) );
691 assertEquals( 200, response.getStatus() );
692 verifyRelReps( 0, entityAsString( response ) );
693 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
694 }
695
696 @Test
697 public void shouldRespondWith404WhenGettingIncomingRelationshipsForNonExistingNode() throws DatabaseBlockedException
698 {
699 Response response = service.getNodeRelationships( 999999, RelationshipDirection.all,
700 new AmpersandSeparatedCollection( "" ) );
701 assertEquals( 404, response.getStatus() );
702 }
703
704 @Test
705 public void shouldRespondWith204AndSetCorrectDataWhenSettingRelationshipProperties() throws DatabaseBlockedException
706 {
707 long relationshipId = helper.createRelationship( "KNOWS" );
708 String json = "{\"name\": \"Mattias\", \"age\": 30}";
709 Response response = service.setAllRelationshipProperties( relationshipId, json );
710 assertEquals( 204, response.getStatus() );
711 Map<String, Object> setProperties = new HashMap<String, Object>();
712 setProperties.put( "name", "Mattias" );
713 setProperties.put( "age", 30 );
714 assertEquals( setProperties, helper.getRelationshipProperties( relationshipId ) );
715 }
716
717 @Test
718 public void shouldRespondWith400WhenSettingRelationshipPropertiesWithBadJson() throws DatabaseBlockedException
719 {
720 long relationshipId = helper.createRelationship( "KNOWS" );
721 String json = "{\"name: \"Mattias\", \"age\": 30}";
722 Response response = service.setAllRelationshipProperties( relationshipId, json );
723 assertEquals( 400, response.getStatus() );
724 }
725
726 @Test
727 public void shouldRespondWith404WhenSettingRelationshipPropertiesOnNonExistingRelationship() throws DatabaseBlockedException
728 {
729 long relationshipId = 99999999;
730 String json = "{\"name\": \"Mattias\", \"age\": 30}";
731 Response response = service.setAllRelationshipProperties( relationshipId, json );
732 assertEquals( 404, response.getStatus() );
733 }
734
735 @Test
736 public void shouldRespondWith204AndSetCorrectDataWhenSettingRelationshipProperty() throws DatabaseBlockedException
737 {
738 long relationshipId = helper.createRelationship( "KNOWS" );
739 String key = "name";
740 Object value = "Mattias";
741 String json = "\"" + value + "\"";
742 Response response = service.setRelationshipProperty( relationshipId, key, json );
743 assertEquals( 204, response.getStatus() );
744 assertEquals( value, helper.getRelationshipProperties( relationshipId ).get( "name" ) );
745 }
746
747 @Test
748 public void shouldRespondWith400WhenSettingRelationshipPropertyWithBadJson() throws DatabaseBlockedException
749 {
750 long relationshipId = helper.createRelationship( "KNOWS" );
751 String json = "}Mattias";
752 Response response = service.setRelationshipProperty( relationshipId, "name", json );
753 assertEquals( 400, response.getStatus() );
754 }
755
756 @Test
757 public void shouldRespondWith404WhenSettingRelationshipPropertyOnNonExistingRelationship() throws DatabaseBlockedException
758 {
759 long relationshipId = 99999999;
760 String json = "\"Mattias\"";
761 Response response = service.setRelationshipProperty( relationshipId, "name", json );
762 assertEquals( 404, response.getStatus() );
763 }
764
765 @Test
766 public void shouldRespondWith204WhenSuccessfullyRemovedRelationshipProperties() throws DatabaseBlockedException
767 {
768 long relationshipId = helper.createRelationship( "KNOWS" );
769 helper.setRelationshipProperties( relationshipId, Collections.singletonMap( "foo", (Object) "bar" ) );
770
771 Response response = service.deleteAllRelationshipProperties( relationshipId );
772 assertEquals( 204, response.getStatus() );
773 }
774
775 @Test
776 public void shouldRespondWith204WhenSuccessfullyRemovedRelationshipPropertiesWhichAreEmpty() throws DatabaseBlockedException
777 {
778 long relationshipId = helper.createRelationship( "KNOWS" );
779
780 Response response = service.deleteAllRelationshipProperties( relationshipId );
781 assertEquals( 204, response.getStatus() );
782 }
783
784 @Test
785 public void shouldRespondWith404WhenNoRelationshipFromWhichToRemoveProperties() throws DatabaseBlockedException
786 {
787 long relationshipId = helper.createRelationship( "KNOWS" );
788
789 Response response = service.deleteAllRelationshipProperties( relationshipId + 1 * 1000 );
790 assertEquals( 404, response.getStatus() );
791 }
792
793 @Test
794 public void shouldRespondWith204WhenRemovingRelationshipProperty() throws DatabaseBlockedException
795 {
796 long relationshipId = helper.createRelationship( "KNOWS" );
797 helper.setRelationshipProperties( relationshipId, Collections.singletonMap( "foo", (Object) "bar" ) );
798
799 Response response = service.deleteRelationshipProperty( relationshipId, "foo" );
800
801 assertEquals( 204, response.getStatus() );
802 }
803
804 @Test
805 public void shouldRespondWith404WhenRemovingRelationshipPropertyWhichDoesNotExist() throws DatabaseBlockedException
806 {
807 long relationshipId = helper.createRelationship( "KNOWS" );
808 Response response = service.deleteRelationshipProperty( relationshipId, "foo" );
809 assertEquals( 404, response.getStatus() );
810 }
811
812 @Test
813 public void shouldRespondWith404WhenNoRelationshipFromWhichToRemoveProperty() throws DatabaseBlockedException
814 {
815 long relationshipId = helper.createRelationship( "KNOWS" );
816
817 Response response = service.deleteRelationshipProperty( relationshipId * 1000, "some-key" );
818 assertEquals( 404, response.getStatus() );
819 }
820
821 @Test
822 public void shouldRespondWithNoContentNoNodeIndexesExist()
823 {
824 Response response = service.getNodeIndexRoot();
825 assertEquals( 204, response.getStatus() );
826 }
827
828 @Test
829 public void shouldRespondWithAvailableIndexNodeRoots() throws BadInputException
830 {
831 String indexName = "someNodes";
832 helper.createNodeIndex( indexName );
833 Response response = service.getNodeIndexRoot();
834 assertEquals( 200, response.getStatus() );
835
836 Map<String, Object> resultAsMap = output.getResultAsMap();
837 assertThat( resultAsMap.size(), is( 1 ) );
838 assertThat( resultAsMap, hasKey( indexName ) );
839 }
840
841 @Test
842 public void shouldRespondWithNoContentWhenNoRelationshipIndexesExist()
843 {
844 Response response = service.getRelationshipIndexRoot();
845 assertEquals( 204, response.getStatus() );
846 }
847
848 @Test
849 public void shouldRespondWithAvailableIndexRelationshipRoots() throws BadInputException
850 {
851 String indexName = "someRelationships";
852 helper.createRelationshipIndex( indexName );
853 Response response = service.getRelationshipIndexRoot();
854 assertEquals( 200, response.getStatus() );
855 Map<String, Object> resultAsMap = output.getResultAsMap();
856 assertThat( resultAsMap.size(), is( 1 ) );
857 assertThat( resultAsMap, hasKey( indexName ) );
858 }
859
860 @Test
861 public void shouldBeAbleToGetRoot() throws JsonParseException
862 {
863 Response response = service.getRoot();
864 assertEquals( 200, response.getStatus() );
865 String entity = entityAsString( response );
866 Map<String, Object> map = JsonHelper.jsonToMap( entity );
867 assertNotNull( map.get( "node" ) );
868 assertNotNull( map.get( "reference_node" ) );
869 assertNotNull( map.get( "node_index" ) );
870 assertNotNull( map.get( "extensions_info" ) );
871 assertNotNull( map.get( "relationship_index" ) );
872 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
873 }
874
875 @Test
876 public void shouldBeAbleToGetRootWhenNoReferenceNodePresent() throws JsonParseException
877 {
878 helper.deleteNode( 0l );
879
880 Response response = service.getRoot();
881 assertEquals( 200, response.getStatus() );
882 String entity = entityAsString( response );
883 Map<String, Object> map = JsonHelper.jsonToMap( entity );
884 assertNotNull( map.get( "node" ) );
885
886 assertNotNull( map.get( "node_index" ) );
887 assertNotNull( map.get( "extensions_info" ) );
888 assertNotNull( map.get( "relationship_index" ) );
889
890 assertNull( map.get( "reference_node" ) );
891
892 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
893 }
894
895 @Test
896 public void shouldBeAbleToIndexNode() throws DatabaseBlockedException, JsonParseException
897 {
898 Response response = service.createNode( null );
899 URI nodeUri = (URI) response.getMetadata().getFirst( "Location" );
900
901 String key = "key";
902 String value = "value";
903 response = service.addToNodeIndex( "node", key, value,
904 JsonHelper.createJsonFrom( nodeUri.toString() ) );
905 assertEquals( 201, response.getStatus() );
906 assertNotNull( response.getMetadata().getFirst( "Location" ) );
907 }
908
909 @Test
910 public void shouldBeAbleToGetNodeRepresentationFromIndexUri() throws DatabaseBlockedException, JsonParseException
911 {
912 String key = "key_get_noderep";
913 String value = "value";
914 long nodeId = helper.createNode();
915 String indexName = "all-the-best-nodes";
916 helper.addNodeToIndex( indexName, key, value, nodeId );
917 Response response = service.getNodeFromIndexUri( indexName, key, value, nodeId );
918 assertEquals( 200, response.getStatus() );
919 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
920 assertNull( response.getMetadata().get( "Location" ) );
921 Map<String, Object> map = JsonHelper.jsonToMap( entityAsString( response ) );
922 assertNotNull( map );
923 assertTrue( map.containsKey( "self" ) );
924 }
925
926 @Test
927 public void shouldBeAbleToGetRelationshipRepresentationFromIndexUri() throws DatabaseBlockedException, JsonParseException
928 {
929 String key = "key_get_noderep";
930 String value = "value";
931 long startNodeId = helper.createNode();
932 long endNodeId = helper.createNode();
933 String relationshipType = "knows";
934 long relationshipId = helper.createRelationship( relationshipType, startNodeId, endNodeId );
935
936 String indexName = "all-the-best-relationships";
937 helper.addRelationshipToIndex( indexName, key, value, relationshipId );
938 Response response = service.getRelationshipFromIndexUri( indexName, key, value, relationshipId );
939 assertEquals( 200, response.getStatus() );
940 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
941 assertNull( response.getMetadata().get( "Location" ) );
942 Map<String, Object> map = JsonHelper.jsonToMap( entityAsString( response ) );
943 assertNotNull( map );
944 assertTrue( map.containsKey( "self" ) );
945 }
946
947
948 @Test
949 public void shouldBeAbleToGetListOfNodeRepresentationsFromIndexLookup() throws DatabaseBlockedException, PropertyValueException, URISyntaxException
950 {
951 RestfulModelHelper.DomainModel matrixers = RestfulModelHelper.generateMatrix( service );
952
953 Map.Entry<String, String> indexedKeyValue = matrixers.indexedNodeKeyValues.entrySet().iterator().next();
954 Response response = service.getIndexedNodes( matrixers.nodeIndexName, indexedKeyValue.getKey(), indexedKeyValue.getValue() );
955 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
956 Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
957 int counter = 0;
958 for ( Object item : items )
959 {
960 Map<?, ?> map = (Map<?, ?>) item;
961 Map<?, ?> properties = (Map<?, ?>) map.get( "data" );
962 assertNotNull( map.get( "self" ) );
963 String indexedUri = (String) map.get( "indexed" );
964 assertEquals( matrixers.indexedNodeUriToEntityMap.get( new URI(indexedUri) ).properties.get("name"), properties.get( "name" ) );
965 counter++;
966 }
967 assertEquals( 2, counter );
968 }
969
970 @Test
971 public void shouldBeAbleToGetListOfNodeRepresentationsFromIndexQuery() throws DatabaseBlockedException, PropertyValueException, URISyntaxException
972 {
973 RestfulModelHelper.DomainModel matrixers = RestfulModelHelper.generateMatrix( service );
974
975 Map.Entry<String, String> indexedKeyValue = matrixers.indexedNodeKeyValues.entrySet().iterator().next();
976
977 Response response = service.getIndexedNodesByQuery( matrixers.nodeIndexName, indexedKeyValue.getKey(), indexedKeyValue.getValue().substring( 0, 1 ) + "*" );
978 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
979 Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
980 int counter = 0;
981 for ( Object item : items )
982 {
983 Map<?, ?> map = (Map<?, ?>) item;
984 Map<?, ?> properties = (Map<?, ?>) map.get( "data" );
985 String indexedUri = (String) map.get( "indexed" );
986 assertNull(indexedUri);
987 String selfUri = (String) map.get("self");
988 assertNotNull( selfUri );
989 assertEquals( matrixers.nodeUriToEntityMap.get( new URI(selfUri) ).properties.get("name"), properties.get( "name" ) );
990 counter++;
991 }
992 assertThat( counter, is( greaterThanOrEqualTo(2)) );
993 }
994
995
996 @Test
997 public void shouldBeAbleToGetListOfRelationshipRepresentationsFromIndexLookup() throws DatabaseBlockedException, PropertyValueException
998 {
999 String key = "key_get";
1000 String value = "value";
1001
1002 long startNodeId = helper.createNode();
1003 long endNodeId = helper.createNode();
1004
1005 String relationshipType1 = "KNOWS";
1006 long relationshipId1 = helper.createRelationship( relationshipType1, startNodeId, endNodeId );
1007 String relationshipType2 = "PLAYS-NICE-WITH";
1008 long relationshipId2 = helper.createRelationship( relationshipType2, startNodeId, endNodeId );
1009
1010 String indexName = "matrixal-relationships";
1011 helper.createRelationshipIndex( indexName );
1012 helper.addRelationshipToIndex( indexName, key, value, relationshipId1 );
1013 helper.addRelationshipToIndex( indexName, key, value, relationshipId2 );
1014
1015 Response response = service.getIndexedRelationships( indexName, key, value );
1016 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1017 Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
1018 int counter = 0;
1019 for ( Object item : items )
1020 {
1021 Map<?, ?> map = (Map<?, ?>) item;
1022 assertNotNull( map.get( "self" ) );
1023 String indexedUri = (String) map.get( "indexed" );
1024 assertThat( indexedUri, containsString( key ) );
1025 assertThat( indexedUri, containsString( value ) );
1026 assertTrue( indexedUri.endsWith( Long.toString( relationshipId1 ) ) ||
1027 indexedUri.endsWith( Long.toString( relationshipId2 ) ) );
1028 counter++;
1029 }
1030 assertEquals( 2, counter );
1031 }
1032
1033 @Test
1034 public void shouldBeAbleToGetListOfRelationshipRepresentationsFromIndexQuery() throws DatabaseBlockedException, PropertyValueException
1035 {
1036 String key = "key_get";
1037 String value = "value";
1038
1039 long startNodeId = helper.createNode();
1040 long endNodeId = helper.createNode();
1041
1042 String relationshipType1 = "KNOWS";
1043 long relationshipId1 = helper.createRelationship( relationshipType1, startNodeId, endNodeId );
1044 String relationshipType2 = "PLAYS-NICE-WITH";
1045 long relationshipId2 = helper.createRelationship( relationshipType2, startNodeId, endNodeId );
1046
1047 String indexName = "matrixal-relationships";
1048 helper.createRelationshipIndex( indexName );
1049 helper.addRelationshipToIndex( indexName, key, value, relationshipId1 );
1050 helper.addRelationshipToIndex( indexName, key, value, relationshipId2 );
1051
1052 Response response = service.getIndexedRelationshipsByQuery( indexName, key, value.substring( 0,1 ) + "*" );
1053 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1054 Collection<?> items = (Collection<?>) JsonHelper.jsonToSingleValue( entityAsString( response ) );
1055 int counter = 0;
1056 for ( Object item : items )
1057 {
1058 Map<?, ?> map = (Map<?, ?>) item;
1059 String indexedUri = (String) map.get( "indexed" );
1060 assertNull( indexedUri );
1061 String selfUri = (String) map.get("self");
1062 assertNotNull( selfUri );
1063 assertTrue( selfUri.endsWith( Long.toString( relationshipId1 ) ) ||
1064 selfUri.endsWith( Long.toString( relationshipId2 ) ) );
1065 counter++;
1066 }
1067 assertThat( counter, is(greaterThanOrEqualTo( 2 )));
1068 }
1069
1070 @Test
1071 public void shouldGet200AndEmptyListWhenNothingFoundInIndexLookup() throws DatabaseBlockedException, PropertyValueException
1072 {
1073 String indexName = "nothing-in-this-index";
1074 helper.createNodeIndex( indexName );
1075 Response response = service.getIndexedNodes( indexName, "fooo", "baaar" );
1076 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1077 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
1078 String entity = entityAsString( response );
1079 Object parsedJson = JsonHelper.jsonToSingleValue( entity );
1080 assertTrue( parsedJson instanceof Collection<?> );
1081 assertTrue( ((Collection<?>) parsedJson).isEmpty() );
1082 }
1083
1084 @Test
1085 public void shouldBeAbleToRemoveNodeFromIndex() throws DatabaseBlockedException
1086 {
1087 long nodeId = helper.createNode();
1088 String key = "key_remove";
1089 String value = "value";
1090 helper.addNodeToIndex( "node", key, value, nodeId );
1091 assertEquals( 1, helper.getIndexedNodes( "node", key, value ).size() );
1092 Response response = service.deleteFromNodeIndex( "node", key, value, nodeId );
1093 assertEquals( Status.NO_CONTENT.getStatusCode(), response.getStatus() );
1094 assertEquals( 0, helper.getIndexedNodes( "node", key, value ).size() );
1095 }
1096
1097 @Test
1098 public void shouldBeAbleToRemoveRelationshipFromIndex() throws DatabaseBlockedException
1099 {
1100 long startNodeId = helper.createNode();
1101 long endNodeId = helper.createNode();
1102 String relationshipType = "related-to";
1103 long relationshipId = helper.createRelationship( relationshipType, startNodeId, endNodeId );
1104 String key = "key_remove";
1105 String value = "value";
1106 String indexName = "relationships";
1107 helper.addRelationshipToIndex( indexName, key, value, relationshipId );
1108 assertEquals( 1, helper.getIndexedRelationships( indexName, key, value ).size() );
1109 Response response = service.deleteFromRelationshipIndex( indexName, key, value, relationshipId );
1110 assertEquals( Status.NO_CONTENT.getStatusCode(), response.getStatus() );
1111 assertEquals( 0, helper.getIndexedRelationships( indexName, key, value ).size() );
1112 }
1113
1114 @Test
1115 public void shouldGet404IfRemovingNonExistentNodeIndexing() throws DatabaseBlockedException
1116 {
1117 Response response = service.deleteFromNodeIndex( "nodes", "bogus", "bogus", 999999 );
1118 assertEquals( Status.NOT_FOUND.getStatusCode(), response.getStatus() );
1119 }
1120
1121 @Test
1122 public void shouldGet404IfRemovingNonExistentRelationshipIndexing() throws DatabaseBlockedException
1123 {
1124 Response response = service.deleteFromRelationshipIndex( "relationships", "bogus", "bogus", 999999 );
1125 assertEquals( Status.NOT_FOUND.getStatusCode(), response.getStatus() );
1126 }
1127
1128 @Test
1129 public void shouldGet404WhenTraversingFromNonExistentNode() throws DatabaseBlockedException
1130 {
1131 Response response = service.traverse( 9999999, TraverserReturnType.node, "{}" );
1132 assertEquals( Status.NOT_FOUND.getStatusCode(), response.getStatus() );
1133 }
1134
1135 @Test
1136 public void shouldGet200WhenNoHitsReturnedFromTraverse() throws DatabaseBlockedException, BadInputException
1137 {
1138 long startNode = helper.createNode();
1139 Response response = service.traverse( startNode, TraverserReturnType.node, "" );
1140 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1141
1142 List<Object> resultAsList = output.getResultAsList();
1143
1144 assertThat( resultAsList.size(), is( 0 ) );
1145 }
1146
1147 @Test
1148 public void shouldGetSomeHitsWhenTraversingWithDefaultDescription() throws DatabaseBlockedException
1149 {
1150 long startNode = helper.createNode();
1151 long child1_l1 = helper.createNode();
1152 helper.createRelationship( "knows", startNode, child1_l1 );
1153 long child2_l1 = helper.createNode();
1154 helper.createRelationship( "knows", startNode, child2_l1 );
1155 long child1_l2 = helper.createNode();
1156 helper.createRelationship( "knows", child2_l1, child1_l2 );
1157 Response response = service.traverse( startNode, TraverserReturnType.node, "" );
1158 String entity = entityAsString( response );
1159 assertTrue( entity.contains( "/node/" + child1_l1 ) );
1160 assertTrue( entity.contains( "/node/" + child2_l1 ) );
1161 assertFalse( entity.contains( "/node/" + child1_l2 ) );
1162 assertEquals( response.getMetadata().getFirst( HttpHeaders.CONTENT_ENCODING ), "UTF-8" );
1163 }
1164
1165 @Test
1166 public void shouldBeAbleToDescribeTraverser() throws DatabaseBlockedException
1167 {
1168 long startNode = helper.createNode( MapUtil.map( "name", "Mattias" ) );
1169 long node1 = helper.createNode( MapUtil.map( "name", "Emil" ) );
1170 long node2 = helper.createNode( MapUtil.map( "name", "Johan" ) );
1171 long node3 = helper.createNode( MapUtil.map( "name", "Tobias" ) );
1172 helper.createRelationship( "knows", startNode, node1 );
1173 helper.createRelationship( "knows", startNode, node2 );
1174 helper.createRelationship( "knows", node1, node3 );
1175 String description = "{" + "\"prune evaluator\":{\"language\":\"builtin\",\"name\":\"none\"},"
1176 + "\"return filter\":{\"language\":\"javascript\",\"body\":\"position.endNode().getProperty('name').toLowerCase().contains('t');\"},"
1177 + "\"order\":\"depth first\"," + "\"relationships\":{\"type\":\"knows\",\"direction\":\"all\"}" + "}";
1178 Response response = service.traverse( startNode, TraverserReturnType.node, description );
1179 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1180 String entity = entityAsString( response );
1181 assertTrue( entity.contains( "node/" + startNode ) );
1182 assertFalse( entity.contains( "node/" + node1 ) );
1183 assertFalse( entity.contains( "node/" + node2 ) );
1184 assertTrue( entity.contains( "node/" + node3 ) );
1185 }
1186
1187 @Test
1188 public void shouldBeAbleToGetOtherResultTypesWhenTraversing() throws DatabaseBlockedException
1189 {
1190 long startNode = helper.createNode( MapUtil.map( "name", "Mattias" ) );
1191 long node1 = helper.createNode( MapUtil.map( "name", "Emil" ) );
1192 long node2 = helper.createNode( MapUtil.map( "name", "Johan" ) );
1193 long node3 = helper.createNode( MapUtil.map( "name", "Tobias" ) );
1194 long rel1 = helper.createRelationship( "knows", startNode, node1 );
1195 long rel2 = helper.createRelationship( "knows", startNode, node2 );
1196 long rel3 = helper.createRelationship( "knows", node1, node3 );
1197
1198 Response response = service.traverse( startNode, TraverserReturnType.relationship, "" );
1199 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1200 String entity = entityAsString( response );
1201 assertTrue( entity.contains( "/relationship/" + rel1 ) );
1202 assertTrue( entity.contains( "/relationship/" + rel2 ) );
1203 assertFalse( entity.contains( "/relationship/" + rel3 ) );
1204
1205 response = service.traverse( startNode, TraverserReturnType.path, "" );
1206 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1207 entity = entityAsString( response );
1208 assertTrue( entity.contains( "nodes" ) );
1209 assertTrue( entity.contains( "relationships" ) );
1210 assertTrue( entity.contains( "length" ) );
1211
1212 response = service.traverse( startNode, TraverserReturnType.fullpath, "" );
1213 assertEquals( Status.OK.getStatusCode(), response.getStatus() );
1214 entity = entityAsString( response );
1215 assertTrue( entity.contains( "nodes" ) );
1216 assertTrue( entity.contains( "data" ) );
1217 assertTrue( entity.contains( "type" ) );
1218 assertTrue( entity.contains( "self" ) );
1219 assertTrue( entity.contains( "outgoing_relationships" ) );
1220 assertTrue( entity.contains( "incoming_relationships" ) );
1221 assertTrue( entity.contains( "relationships" ) );
1222 assertTrue( entity.contains( "length" ) );
1223 }
1224
1225 private static String markWithUnicodeMarker( String string )
1226 {
1227 return String.valueOf( (char) 0xfeff ) + string;
1228 }
1229
1230 @Test
1231 public void shouldBeAbleToFindSinglePathBetweenTwoNodes() throws Exception
1232 {
1233 long n1 = helper.createNode();
1234 long n2 = helper.createNode();
1235 helper.createRelationship( "knows", n1, n2 );
1236 Map<String, Object> config = MapUtil.map(
1237 "max depth", 3,
1238 "algorithm", "shortestPath",
1239 "to", Long.toString( n2 ),
1240 "relationships", MapUtil.map(
1241 "type", "knows",
1242 "direction", "out" ) );
1243
1244 String payload = JsonHelper.createJsonFrom( config );
1245
1246 Response response = service.singlePath( n1, payload );
1247 assertThat( response.getStatus(), is( 200 ) );
1248
1249 Map<String, Object> resultAsMap = output.getResultAsMap();
1250 assertThat( (Integer) resultAsMap.get( "length" ), is( 1 ) );
1251 }
1252
1253 @Test
1254 public void shouldBeAbleToFindSinglePathBetweenTwoNodesEvenWhenAskingForAllPaths() throws Exception
1255 {
1256 long n1 = helper.createNode();
1257 long n2 = helper.createNode();
1258 helper.createRelationship( "knows", n1, n2 );
1259 Map<String, Object> config = MapUtil.map(
1260 "max depth", 3,
1261 "algorithm", "shortestPath",
1262 "to", Long.toString( n2 ),
1263 "relationships", MapUtil.map(
1264 "type", "knows",
1265 "direction", "out" ) );
1266
1267 String payload = JsonHelper.createJsonFrom( config );
1268
1269 Response response = service.allPaths( n1, payload );
1270 assertThat( response.getStatus(), is( 200 ) );
1271
1272 List<Object> resultAsList = output.getResultAsList();
1273 assertThat( resultAsList.size(), is( 1 ) );
1274 }
1275
1276 @Test
1277 public void shouldBeAbleToParseJsonEvenWithUnicodeMarkerAtTheStart() throws DatabaseBlockedException, JsonParseException
1278 {
1279 Response response = service.createNode( markWithUnicodeMarker( "{\"name\":\"Mattias\"}" ) );
1280 assertEquals( Status.CREATED.getStatusCode(), response.getStatus() );
1281 String nodeLocation = response.getMetadata().getFirst( HttpHeaders.LOCATION ).toString();
1282
1283 long node = helper.createNode();
1284 assertEquals( Status.NO_CONTENT.getStatusCode(), service.setNodeProperty( node, "foo",
1285 markWithUnicodeMarker( "\"bar\"" ) ).getStatus() );
1286 assertEquals( Status.NO_CONTENT.getStatusCode(), service.setNodeProperty( node, "foo",
1287 markWithUnicodeMarker( "" + 10 ) ).getStatus() );
1288 assertEquals( Status.NO_CONTENT.getStatusCode(), service.setAllNodeProperties( node,
1289 markWithUnicodeMarker( "{\"name\":\"Something\",\"number\":10}" ) )
1290 .getStatus() );
1291
1292 assertEquals( Status.CREATED.getStatusCode(),
1293 service.createRelationship(
1294 node,
1295 markWithUnicodeMarker( "{\"to\":\"" + nodeLocation + "\",\"type\":\"knows\"}" ) ).getStatus() );
1296
1297 long relationship = helper.createRelationship( "knows" );
1298 assertEquals( Status.NO_CONTENT.getStatusCode(), service.setRelationshipProperty(
1299 relationship, "foo", markWithUnicodeMarker( "\"bar\"" ) ).getStatus() );
1300 assertEquals( Status.NO_CONTENT.getStatusCode(), service.setRelationshipProperty(
1301 relationship, "foo", markWithUnicodeMarker( "" + 10 ) ).getStatus() );
1302 assertEquals(
1303 Status.NO_CONTENT.getStatusCode(),
1304 service.setAllRelationshipProperties( relationship,
1305 markWithUnicodeMarker( "{\"name\":\"Something\",\"number\":10}" ) ).getStatus() );
1306
1307 assertEquals( Status.CREATED.getStatusCode(), service.addToNodeIndex( "node", "foo", "bar",
1308 markWithUnicodeMarker( JsonHelper.createJsonFrom( nodeLocation ) ) ).getStatus() );
1309
1310 assertEquals( Status.OK.getStatusCode(), service.traverse( node, TraverserReturnType.node,
1311 markWithUnicodeMarker( "{\"max depth\":2}" ) ).getStatus() );
1312 }
1313
1314 @Test
1315 public void shouldAdvertiseUriForQueringAllRelationsInTheDatabase() {
1316 Response response = service.getRoot();
1317 assertThat(new String((byte[])response.getEntity()), containsString("\"relationship_types\" : \"http://neo4j.org/relationship/types\""));
1318 }
1319 }