/*
 * 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.Graph.Features.EdgeFeatures;
import org.apache.tinkerpop.gremlin.structure.Graph.Features.EdgePropertyFeatures;
import org.apache.tinkerpop.gremlin.structure.Graph.Features.GraphFeatures;
import org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures;
import org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.UUID;

import static org.apache.tinkerpop.gremlin.structure.Graph.Features.ElementFeatures.FEATURE_ANY_IDS;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.ElementFeatures.FEATURE_NUMERIC_IDS;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.ElementFeatures.FEATURE_STRING_IDS;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.ElementFeatures.FEATURE_UUID_IDS;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.GraphFeatures.FEATURE_COMPUTER;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.GraphFeatures.FEATURE_THREADED_TRANSACTIONS;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.GraphFeatures.FEATURE_TRANSACTIONS;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VariableFeatures.FEATURE_VARIABLES;
import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeThat;

/**
 * Tests that do basic validation of proper Feature settings in Graph implementations.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
@RunWith(Enclosed.class)
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public class FeatureSupportTest {
    private static final String INVALID_FEATURE_SPECIFICATION = "Features for %s specify that %s is false, but the feature appears to be implemented.  Reconsider this setting or throw the standard Exception.";
    private static final Logger logger = LoggerFactory.getLogger(FeatureSupportTest.class);

    public static class FeatureToStringTest extends AbstractGremlinTest {
        /**
         * A rough test to ensure that StringFactory is being used to toString Features.
         */
        @Test
        public void shouldHaveStandardToStringRepresentation() {
            assertTrue(graph.features().toString().startsWith("FEATURES"));
        }
    }

    /**
     * Feature checks that test {@link Graph} functionality to determine if a feature should be on when it is marked
     * as not supported.
     */
    @ExceptionCoverage(exceptionClass = Graph.Exceptions.class, methods = {
            "variablesNotSupported",
            "graphComputerNotSupported",
            "transactionsNotSupported"
    })
    public static class GraphFunctionalityTest extends AbstractGremlinTest {

        /**
         * This isn't really a test.  It just pretty prints the features for the graph for reference.  Of course,
         * if the implementing classes use anonymous inner classes it will
         */
        @Test
        public void shouldPrintTheFeatureList() {
            logger.info(String.format("Printing Features of %s for reference: ", g.getClass().getSimpleName()));
            logger.info(graph.features().toString());
            assertTrue(true);
        }

        /**
         * A {@link Graph} that does not support {@link Graph.Features.GraphFeatures#FEATURE_COMPUTER} must call
         * {@link Graph.Exceptions#graphComputerNotSupported()}.
         */
        @Test
        @FeatureRequirement(featureClass = GraphFeatures.class, feature = FEATURE_COMPUTER, supported = false)
        public void shouldSupportComputerIfAGraphCanCompute() throws Exception {
            try {
                graph.compute();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, GraphFeatures.class.getSimpleName(), FEATURE_COMPUTER));
            } catch (Exception e) {
                validateException(Graph.Exceptions.graphComputerNotSupported(), e);
            }
        }

        /**
         * A {@link Graph} that does not support {@link Graph.Features.GraphFeatures#FEATURE_TRANSACTIONS} must call
         * {@link Graph.Exceptions#transactionsNotSupported()}.
         */
        @Test
        @FeatureRequirement(featureClass = GraphFeatures.class, feature = FEATURE_TRANSACTIONS, supported = false)
        public void shouldSupportTransactionsIfAGraphConstructsATx() throws Exception {
            try {
                graph.tx();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, GraphFeatures.class.getSimpleName(), FEATURE_TRANSACTIONS));
            } catch (Exception e) {
                validateException(Graph.Exceptions.transactionsNotSupported(), e);
            }
        }

        /**
         * A {@link Graph} that does not support {@link Graph.Features.VariableFeatures#FEATURE_VARIABLES} must call
         * {@link Graph.Exceptions#variablesNotSupported()}.
         */
        @Test
        @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = FEATURE_VARIABLES, supported = false)
        public void shouldSupportMemoryIfAGraphAcceptsMemory() throws Exception {
            try {
                graph.variables();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, Graph.Features.VariableFeatures.class.getSimpleName(), FEATURE_VARIABLES));
            } catch (Exception e) {
                validateException(Graph.Exceptions.variablesNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_TRANSACTIONS)
        @FeatureRequirement(featureClass = Graph.Features.GraphFeatures.class, feature = FEATURE_THREADED_TRANSACTIONS, supported = false)
        public void shouldThrowOnThreadedTransactionNotSupported() {
            try {
                graph.tx().createThreadedTx();
                fail("An exception should be thrown since the threaded transaction feature is not supported");
            } catch (Exception e) {
                validateException(Transaction.Exceptions.threadedTransactionsNotSupported(), e);
            }
        }
    }

    /**
     * Feature checks that test {@link Vertex} functionality to determine if a feature
     * should be on when it is marked as not supported.
     */
    @ExceptionCoverage(exceptionClass = Vertex.Exceptions.class, methods = {
            "userSuppliedIdsNotSupported",
            "userSuppliedIdsOfThisTypeNotSupported",
            "vertexRemovalNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Graph.Exceptions.class, methods = {
            "vertexAdditionsNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Element.Exceptions.class, methods = {
            "propertyAdditionNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Property.Exceptions.class, methods = {
            "propertyRemovalNotSupported"
    })
    public static class VertexFunctionalityTest extends AbstractGremlinTest {

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES, supported = false)
        public void shouldSupportAddVerticesIfAVertexCanBeAdded() throws Exception {
            try {
                graph.addVertex();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_ADD_VERTICES));
            } catch (Exception e) {
                validateException(Graph.Exceptions.vertexAdditionsNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsIfAnIdCanBeAssignedToVertex() throws Exception {
            try {
                graph.addVertex(T.id, graphProvider.convertId(99999943835l, Vertex.class));
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_USER_SUPPLIED_IDS));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.userSuppliedIdsNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        public void shouldNotAllowAnyIdsIfUserSuppliedIdsIsFalse() throws Exception {
            assertFalse(graph.features().vertex().willAllowId(graphProvider.convertId(99999943835l, Vertex.class)));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_STRING_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeString() throws Exception {
            final String id = "this-is-a-valid-id";

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().willAllowId(id));

            try {
                graph.addVertex(T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_STRING_IDS));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeNumericInt() throws Exception {
            final int id = 123456;

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().willAllowId(id));

            try {
                graph.addVertex(T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeNumericLong() throws Exception {
            final long id = 123456l;

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().willAllowId(id));

            try {
                graph.addVertex(T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_UUID_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeUuid() throws Exception {
            final UUID id = UUID.randomUUID();

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().willAllowId(id));

            try {
                graph.addVertex(T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_UUID_IDS));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_ANY_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeAny() throws Exception {
            try {
                final Date id = new Date();
                graph.addVertex(T.id, id);

                // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
                // to throw the exception
                if (!graph.features().vertex().willAllowId(id))
                    fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_ANY_IDS));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_STRING_IDS, supported = false)
        public void shouldSupportStringIdsIfStringIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            if (v.id() instanceof String)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_STRING_IDS));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_UUID_IDS, supported = false)
        public void shouldSupportUuidIdsIfUuidIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            if (v.id() instanceof UUID)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_UUID_IDS));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportNumericIdsIfNumericIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            if (v.id() instanceof Number)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_ADD_PROPERTY, supported = false)
        public void shouldSupportAddVertexPropertyIfItCanBeAdded() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "should", "not-add-property");
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_ADD_PROPERTY));
            } catch (Exception e) {
                validateException(Element.Exceptions.propertyAdditionNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_REMOVE_VERTICES, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        public void shouldSupportRemoveVerticesIfAVertexCanBeRemoved() throws Exception {
            try {
                graph.addVertex().remove();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_REMOVE_VERTICES));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.vertexRemovalNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_REMOVE_PROPERTY, supported = false)
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        public void shouldSupportRemovePropertyIfAPropertyCanBeRemoved() throws Exception {
            try {
                final Vertex v = graph.addVertex("name", "me");
                v.property("name").remove();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_REMOVE_PROPERTY));
            } catch (Exception e) {
                validateException(Property.Exceptions.propertyRemovalNotSupported(), e);
            }
        }
    }

    /**
     * Feature checks that test {@link Edge} functionality to determine if a feature
     * should be on when it is marked as not supported.
     */
    @ExceptionCoverage(exceptionClass = Vertex.Exceptions.class, methods = {
            "edgeAdditionsNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Edge.Exceptions.class, methods = {
            "edgeRemovalNotSupported",
            "userSuppliedIdsNotSupported",
            "userSuppliedIdsOfThisTypeNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Element.Exceptions.class, methods = {
            "propertyAdditionNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Property.Exceptions.class, methods = {
            "propertyRemovalNotSupported"
    })
    public static class EdgeFunctionalityTest extends AbstractGremlinTest {

        @Test
        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        public void shouldSupportAddEdgesIfEdgeCanBeAdded() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                v.addEdge("friend", v);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), EdgeFeatures.FEATURE_ADD_EDGES));
            } catch (Exception e) {
                validateException(Vertex.Exceptions.edgeAdditionsNotSupported(), e);
            }
        }

        @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)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = EdgeFeatures.FEATURE_USER_SUPPLIED_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsIfAnIdCanBeAssignedToEdge() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                v.addEdge("friend", v, T.id, graphProvider.convertId(99999943835l, Edge.class));
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), EdgeFeatures.FEATURE_USER_SUPPLIED_IDS));
            } catch (Exception e) {
                validateException(Edge.Exceptions.userSuppliedIdsNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = EdgeFeatures.FEATURE_USER_SUPPLIED_IDS, supported = false)
        public void shouldNotAllowAnyIdsIfUserSuppliedIdsIsFalse() throws Exception {
            assertFalse(graph.features().edge().willAllowId(graphProvider.convertId(99999943835l, Edge.class)));
        }

        @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)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = FEATURE_STRING_IDS, supported = false)
        public void shouldSupportStringIdsIfStringIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            final Edge e = v.addEdge("knows", v);
            if (e.id() instanceof String)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_STRING_IDS));
        }

        @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)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = FEATURE_UUID_IDS, supported = false)
        public void shouldSupportUuidIdsIfUuidIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            final Edge e = v.addEdge("knows", v);
            if (e.id() instanceof UUID)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_UUID_IDS));
        }

        @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)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = EdgeFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportNumericIdsIfNumericIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            final Edge e = v.addEdge("knows", v);
            if (e.id() instanceof Number)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_STRING_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeString() throws Exception {
            final String id = "this-is-a-valid-id";

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().edge().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.addEdge("test", v, T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_STRING_IDS));
            } catch (Exception e) {
                validateException(Edge.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeNumericInt() throws Exception {
            final int id = 123456;

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().edge().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.addEdge("test", v, T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
            } catch (Exception e) {
                validateException(Edge.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeNumericLong() throws Exception {
            final long id = 123456l;

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().edge().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.addEdge("test", v, T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
            } catch (Exception e) {
                validateException(Edge.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_UUID_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeUuid() throws Exception {
            final UUID id = UUID.randomUUID();

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().edge().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.addEdge("test", v, T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_UUID_IDS));
            } catch (Exception e) {
                validateException(Edge.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @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)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexFeatures.class, feature = FEATURE_ANY_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeAny() throws Exception {
            final Date id = new Date();

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().edge().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.addEdge("test", v, T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), FEATURE_ANY_IDS));
            } catch (Exception e) {
                validateException(Edge.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), e);
            }
        }

        @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)
        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = EdgeFeatures.FEATURE_ADD_PROPERTY, supported = false)
        public void shouldSupportAddEdgePropertyIfItCanBeAdded() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                final Edge e = v.addEdge("test", v);
                e.property("should", "not-add-property");
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgePropertyFeatures.class.getSimpleName(), EdgeFeatures.FEATURE_ADD_PROPERTY));
            } catch (Exception e) {
                validateException(Element.Exceptions.propertyAdditionNotSupported(), e);
            }
        }

        @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, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        public void shouldSupportRemoveEdgesIfEdgeCanBeRemoved() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                v.addEdge("friend", v);
                v.remove();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), EdgeFeatures.FEATURE_REMOVE_EDGES));
            } catch (Exception ex) {
                validateException(Edge.Exceptions.edgeRemovalNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = EdgeFeatures.FEATURE_REMOVE_PROPERTY, supported = false)
        @FeatureRequirementSet(FeatureRequirementSet.Package.SIMPLE)
        public void shouldSupportRemovePropertyIfAPropertyCanBeRemoved() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                final Edge e = v.addEdge("self", v, "name", "foo");
                e.property("name").remove();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgeFeatures.class.getSimpleName(), EdgeFeatures.FEATURE_REMOVE_PROPERTY));
            } catch (Exception ex) {
                validateException(Property.Exceptions.propertyRemovalNotSupported(), ex);
            }
        }
    }

    /**
     * Feature checks that test {@link Element} {@link Property} functionality to determine if a feature should be on
     * when it is marked as not supported.
     */
    @RunWith(Parameterized.class)
    @ExceptionCoverage(exceptionClass = Property.Exceptions.class, methods = {
            "dataTypeOfPropertyValueNotSupported"
    })
    public static class ElementPropertyDataTypeFunctionalityTest extends AbstractGremlinTest {
        private static final String INVALID_FEATURE_SPECIFICATION = "Features for %s specify that %s is false, but the feature appears to be implemented.  Reconsider this setting or throw the standard Exception.";

        @Parameterized.Parameters(name = "supports{0}({1})")
        public static Iterable<Object[]> data() {
            return PropertyTest.PropertyFeatureSupportTest.data();
        }

        @Parameterized.Parameter(value = 0)
        public String featureName;

        @Parameterized.Parameter(value = 1)
        public Object value;

        @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)
        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = EdgeFeatures.FEATURE_ADD_PROPERTY)
        public void shouldEnableFeatureOnEdgeIfNotEnabled() throws Exception {
            assumeThat(graph.features().supports(EdgePropertyFeatures.class, featureName), is(false));
            try {
                final Edge edge = createEdgeForPropertyFeatureTests();
                edge.property("aKey", value);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, EdgePropertyFeatures.class.getSimpleName(), featureName));
            } catch (Exception e) {
                validateException(Property.Exceptions.dataTypeOfPropertyValueNotSupported(value), e);
            }
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
        public void shouldEnableFeatureOnVertexIfNotEnabled() throws Exception {
            assumeThat(graph.features().supports(VertexPropertyFeatures.class, featureName), is(false));
            try {
                graph.addVertex("aKey", value);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), featureName));
            } catch (Exception e) {
                validateException(Property.Exceptions.dataTypeOfPropertyValueNotSupported(value), e);
            }
        }

        private Edge createEdgeForPropertyFeatureTests() {
            final Vertex vertexA = graph.addVertex();
            final Vertex vertexB = graph.addVertex();
            return vertexA.addEdge(graphProvider.convertLabel("knows"), vertexB);
        }
    }

    /**
     * Feature checks that tests if {@link Graph.Variables}
     * functionality to determine if a feature should be on when it is marked as not supported.
     */
    @RunWith(Parameterized.class)
    @ExceptionCoverage(exceptionClass = Graph.Variables.Exceptions.class, methods = {
            "dataTypeOfVariableValueNotSupported"
    })
    public static class GraphVariablesFunctionalityTest extends AbstractGremlinTest {
        private static final String INVALID_FEATURE_SPECIFICATION = "Features for %s specify that %s is false, but the feature appears to be implemented.  Reconsider this setting or throw the standard Exception.";

        @Parameterized.Parameters(name = "supports{0}({1})")
        public static Iterable<Object[]> data() {
            return VariablesTest.GraphVariablesFeatureSupportTest.data();
        }

        @Parameterized.Parameter(value = 0)
        public String featureName;

        @Parameterized.Parameter(value = 1)
        public Object value;

        /**
         * In this case, the feature requirement for sideEffects is checked, because it means that at least one aspect of
         * sideEffects is supported so we need to test other features to make sure they work properly.
         */
        @Test
        @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES)
        public void shouldEnableFeatureOnGraphIfNotEnabled() throws Exception {
            assumeThat(graph.features().supports(Graph.Features.VariableFeatures.class, featureName), is(false));
            try {
                final Graph.Variables variables = graph.variables();
                variables.set("aKey", value);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, Graph.Features.VariableFeatures.class.getSimpleName(), featureName));
            } catch (Exception e) {
                validateException(Graph.Variables.Exceptions.dataTypeOfVariableValueNotSupported(value), e);
            }
        }
    }

    @ExceptionCoverage(exceptionClass = VertexProperty.Exceptions.class, methods = {
            "multiPropertiesNotSupported",
            "metaPropertiesNotSupported",
            "userSuppliedIdsNotSupported",
            "userSuppliedIdsOfThisTypeNotSupported",
            "identicalMultiPropertiesNotSupported"
    })
    @ExceptionCoverage(exceptionClass = Element.Exceptions.class, methods = {
            "propertyRemovalNotSupported"
    })
    public static class VertexPropertyFunctionalityTest extends AbstractGremlinTest {

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = VertexPropertyFeatures.FEATURE_USER_SUPPLIED_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsIfAnIdCanBeAssigned() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "name", "me", T.id, graphProvider.convertId(99999943835l, VertexProperty.class));
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), VertexPropertyFeatures.FEATURE_USER_SUPPLIED_IDS));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.userSuppliedIdsNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        public void shouldNotAllowAnyIdsIfUserSuppliedIdsIsFalse() throws Exception {
            assertFalse(graph.features().vertex().properties().willAllowId(graphProvider.convertId(99999943835l, VertexProperty.class)));
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeString() throws Exception {
            final String id = "this-is-a-valid-id";

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().properties().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "test", "me", T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), FEATURE_STRING_IDS));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeNumericInt() throws Exception {
            final int id = 123456;

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().properties().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "test", "me", T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeNumericLong() throws Exception {
            final long id = 123456l;

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().properties().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "test", "me", T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), FEATURE_NUMERIC_IDS));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_UUID_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeUuid() throws Exception {
            final UUID id = UUID.randomUUID();

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().properties().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "test", "me", T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), FEATURE_UUID_IDS));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_ANY_IDS, supported = false)
        public void shouldSupportUserSuppliedIdsOfTypeAny() throws Exception {
            final Date id = new Date();

            // a graph can "allow" an id without internally supporting it natively and therefore doesn't need
            // to throw the exception
            assumeFalse(graph.features().vertex().properties().willAllowId(id));

            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "test", "me", T.id, id);
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), FEATURE_ANY_IDS));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.userSuppliedIdsOfThisTypeNotSupported(), ex);
            }
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_IDS, supported = false)
        public void shouldSupportStringIdsIfStringIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            final VertexProperty p = v.property(VertexProperty.Cardinality.single, "name", "stephen");
            if (p.id() instanceof String)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), VertexPropertyFeatures.FEATURE_STRING_IDS));
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_UUID_IDS, supported = false)
        public void shouldSupportUuidIdsIfUuidIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            final VertexProperty p = v.property(VertexProperty.Cardinality.single, "name", "stephen");
            if (p.id() instanceof UUID)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), VertexPropertyFeatures.FEATURE_UUID_IDS));
        }

        @Test
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS, supported = false)
        @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_NUMERIC_IDS, supported = false)
        public void shouldSupportNumericIdsIfNumericIdsAreGeneratedFromTheGraph() throws Exception {
            final Vertex v = graph.addVertex();
            final VertexProperty p = v.property(VertexProperty.Cardinality.single, "name", "stephen");
            if (p.id() instanceof Number)
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), VertexPropertyFeatures.FEATURE_NUMERIC_IDS));
        }


        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = VertexPropertyFeatures.FEATURE_REMOVE_PROPERTY, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES)
        @FeatureRequirementSet(FeatureRequirementSet.Package.VERTICES_ONLY)
        public void shouldSupportRemovePropertyIfAPropertyCanBeRemoved() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                final VertexProperty p = v.property(VertexProperty.Cardinality.single, "name", "me", "test", "this");
                p.property("test").remove();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexPropertyFeatures.class.getSimpleName(), VertexPropertyFeatures.FEATURE_REMOVE_PROPERTY));
            } catch (Exception ex) {
                validateException(Property.Exceptions.propertyRemovalNotSupported(), 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)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_MULTI_PROPERTIES)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_DUPLICATE_MULTI_PROPERTIES, supported = false)
        public void shouldSupportIdenticalMultiPropertyIfTheSameKeyCanBeAssignedSameValueMoreThanOnce() throws Exception {
            try {
                final Vertex v = graph.addVertex("name", "stephen", "name", "stephen");
                if (2 == IteratorUtils.count(v.properties()))
                    fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_DUPLICATE_MULTI_PROPERTIES));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.identicalMultiPropertiesNotSupported(), 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)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_MULTI_PROPERTIES, supported = false)
        public void shouldSupportMultiPropertyIfTheSameKeyCanBeAssignedMoreThanOnce() throws Exception {
            try {
                final Vertex v = graph.addVertex("name", "stephen", "name", "steve");
                if (2 == IteratorUtils.count(v.properties()))
                    fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_MULTI_PROPERTIES));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.multiPropertiesNotSupported(), 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)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES)
        public void shouldSupportMetaPropertyIfPropertiesCanBePutOnProperties() throws Exception {
            try {
                final Vertex v = graph.addVertex();
                v.property(VertexProperty.Cardinality.single, "name", "stephen", "p", "on-property");
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_META_PROPERTIES));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.metaPropertiesNotSupported(), 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)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES)
        public void shouldSupportMetaPropertyIfPropertiesCanBePutOnPropertiesViaVertexProperty() throws Exception {
            try {
                final Vertex v = graph.addVertex("name", "stephen");
                v.property("name").property("p", "on-property");
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_META_PROPERTIES));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.metaPropertiesNotSupported(), 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)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_PROPERTY)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES, supported = false)
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = VertexFeatures.FEATURE_META_PROPERTIES)
        public void shouldSupportMetaPropertyIfPropertiesHaveAnIteratorViaVertexProperty() throws Exception {
            try {
                final Vertex v = graph.addVertex("name", "stephen");
                v.property("name").properties();
                fail(String.format(INVALID_FEATURE_SPECIFICATION, VertexFeatures.class.getSimpleName(), VertexFeatures.FEATURE_META_PROPERTIES));
            } catch (Exception ex) {
                validateException(VertexProperty.Exceptions.metaPropertiesNotSupported(), ex);
            }
        }
    }

    /**
     * Feature checks that simply evaluate conflicting feature definitions without evaluating the actual implementation
     * itself.
     */
    public static class LogicalFeatureSupportTest extends AbstractGremlinTest {

        private EdgeFeatures edgeFeatures;
        private EdgePropertyFeatures edgePropertyFeatures;
        private GraphFeatures graphFeatures;
        private Graph.Features.VariableFeatures variablesFeatures;
        private VertexFeatures vertexFeatures;
        private VertexPropertyFeatures vertexPropertyFeatures;

        @Before
        public void innerSetup() {
            final Graph.Features f = graph.features();
            edgeFeatures = f.edge();
            edgePropertyFeatures = edgeFeatures.properties();
            graphFeatures = f.graph();
            variablesFeatures = graphFeatures.variables();
            vertexFeatures = f.vertex();
            vertexPropertyFeatures = vertexFeatures.properties();
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ANY_IDS)
        public void shouldNotSupportAnyIdsUnlessUserSuppliedIdsIsSupportedOnVertex() {
            assertTrue(vertexFeatures.supportsUserSuppliedIds());
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = FEATURE_ANY_IDS)
        public void shouldNotSupportAnyIdsUnlessUserSuppliedIdsIsSupportedOnEdge() {
            assertTrue(edgeFeatures.supportsUserSuppliedIds());
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = VertexPropertyFeatures.FEATURE_ANY_IDS)
        public void shouldNotSupportAnyIdsUnlessUserSuppliedIdsIsSupportedOnVertexProperty() {
            assertTrue(vertexPropertyFeatures.supportsUserSuppliedIds());
        }

        @Test
        public void shouldSupportADataTypeIfGraphHasVariablesEnabled() {
            assertEquals(variablesFeatures.supportsVariables(), (variablesFeatures.supportsBooleanValues() || variablesFeatures.supportsDoubleValues()
                    || variablesFeatures.supportsFloatValues() || variablesFeatures.supportsIntegerValues()
                    || variablesFeatures.supportsLongValues() || variablesFeatures.supportsMapValues()
                    || variablesFeatures.supportsMixedListValues() || variablesFeatures.supportsByteValues()
                    || variablesFeatures.supportsBooleanArrayValues() || variablesFeatures.supportsByteArrayValues()
                    || variablesFeatures.supportsDoubleArrayValues() || variablesFeatures.supportsFloatArrayValues()
                    || variablesFeatures.supportsIntegerArrayValues() || variablesFeatures.supportsLongArrayValues()
                    || variablesFeatures.supportsSerializableValues() || variablesFeatures.supportsStringValues()
                    || variablesFeatures.supportsUniformListValues() || variablesFeatures.supportsStringArrayValues()));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_PROPERTIES)
        public void shouldSupportADataTypeIfEdgeHasPropertyEnabled() {
            assertEquals(edgePropertyFeatures.supportsProperties(), (edgePropertyFeatures.supportsBooleanValues() || edgePropertyFeatures.supportsDoubleValues()
                    || edgePropertyFeatures.supportsFloatValues() || edgePropertyFeatures.supportsIntegerValues()
                    || edgePropertyFeatures.supportsLongValues() || edgePropertyFeatures.supportsMapValues()
                    || edgePropertyFeatures.supportsMixedListValues() || edgePropertyFeatures.supportsByteValues()
                    || edgePropertyFeatures.supportsBooleanArrayValues() || edgePropertyFeatures.supportsByteArrayValues()
                    || edgePropertyFeatures.supportsDoubleArrayValues() || edgePropertyFeatures.supportsFloatArrayValues()
                    || edgePropertyFeatures.supportsIntegerArrayValues() || edgePropertyFeatures.supportsLongArrayValues()
                    || edgePropertyFeatures.supportsSerializableValues() || edgePropertyFeatures.supportsStringValues()
                    || edgePropertyFeatures.supportsUniformListValues() || edgePropertyFeatures.supportsStringArrayValues()));
        }

        @Test
        @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = VertexPropertyFeatures.FEATURE_PROPERTIES)
        public void shouldSupportADataTypeIfVertexHasPropertyEnabled() {
            assertEquals(vertexPropertyFeatures.supportsProperties(), (vertexPropertyFeatures.supportsBooleanValues() || vertexPropertyFeatures.supportsDoubleValues()
                    || vertexPropertyFeatures.supportsFloatValues() || vertexPropertyFeatures.supportsIntegerValues()
                    || vertexPropertyFeatures.supportsLongValues() || vertexPropertyFeatures.supportsMapValues()
                    || vertexPropertyFeatures.supportsMixedListValues() || vertexPropertyFeatures.supportsByteValues()
                    || vertexPropertyFeatures.supportsBooleanArrayValues() || vertexPropertyFeatures.supportsByteArrayValues()
                    || vertexPropertyFeatures.supportsDoubleArrayValues() || vertexPropertyFeatures.supportsFloatArrayValues()
                    || vertexPropertyFeatures.supportsIntegerArrayValues() || vertexPropertyFeatures.supportsLongArrayValues()
                    || vertexPropertyFeatures.supportsSerializableValues() || vertexPropertyFeatures.supportsStringValues()
                    || vertexPropertyFeatures.supportsUniformListValues() || vertexPropertyFeatures.supportsStringArrayValues()));
        }

        @Test
        public void shouldSupportRegularTransactionsIfThreadedTransactionsAreEnabled() {
            if (graphFeatures.supportsThreadedTransactions())
                assertThat(graphFeatures.supportsThreadedTransactions(), is(true));
        }

        @Test
        public void shouldSupportMultiPropertiesIfSupportingIdenticalMultiProperties() {
            if (vertexFeatures.supportsDuplicateMultiProperties())
                assertThat(vertexFeatures.supportsMultiProperties(), is(true));
        }
    }
}
