/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tinkerpop.gremlin.structure; import org.apache.tinkerpop.gremlin.AbstractGremlinTest; import org.apache.tinkerpop.gremlin.ExceptionCoverage; import org.apache.tinkerpop.gremlin.FeatureRequirement; import org.apache.tinkerpop.gremlin.FeatureRequirementSet; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import java.util.Iterator; import java.util.List; import java.util.Set; import static org.apache.tinkerpop.gremlin.structure.Graph.Features.PropertyFeatures.*; import static org.junit.Assert.*; /** * @author Stephen Mallette (http://stephen.genoprime.com) * @author Marko A. Rodriguez (http://markorodriguez.com) */ @RunWith(Enclosed.class) public class EdgeTest { @ExceptionCoverage(exceptionClass = Element.Exceptions.class, methods = { "labelCanNotBeNull", "labelCanNotBeEmpty", "labelCanNotBeAHiddenKey" }) public static class BasicEdgeTest extends AbstractGremlinTest { @Test @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) public void shouldValidateEquality() { final Vertex v = graph.addVertex(); final Edge e1 = v.addEdge("self", v); final Edge e2 = v.addEdge("self", v); assertEquals(e1, e1); assertEquals(e2, e2); assertNotEquals(e1, e2); } @Test @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) public void shouldValidateIdEquality() { final Vertex v = graph.addVertex(); final Edge e1 = v.addEdge("self", v); final Edge e2 = v.addEdge("self", v); assertEquals(e1.id(), e1.id()); assertEquals(e2.id(), e2.id()); assertEquals(e1.id().toString(), e1.id().toString()); assertEquals(e2.id().toString(), e2.id().toString()); assertNotEquals(e1.id(), e2.id()); assertNotEquals(e1.id().toString(), e2.id().toString()); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldHaveStandardStringRepresentation() { final Vertex v1 = graph.addVertex(); final Vertex v2 = graph.addVertex(); final Edge e = v1.addEdge("friends", v2); assertEquals(StringFactory.edgeString(e), e.toString()); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldHaveExceptionConsistencyWhenUsingNullEdgeLabel() { final Vertex v = graph.addVertex(); try { v.addEdge(null, v); fail("Call to Vertex.addEdge() should throw an exception when label is null"); } catch (Exception ex) { validateException(Element.Exceptions.labelCanNotBeNull(), ex); } } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldHaveExceptionConsistencyWhenUsingNullVertex() { final Vertex v = graph.addVertex(); try { v.addEdge("tonothing", null); fail("Call to Vertex.addEdge() should throw an exception when vertex is null"); } catch (Exception ex) { validateException(Graph.Exceptions.argumentCanNotBeNull("vertex"), ex); } } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldHaveExceptionConsistencyWhenUsingEmptyVertexLabel() { final Vertex v = graph.addVertex(); try { v.addEdge("", v); fail("Call to Vertex.addEdge() should throw an exception when label is empty"); } catch (Exception ex) { validateException(Element.Exceptions.labelCanNotBeEmpty(), ex); } } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldHaveExceptionConsistencyWhenUsingSystemVertexLabel() { final String label = Graph.Hidden.hide("systemLabel"); final Vertex v = graph.addVertex(); try { v.addEdge(label, v); fail("Call to Vertex.addEdge() should throw an exception when label is a system key"); } catch (Exception ex) { validateException(Element.Exceptions.labelCanNotBeAHiddenKey(label), ex); } } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_STRING_VALUES) public void shouldAutotypeStringProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v, "string", "marko"); final String name = e.value("string"); assertEquals(name, "marko"); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) public void shouldAutotypeIntegerProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v, "integer", 33); final Integer age = e.value("integer"); assertEquals(Integer.valueOf(33), age); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_BOOLEAN_VALUES) public void shouldAutotypeBooleanProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v, "boolean", true); final Boolean best = e.value("boolean"); assertEquals(best, true); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_DOUBLE_VALUES) public void shouldAutotypeDoubleProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v, "double", 0.1d); final Double best = e.value("double"); assertEquals(best, Double.valueOf(0.1d)); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_LONG_VALUES) public void shouldAutotypeLongProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v, "long", 1l); final Long best = e.value("long"); assertEquals(best, Long.valueOf(1l)); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_PROPERTY) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = FEATURE_FLOAT_VALUES) public void shouldAutotypeFloatProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v, "float", 0.1f); final Float best = e.value("float"); assertEquals(best, Float.valueOf(0.1f)); } @Test @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE) public void shouldGetPropertyKeysOnEdge() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("friend", v, "name", "marko", "location", "desert", "status", "dope"); Set<String> keys = e.keys(); assertEquals(3, keys.size()); assertTrue(keys.contains("name")); assertTrue(keys.contains("location")); assertTrue(keys.contains("status")); final List<Property<Object>> m = IteratorUtils.list(e.properties()); assertEquals(3, m.size()); assertTrue(m.stream().anyMatch(p -> p.key().equals("name"))); assertTrue(m.stream().anyMatch(p -> p.key().equals("location"))); assertTrue(m.stream().anyMatch(p -> p.key().equals("status"))); assertEquals("marko", m.stream().filter(p -> p.key().equals("name")).map(Property::value).findAny().orElse(null)); assertEquals("desert", m.stream().filter(p -> p.key().equals("location")).map(Property::value).findAny().orElse(null)); assertEquals("dope", m.stream().filter(p -> p.key().equals("status")).map(Property::value).findAny().orElse(null)); e.property("status").remove(); keys = e.keys(); assertEquals(2, keys.size()); assertTrue(keys.contains("name")); assertTrue(keys.contains("location")); e.properties().forEachRemaining(Property::remove); keys = e.keys(); assertEquals(0, keys.size()); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_REMOVE_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldNotGetConcurrentModificationException() { for (int i = 0; i < 25; i++) { final Vertex v = graph.addVertex(); v.addEdge("friend", v); } tryCommit(graph, getAssertVertexEdgeCounts(25, 25)); for (Edge e : g.E().toList()) { e.remove(); tryCommit(graph); } tryCommit(graph, getAssertVertexEdgeCounts(25, 0)); } @Test @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE) @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_INTEGER_VALUES) @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_REMOVE_EDGES) public void shouldNotHaveAConcurrentModificationExceptionWhenIteratingAndRemovingAddingEdges() { final Vertex v1 = graph.addVertex("name", "marko"); final Vertex v2 = graph.addVertex("name", "puppy"); v1.addEdge("knows", v2, "since", 2010); v1.addEdge("pets", v2); v1.addEdge("walks", v2, "location", "arroyo"); v2.addEdge("knows", v1, "since", 2010); assertEquals(4l, IteratorUtils.count(v1.edges(Direction.BOTH))); assertEquals(4l, IteratorUtils.count(v2.edges(Direction.BOTH))); v1.edges(Direction.BOTH).forEachRemaining(edge -> { v1.addEdge("livesWith", v2); v1.addEdge("walks", v2, "location", "river"); edge.remove(); }); //assertEquals(8, v1.outE().count().next().intValue()); TODO: Neo4j is not happy //assertEquals(8, v2.outE().count().next().intValue()); v1.edges(Direction.BOTH).forEachRemaining(Edge::remove); assertEquals(0, IteratorUtils.count(v1.edges(Direction.BOTH))); assertEquals(0, IteratorUtils.count(v2.edges(Direction.BOTH))); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldReturnEmptyIteratorIfNoProperties() { final Vertex v = graph.addVertex(); final Edge e = v.addEdge("knows", v); assertEquals(0, IteratorUtils.count(e.properties())); } @Test @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) public void shouldReturnOutThenInOnVertexIterator() { final Vertex a = graph.addVertex(); final Vertex b = graph.addVertex(); final Edge e = a.addEdge("knows", b); assertEquals(a, e.outVertex()); assertEquals(b, e.inVertex()); final Iterator<Vertex> iterator = e.vertices(Direction.BOTH); assertTrue(iterator.hasNext()); assertEquals(a, iterator.next()); assertTrue(iterator.hasNext()); assertEquals(b, iterator.next()); assertFalse(iterator.hasNext()); } } }