/* * 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.structure.util.StringFactory; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VariableFeatures.FEATURE_VARIABLES; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.*; import static org.junit.Assume.assumeThat; /** * Gremlin Test Suite for {@link org.apache.tinkerpop.gremlin.structure.Graph.Variables} operations. * * @author Stephen Mallette (http://stephen.genoprime.com) */ @RunWith(Enclosed.class) @SuppressWarnings("ThrowableResultOfMethodCallIgnored") public class VariablesTest { /** * Basic tests to ensure that {@link org.apache.tinkerpop.gremlin.structure.Graph.Variables} have * appropriate {@link String} representations. */ public static class StringRepresentationTest extends AbstractGremlinTest { @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_STRING_VALUES) public void testVariables() { final Graph.Variables variables = graph.variables(); variables.set("xo", "test1"); variables.set("yo", "test2"); variables.set("zo", "test3"); tryCommit(graph, graph -> assertEquals(StringFactory.graphVariablesString(variables), variables.toString())); } } /** * Test exceptions around {@link org.apache.tinkerpop.gremlin.structure.Graph.Variables}. */ @RunWith(Parameterized.class) @ExceptionCoverage(exceptionClass = Graph.Variables.Exceptions.class, methods = { "variableValueCanNotBeNull", "variableKeyCanNotBeNull", "variableKeyCanNotBeEmpty" }) public static class VariableExceptionConsistencyTest extends AbstractGremlinTest { @Parameterized.Parameters(name = "expect({0})") public static Iterable<Object[]> data() { return Arrays.asList(new Object[][]{ {"variableValueCanNotBeNull", "k", null, Graph.Variables.Exceptions.variableValueCanNotBeNull()}, {"variableKeyCanNotBeNull", null, "v", Graph.Variables.Exceptions.variableKeyCanNotBeNull()}, {"variableKeyCanNotBeEmpty", "", "v", Graph.Variables.Exceptions.variableKeyCanNotBeEmpty()}}); } @Parameterized.Parameter(value = 0) public String name; @Parameterized.Parameter(value = 1) public String key; @Parameterized.Parameter(value = 2) public String val; @Parameterized.Parameter(value = 3) public Exception expectedException; @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = FEATURE_VARIABLES) public void testGraphVariablesSet() throws Exception { try { graph.variables().set(key, val); fail(String.format("Setting an annotation with these arguments [key: %s value: %s] should throw an exception", key, val)); } catch (Exception ex) { validateException(expectedException, ex); } } } /** * Ensure that the {@link org.apache.tinkerpop.gremlin.structure.Graph.Variables#asMap()} method returns some basics. * Other tests will enforce that all types are properly covered in {@link org.apache.tinkerpop.gremlin.structure.Graph.Variables}. */ public static class VariableAsMapTest extends AbstractGremlinTest { @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_STRING_VALUES) public void shouldHoldVariableNone() { final Graph.Variables variables = graph.variables(); final Map<String, Object> mapOfAnnotations = variables.asMap(); assertNotNull(mapOfAnnotations); assertEquals(0, mapOfAnnotations.size()); try { mapOfAnnotations.put("something", "can't do this"); fail("Should not be able to mutate the Map returned from Graph.variables.getAnnotations()"); } catch (UnsupportedOperationException ignored) { } } @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_STRING_VALUES) public void shouldHoldVariableString() { final Graph.Variables variables = graph.variables(); variables.set("test1", "1"); variables.set("test2", "2"); variables.set("test3", "3"); tryCommit(graph, graph -> { final Map<String, Object> m = variables.asMap(); assertEquals("1", m.get("test1")); assertEquals("2", m.get("test2")); assertEquals("3", m.get("test3")); }); } @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES) public void shouldHoldVariableInteger() { final Graph.Variables variables = graph.variables(); variables.set("test1", 1); variables.set("test2", 2); variables.set("test3", 3); tryCommit(graph, graph -> { final Map<String, Object> m = variables.asMap(); assertEquals(1, m.get("test1")); assertEquals(2, m.get("test2")); assertEquals(3, m.get("test3")); }); } @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_LONG_VALUES) public void shouldHoldVariableLong() { final Graph.Variables variables = graph.variables(); variables.set("test1", 1l); variables.set("test2", 2l); variables.set("test3", 3l); tryCommit(graph, graph -> { final Map<String, Object> m = variables.asMap(); assertEquals(1l, m.get("test1")); assertEquals(2l, m.get("test2")); assertEquals(3l, m.get("test3")); }); } @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_VARIABLES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_STRING_VALUES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES) @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = Graph.Features.VariableFeatures.FEATURE_LONG_VALUES) public void shouldHoldVariableMixed() { final Graph.Variables variables = graph.variables(); variables.set("test1", "1"); variables.set("test2", 2); variables.set("test3", 3l); tryCommit(graph, graph -> { final Map<String, Object> m = variables.asMap(); assertEquals("1", m.get("test1")); assertEquals(2, m.get("test2")); assertEquals(3l, m.get("test3")); }); } } /** * Tests for feature support on {@link org.apache.tinkerpop.gremlin.structure.Graph.Variables}. The tests validate if * {@link org.apache.tinkerpop.gremlin.structure.Graph.Features.VariableFeatures} should be turned on or off and if the * enabled features are properly supported by the implementation. Note that these tests are run in a separate * test class as they are "parameterized" tests. */ @RunWith(Parameterized.class) public static class GraphVariablesFeatureSupportTest extends AbstractGremlinTest { private static final Map<String, Object> testMap = new HashMap<>(); private static final ArrayList<Object> mixedList = new ArrayList<>(); private static final ArrayList<String> uniformStringList = new ArrayList<>(); private static final ArrayList<Integer> uniformIntegerList = new ArrayList<>(); static { testMap.put("testString", "try"); testMap.put("testInteger", 123); mixedList.add("try1"); mixedList.add(2); uniformStringList.add("try1"); uniformStringList.add("try2"); uniformIntegerList.add(100); uniformIntegerList.add(200); uniformIntegerList.add(300); } @Parameterized.Parameters(name = "supports{0}({1})") public static Iterable<Object[]> data() { return Arrays.asList(new Object[][]{ {Graph.Features.VariableFeatures.FEATURE_BOOLEAN_VALUES, true}, {Graph.Features.VariableFeatures.FEATURE_BOOLEAN_VALUES, false}, {Graph.Features.VariableFeatures.FEATURE_DOUBLE_VALUES, Double.MIN_VALUE}, {Graph.Features.VariableFeatures.FEATURE_DOUBLE_VALUES, Double.MAX_VALUE}, {Graph.Features.VariableFeatures.FEATURE_DOUBLE_VALUES, 0.0d}, {Graph.Features.VariableFeatures.FEATURE_DOUBLE_VALUES, 0.5d}, {Graph.Features.VariableFeatures.FEATURE_DOUBLE_VALUES, -0.5d}, {Graph.Features.VariableFeatures.FEATURE_FLOAT_VALUES, Float.MIN_VALUE}, {Graph.Features.VariableFeatures.FEATURE_FLOAT_VALUES, Float.MAX_VALUE}, {Graph.Features.VariableFeatures.FEATURE_FLOAT_VALUES, 0.0f}, {Graph.Features.VariableFeatures.FEATURE_FLOAT_VALUES, 0.5f}, {Graph.Features.VariableFeatures.FEATURE_FLOAT_VALUES, -0.5f}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES, Integer.MIN_VALUE}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES, Integer.MAX_VALUE}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES, 0}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES, 10000}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_VALUES, -10000}, {Graph.Features.VariableFeatures.FEATURE_LONG_VALUES, Long.MIN_VALUE}, {Graph.Features.VariableFeatures.FEATURE_LONG_VALUES, Long.MAX_VALUE}, {Graph.Features.VariableFeatures.FEATURE_LONG_VALUES, 0l}, {Graph.Features.VariableFeatures.FEATURE_LONG_VALUES, 10000l}, {Graph.Features.VariableFeatures.FEATURE_LONG_VALUES, -10000l}, {Graph.Features.VariableFeatures.FEATURE_MAP_VALUES, testMap}, {Graph.Features.VariableFeatures.FEATURE_MIXED_LIST_VALUES, mixedList}, {Graph.Features.VariableFeatures.FEATURE_BOOLEAN_ARRAY_VALUES, new boolean[]{true, false}}, {Graph.Features.VariableFeatures.FEATURE_DOUBLE_ARRAY_VALUES, new double[]{1d, 2d}}, {Graph.Features.VariableFeatures.FEATURE_FLOAT_ARRAY_VALUES, new float[]{1f, 2f}}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_ARRAY_VALUES, new int[]{1, 2}}, {Graph.Features.VariableFeatures.FEATURE_LONG_ARRAY_VALUES, new long[]{1l, 2l}}, {Graph.Features.VariableFeatures.FEATURE_STRING_ARRAY_VALUES, new String[]{"try1", "try2"}}, {Graph.Features.VariableFeatures.FEATURE_INTEGER_ARRAY_VALUES, new int[1]}, {Graph.Features.VariableFeatures.FEATURE_SERIALIZABLE_VALUES, new MockSerializable("testing")}, {Graph.Features.VariableFeatures.FEATURE_STRING_VALUES, "short string"}, {Graph.Features.VariableFeatures.FEATURE_UNIFORM_LIST_VALUES, uniformIntegerList}, {Graph.Features.VariableFeatures.FEATURE_UNIFORM_LIST_VALUES, uniformStringList} }); } @Parameterized.Parameter(value = 0) public String featureName; @Parameterized.Parameter(value = 1) public Object value; @Test @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = FEATURE_VARIABLES) public void shouldSetValueOnGraph() throws Exception { assumeThat(graph.features().supports(Graph.Features.VariableFeatures.class, featureName), is(true)); final Graph.Variables variables = graph.variables(); variables.set("aKey", value); if (value instanceof Map) tryCommit(graph, graph -> { final Map map = variables.<Map>get("aKey").get(); assertEquals(((Map) value).size(), map.size()); ((Map) value).keySet().forEach(k -> assertEquals(((Map) value).get(k), map.get(k))); }); else if (value instanceof List) tryCommit(graph, graph -> { final List l = variables.<List>get("aKey").get(); assertEquals(((List) value).size(), l.size()); for (int ix = 0; ix < ((List) value).size(); ix++) { assertEquals(((List) value).get(ix), l.get(ix)); } }); else if (value instanceof MockSerializable) tryCommit(graph, graph -> { final MockSerializable mock = variables.<MockSerializable>get("aKey").get(); assertEquals(((MockSerializable) value).getTestField(), mock.getTestField()); }); else if (value instanceof boolean[]) tryCommit(graph, graph -> { final boolean[] l = variables.<boolean[]>get("aKey").get(); assertEquals(((boolean[]) value).length, l.length); for (int ix = 0; ix < ((boolean[]) value).length; ix++) { assertEquals(((boolean[]) value)[ix], l[ix]); } }); else if (value instanceof double[]) tryCommit(graph, graph -> { final double[] l = variables.<double[]>get("aKey").get(); assertEquals(((double[]) value).length, l.length); for (int ix = 0; ix < ((double[]) value).length; ix++) { assertEquals(((double[]) value)[ix], l[ix], 0.0d); } }); else if (value instanceof float[]) tryCommit(graph, graph -> { final float[] l = variables.<float[]>get("aKey").get(); assertEquals(((float[]) value).length, l.length); for (int ix = 0; ix < ((float[]) value).length; ix++) { assertEquals(((float[]) value)[ix], l[ix], 0.0f); } }); else if (value instanceof int[]) tryCommit(graph, graph -> { final int[] l = variables.<int[]>get("aKey").get(); assertEquals(((int[]) value).length, l.length); for (int ix = 0; ix < ((int[]) value).length; ix++) { assertEquals(((int[]) value)[ix], l[ix]); } }); else if (value instanceof long[]) tryCommit(graph, graph -> { final long[] l = variables.<long[]>get("aKey").get(); assertEquals(((long[]) value).length, l.length); for (int ix = 0; ix < ((long[]) value).length; ix++) { assertEquals(((long[]) value)[ix], l[ix]); } }); else if (value instanceof String[]) tryCommit(graph, graph -> { final String[] l = variables.<String[]>get("aKey").get(); assertEquals(((String[]) value).length, l.length); for (int ix = 0; ix < ((String[]) value).length; ix++) { assertEquals(((String[]) value)[ix], l[ix]); } }); else tryCommit(graph, graph -> assertEquals(value, variables.get("aKey").get())); } } }