Consistent naming for TinkerIoRegistry Now that there are multiple versions of GraphSON/Gryo the naming of registries should reflect the version number. This is a non-breaking change. The old TinkerIoRegistry is just deprecated. CTR
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/802ff9f6 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/802ff9f6 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/802ff9f6 Branch: refs/heads/TINKERPOP-1602 Commit: 802ff9f69b48b4aa56a85c586ed3c58844a89c9f Parents: 3bb177f Author: Stephen Mallette <sp...@genoprime.com> Authored: Tue Jan 17 19:04:03 2017 -0500 Committer: Stephen Mallette <sp...@genoprime.com> Committed: Tue Jan 17 19:04:03 2017 -0500 ---------------------------------------------------------------------- CHANGELOG.asciidoc | 1 + gremlin-console/conf/remote-objects.yaml | 2 +- .../tinkergraph/structure/TinkerGraph.java | 2 +- .../tinkergraph/structure/TinkerIoRegistry.java | 2 + .../structure/TinkerIoRegistryV1d0.java | 263 +++++++++++++++++++ .../structure/TinkerIoRegistryV2d0.java | 5 +- .../TinkerGraphGryoSerializerTest.java | 1 - .../TinkerGraphGryoSerializerV1d0Test.java | 83 ++++++ .../TinkerGraphGryoSerializerV2d0Test.java | 80 ++++++ .../tinkergraph/structure/TinkerGraphTest.java | 30 ++- 10 files changed, 463 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/CHANGELOG.asciidoc ---------------------------------------------------------------------- diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 42088dd..9471b9f 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima TinkerPop 3.2.4 (Release Date: NOT OFFICIALLY RELEASED YET) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Deprecated `TinkerIoRegistry` replacing it with the more consistently named `TinkerIoRegistryV1d0`. * Made error messaging more consistent during result iteration timeouts in Gremlin Server. * `PathRetractionStrategy` does not add a `NoOpBarrierStep` to the end of local children as its wasted computation in 99% of traversals. * Fixed a bug in `AddVertexStartStep` where if a side-effect was being used in the parametrization, an NPE occurred. http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/gremlin-console/conf/remote-objects.yaml ---------------------------------------------------------------------- diff --git a/gremlin-console/conf/remote-objects.yaml b/gremlin-console/conf/remote-objects.yaml index f507f4e..d1909fc 100644 --- a/gremlin-console/conf/remote-objects.yaml +++ b/gremlin-console/conf/remote-objects.yaml @@ -38,4 +38,4 @@ hosts: [localhost] port: 8182 serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, - config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistry] }} \ No newline at end of file + config: { ioRegistries: [org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0] }} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java index 48f4d3d..fa8c62b 100644 --- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java +++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraph.java @@ -233,7 +233,7 @@ public final class TinkerGraph implements Graph { @Override public <I extends Io> I io(final Io.Builder<I> builder) { - return (I) builder.graph(this).onMapper(mapper -> mapper.addRegistry(TinkerIoRegistry.instance())).create(); + return (I) builder.graph(this).onMapper(mapper -> mapper.addRegistry(TinkerIoRegistryV1d0.instance())).create(); } @Override http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistry.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistry.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistry.java index 66bdba1..40720e5 100644 --- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistry.java +++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistry.java @@ -70,7 +70,9 @@ import java.util.Map; * custom data class like a "geographic point". * * @author Stephen Mallette (http://stephen.genoprime.com) + * @deprecated As of release 3.2.4, replaced by {@link TinkerIoRegistryV1d0}. */ +@Deprecated public final class TinkerIoRegistry extends AbstractIoRegistry { private static final TinkerIoRegistry INSTANCE = new TinkerIoRegistry(); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java new file mode 100644 index 0000000..277bedc --- /dev/null +++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV1d0.java @@ -0,0 +1,263 @@ +/* + * 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.tinkergraph.structure; + +import org.apache.commons.configuration.BaseConfiguration; +import org.apache.commons.configuration.Configuration; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry; +import org.apache.tinkerpop.gremlin.structure.io.GraphReader; +import org.apache.tinkerpop.gremlin.structure.io.GraphWriter; +import org.apache.tinkerpop.gremlin.structure.io.IoRegistry; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONUtil; +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoIo; +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoReader; +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoWriter; +import org.apache.tinkerpop.gremlin.structure.util.Attachable; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge; +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex; +import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator; +import org.apache.tinkerpop.shaded.jackson.core.JsonParser; +import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException; +import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext; +import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider; +import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer; +import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer; +import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule; +import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer; +import org.apache.tinkerpop.shaded.kryo.Kryo; +import org.apache.tinkerpop.shaded.kryo.Serializer; +import org.apache.tinkerpop.shaded.kryo.io.Input; +import org.apache.tinkerpop.shaded.kryo.io.Output; +import org.javatuples.Pair; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +/** + * An implementation of the {@link IoRegistry} interface that provides serializers with custom configurations for + * implementation specific classes that might need to be serialized. This registry allows a {@link TinkerGraph} to + * be serialized directly which is useful for moving small graphs around on the network. + * <p/> + * Most providers need not implement this kind of custom serializer as they will deal with much larger graphs that + * wouldn't be practical to serialize in this fashion. This is a bit of a special case for TinkerGraph given its + * in-memory status. Typical implementations would create serializers for a complex vertex identifier or a + * custom data class like a "geographic point". + * + * @author Stephen Mallette (http://stephen.genoprime.com) + */ +public final class TinkerIoRegistryV1d0 extends AbstractIoRegistry { + + private static final TinkerIoRegistryV1d0 INSTANCE = new TinkerIoRegistryV1d0(); + + private TinkerIoRegistryV1d0() { + register(GryoIo.class, TinkerGraph.class, new TinkerGraphGryoSerializer()); + register(GraphSONIo.class, null, new TinkerModule()); + } + + public static TinkerIoRegistryV1d0 instance() { + return INSTANCE; + } + + /** + * Provides a method to serialize an entire {@link TinkerGraph} into itself for Gryo. This is useful when + * shipping small graphs around through Gremlin Server. Reuses the existing Kryo instance for serialization. + */ + final static class TinkerGraphGryoSerializer extends Serializer<TinkerGraph> { + @Override + public void write(final Kryo kryo, final Output output, final TinkerGraph graph) { + try (final ByteArrayOutputStream stream = new ByteArrayOutputStream()) { + GryoWriter.build().mapper(() -> kryo).create().writeGraph(stream, graph); + final byte[] bytes = stream.toByteArray(); + output.writeInt(bytes.length); + output.write(bytes); + } catch (Exception io) { + throw new RuntimeException(io); + } + } + + @Override + public TinkerGraph read(final Kryo kryo, final Input input, final Class<TinkerGraph> tinkerGraphClass) { + final Configuration conf = new BaseConfiguration(); + conf.setProperty("gremlin.tinkergraph.defaultVertexPropertyCardinality", "list"); + final TinkerGraph graph = TinkerGraph.open(conf); + final int len = input.readInt(); + final byte[] bytes = input.readBytes(len); + try (final ByteArrayInputStream stream = new ByteArrayInputStream(bytes)) { + GryoReader.build().mapper(() -> kryo).create().readGraph(stream, graph); + } catch (Exception io) { + throw new RuntimeException(io); + } + + return graph; + } + } + + /** + * Provides a method to serialize an entire {@link TinkerGraph} into itself for GraphSON. This is useful when + * shipping small graphs around through Gremlin Server. + */ + final static class TinkerModule extends SimpleModule { + public TinkerModule() { + super("tinkergraph-1.0"); + addSerializer(TinkerGraph.class, new TinkerGraphJacksonSerializer()); + addDeserializer(TinkerGraph.class, new TinkerGraphJacksonDeserializer()); + } + } + + /** + * Serializes the graph into an edge list format. Edge list is a better choices than adjacency list (which is + * typically standard from the {@link GraphReader} and {@link GraphWriter} perspective) in this case because + * the use case for this isn't around massive graphs. The use case is for "small" subgraphs that are being + * shipped over the wire from Gremlin Server. Edge list format is a bit easier for non-JVM languages to work + * with as a format and doesn't require a cache for loading (as vertex labels are not serialized in adjacency + * list). + */ + final static class TinkerGraphJacksonSerializer extends StdSerializer<TinkerGraph> { + + public TinkerGraphJacksonSerializer() { + super(TinkerGraph.class); + } + + @Override + public void serialize(final TinkerGraph graph, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) + throws IOException { + jsonGenerator.writeStartObject(); + + jsonGenerator.writeFieldName(GraphSONTokens.VERTICES); + jsonGenerator.writeStartArray(); + + final Iterator<Vertex> vertices = graph.vertices(); + while (vertices.hasNext()) { + serializerProvider.defaultSerializeValue(vertices.next(), jsonGenerator); + } + + jsonGenerator.writeEndArray(); + + jsonGenerator.writeFieldName(GraphSONTokens.EDGES); + jsonGenerator.writeStartArray(); + + final Iterator<Edge> edges = graph.edges(); + while (edges.hasNext()) { + serializerProvider.defaultSerializeValue(edges.next(), jsonGenerator); + } + + jsonGenerator.writeEndArray(); + + jsonGenerator.writeEndObject(); + } + + @Override + public void serializeWithType(final TinkerGraph graph, final JsonGenerator jsonGenerator, + final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException { + jsonGenerator.writeStartObject(); + jsonGenerator.writeStringField(GraphSONTokens.CLASS, TinkerGraph.class.getName()); + + jsonGenerator.writeFieldName(GraphSONTokens.VERTICES); + jsonGenerator.writeStartArray(); + jsonGenerator.writeString(ArrayList.class.getName()); + jsonGenerator.writeStartArray(); + + final Iterator<Vertex> vertices = graph.vertices(); + while (vertices.hasNext()) { + GraphSONUtil.writeWithType(vertices.next(), jsonGenerator, serializerProvider, typeSerializer); + } + + jsonGenerator.writeEndArray(); + jsonGenerator.writeEndArray(); + + jsonGenerator.writeFieldName(GraphSONTokens.EDGES); + jsonGenerator.writeStartArray(); + jsonGenerator.writeString(ArrayList.class.getName()); + jsonGenerator.writeStartArray(); + + final Iterator<Edge> edges = graph.edges(); + while (edges.hasNext()) { + GraphSONUtil.writeWithType(edges.next(), jsonGenerator, serializerProvider, typeSerializer); + } + + jsonGenerator.writeEndArray(); + jsonGenerator.writeEndArray(); + + jsonGenerator.writeEndObject(); + } + } + + /** + * Deserializes the edge list format. + */ + static class TinkerGraphJacksonDeserializer extends StdDeserializer<TinkerGraph> { + public TinkerGraphJacksonDeserializer() { + super(TinkerGraph.class); + } + + @Override + public TinkerGraph deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + final Configuration conf = new BaseConfiguration(); + conf.setProperty("gremlin.tinkergraph.defaultVertexPropertyCardinality", "list"); + final TinkerGraph graph = TinkerGraph.open(conf); + + final List<Map<String, Object>> edges; + final List<Map<String, Object>> vertices; + if (!jsonParser.getCurrentToken().isStructStart()) { + if (!jsonParser.getCurrentName().equals(GraphSONTokens.VERTICES)) + throw new IOException(String.format("Expected a '%s' key", GraphSONTokens.VERTICES)); + + jsonParser.nextToken(); + vertices = (List<Map<String, Object>>) deserializationContext.readValue(jsonParser, ArrayList.class); + jsonParser.nextToken(); + + if (!jsonParser.getCurrentName().equals(GraphSONTokens.EDGES)) + throw new IOException(String.format("Expected a '%s' key", GraphSONTokens.EDGES)); + + jsonParser.nextToken(); + edges = (List<Map<String, Object>>) deserializationContext.readValue(jsonParser, ArrayList.class); + } else { + final Map<String, Object> graphData = deserializationContext.readValue(jsonParser, HashMap.class); + vertices = (List<Map<String,Object>>) graphData.get(GraphSONTokens.VERTICES); + edges = (List<Map<String,Object>>) graphData.get(GraphSONTokens.EDGES); + } + + for (Map<String, Object> vertexData : vertices) { + final DetachedVertex detached = new DetachedVertex(vertexData.get(GraphSONTokens.ID), + vertexData.get(GraphSONTokens.LABEL).toString(), (Map<String,Object>) vertexData.get(GraphSONTokens.PROPERTIES)); + detached.attach(Attachable.Method.getOrCreate(graph)); + } + + for (Map<String, Object> edgeData : edges) { + final DetachedEdge detached = new DetachedEdge(edgeData.get(GraphSONTokens.ID), + edgeData.get(GraphSONTokens.LABEL).toString(), (Map<String,Object>) edgeData.get(GraphSONTokens.PROPERTIES), + Pair.with(edgeData.get(GraphSONTokens.OUT), edgeData.get(GraphSONTokens.OUT_LABEL).toString()), + Pair.with(edgeData.get(GraphSONTokens.IN), edgeData.get(GraphSONTokens.IN_LABEL).toString())); + detached.attach(Attachable.Method.getOrCreate(graph)); + } + + return graph; + } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java index 32446a5..727931c 100644 --- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java +++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java @@ -23,6 +23,7 @@ import org.apache.commons.configuration.Configuration; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry; +import org.apache.tinkerpop.gremlin.structure.io.IoRegistry; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONUtil; @@ -56,8 +57,8 @@ import java.util.List; import java.util.Map; /** - * An implementation of the {@link org.apache.tinkerpop.gremlin.structure.io.IoRegistry} interface that provides serializers with custom configurations for - * implementation specific classes that might need to be serialized. This registry allows a {@link org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph} to + * An implementation of the {@link IoRegistry} interface that provides serializers with custom configurations for + * implementation specific classes that might need to be serialized. This registry allows a {@link TinkerGraph} to * be serialized directly which is useful for moving small graphs around on the network. * <p/> * Most providers need not implement this kind of custom serializer as they will deal with much larger graphs that http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerTest.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerTest.java index 3decd5f..703d127 100644 --- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerTest.java +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerTest.java @@ -57,7 +57,6 @@ public class TinkerGraphGryoSerializerTest { @Before public void setUp() throws Exception { - when(kryo.getRegistration((Class) any())).thenReturn(registration); when(input.readBytes(anyInt())).thenReturn(Arrays.copyOf(GryoMapper.HEADER, 100)); } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java new file mode 100644 index 0000000..2233d53 --- /dev/null +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV1d0Test.java @@ -0,0 +1,83 @@ +/* + * 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.tinkergraph.structure; + +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoMapper; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistry; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV1d0; +import org.apache.tinkerpop.shaded.kryo.Kryo; +import org.apache.tinkerpop.shaded.kryo.Registration; +import org.apache.tinkerpop.shaded.kryo.io.Input; +import org.apache.tinkerpop.shaded.kryo.io.Output; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.Arrays; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Unit tests for {@link TinkerIoRegistry.TinkerGraphGryoSerializer} + */ +@RunWith(MockitoJUnitRunner.class) +public class TinkerGraphGryoSerializerV1d0Test { + + @Mock + private Kryo kryo; + @Mock + private Registration registration; + @Mock + private Output output; + @Mock + private Input input; + + private TinkerGraph graph = TinkerGraph.open(); + private TinkerIoRegistryV1d0.TinkerGraphGryoSerializer serializer = new TinkerIoRegistryV1d0.TinkerGraphGryoSerializer(); + + @Before + public void setUp() throws Exception { + when(kryo.getRegistration((Class) any())).thenReturn(registration); + when(input.readBytes(anyInt())).thenReturn(Arrays.copyOf(GryoMapper.HEADER, 100)); + } + + @Test + public void shouldVerifyKryoUsedForWrite() throws Exception { + serializer.write(kryo, output, graph); + verify(kryo, atLeastOnce()).getRegistration((Class) any()); + } + + @Test + public void shouldVerifyKryoUsedForRead() throws Exception { + // Not possible to mock an entire deserialization so just verify the same kryo instances are being used + try { + serializer.read(kryo, input, TinkerGraph.class); + } catch (RuntimeException ex) { + verify(kryo, atLeastOnce()).readObject(any(), any()); + verify(kryo, atLeastOnce()).readClassAndObject(any()); + } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java new file mode 100644 index 0000000..7d2a5e3 --- /dev/null +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphGryoSerializerV2d0Test.java @@ -0,0 +1,80 @@ +/* + * 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.tinkergraph.structure; + +import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoMapper; +import org.apache.tinkerpop.shaded.kryo.Kryo; +import org.apache.tinkerpop.shaded.kryo.Registration; +import org.apache.tinkerpop.shaded.kryo.io.Input; +import org.apache.tinkerpop.shaded.kryo.io.Output; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.Arrays; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Unit tests for {@link TinkerIoRegistry.TinkerGraphGryoSerializer} + */ +@RunWith(MockitoJUnitRunner.class) +public class TinkerGraphGryoSerializerV2d0Test { + + @Mock + private Kryo kryo; + @Mock + private Registration registration; + @Mock + private Output output; + @Mock + private Input input; + + private TinkerGraph graph = TinkerGraph.open(); + private TinkerIoRegistryV2d0.TinkerGraphGryoSerializer serializer = new TinkerIoRegistryV2d0.TinkerGraphGryoSerializer(); + + @Before + public void setUp() throws Exception { + when(kryo.getRegistration((Class) any())).thenReturn(registration); + when(input.readBytes(anyInt())).thenReturn(Arrays.copyOf(GryoMapper.HEADER, 100)); + } + + @Test + public void shouldVerifyKryoUsedForWrite() throws Exception { + serializer.write(kryo, output, graph); + verify(kryo, atLeastOnce()).getRegistration((Class) any()); + } + + @Test + public void shouldVerifyKryoUsedForRead() throws Exception { + // Not possible to mock an entire deserialization so just verify the same kryo instances are being used + try { + serializer.read(kryo, input, TinkerGraph.class); + } catch (RuntimeException ex) { + verify(kryo, atLeastOnce()).readObject(any(), any()); + verify(kryo, atLeastOnce()).readClassAndObject(any()); + } + } +} http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/802ff9f6/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java ---------------------------------------------------------------------- diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java index 9de9a70..a85b0ee 100644 --- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java +++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphTest.java @@ -546,7 +546,35 @@ public class TinkerGraphTest { final ArrayList<Color> colorList = new ArrayList<>(Arrays.asList(Color.RED, Color.GREEN)); final Supplier<ClassResolver> classResolver = new CustomClassResolverSupplier(); - final GryoMapper mapper = GryoMapper.build().addRegistry(TinkerIoRegistry.instance()).classResolver(classResolver).create(); + final GryoMapper mapper = GryoMapper.build().addRegistry(TinkerIoRegistryV1d0.instance()).classResolver(classResolver).create(); + final Kryo kryo = mapper.createMapper(); + try (final ByteArrayOutputStream stream = new ByteArrayOutputStream()) { + final Output out = new Output(stream); + + kryo.writeObject(out, colorList); + out.flush(); + final byte[] b = stream.toByteArray(); + + try (final InputStream inputStream = new ByteArrayInputStream(b)) { + final Input input = new Input(inputStream); + final List m = kryo.readObject(input, ArrayList.class); + final TinkerGraph readX = (TinkerGraph) m.get(0); + assertEquals(104, IteratorUtils.count(readX.vertices())); + assertEquals(102, IteratorUtils.count(readX.edges())); + } + } + } + + @Test + public void shouldSerializeWithColorClassResolverToTinkerGraphUsingDeprecatedTinkerIoRegistry() throws Exception { + final Map<String,Color> colors = new HashMap<>(); + colors.put("red", Color.RED); + colors.put("green", Color.GREEN); + + final ArrayList<Color> colorList = new ArrayList<>(Arrays.asList(Color.RED, Color.GREEN)); + + final Supplier<ClassResolver> classResolver = new CustomClassResolverSupplier(); + final GryoMapper mapper = GryoMapper.build().addRegistry(TinkerIoRegistryV1d0.instance()).classResolver(classResolver).create(); final Kryo kryo = mapper.createMapper(); try (final ByteArrayOutputStream stream = new ByteArrayOutputStream()) { final Output out = new Output(stream);