View Javadoc

    1   /**
    2    * Copyright (c) 2002-2011 "Neo Technology,"
    3    * Network Engine for Objects in Lund AB [http://neotechnology.com]
    4    *
    5    * This file is part of Neo4j.
    6    *
    7    * Neo4j is free software: you can redistribute it and/or modify
    8    * it under the terms of the GNU General Public License as published by
    9    * the Free Software Foundation, either version 3 of the License, or
    10   * (at your option) any later version.
    11   *
    12   * This program is distributed in the hope that it will be useful,
    13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15   * GNU General Public License for more details.
    16   *
    17   * You should have received a copy of the GNU General Public License
    18   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    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         // query for the first letter with which the nodes were indexed.
    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" ); // unlike exact match, a query can not return a sensible index uri for the result
    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 ); // queries can not return a sensible index uri
    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 }