blob: bf1ddcbe21462294ee8468265c5761018b4b324d [file] [log] [blame]
/*
* 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.driver.ser;
import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo;
import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerationException;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
import org.apache.tinkerpop.shaded.jackson.databind.JsonNode;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule;
import org.apache.tinkerpop.shaded.jackson.databind.node.NullNode;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.util.StdDateFormat;
import org.junit.Test;
import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
/**
* These tests focus on message serialization and not "result" serialization as test specific to results (e.g.
* vertices, edges, annotated values, etc.) are handled in the IO packages.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
public class GraphSONMessageSerializerV1d0Test {
public static final GraphSONMessageSerializerV1d0 SERIALIZER = new GraphSONMessageSerializerV1d0();
private static final RequestMessage msg = RequestMessage.build("op")
.overrideRequestId(UUID.fromString("2D62161B-9544-4F39-AF44-62EC49F9A595")).create();
private static final ObjectMapper mapper = new ObjectMapper();
@Test
public void shouldConfigureIoRegistry() throws Exception {
final GraphSONMessageSerializerV1d0 serializer = new GraphSONMessageSerializerV1d0();
final Map<String, Object> config = new HashMap<String, Object>() {{
put(GryoMessageSerializerV1d0.TOKEN_IO_REGISTRIES, Arrays.asList(ColorIoRegistry.class.getName()));
}};
serializer.configure(config, null);
final ResponseMessage toSerialize = ResponseMessage.build(UUID.fromString("2D62161B-9544-4F39-AF44-62EC49F9A595"))
.result(Color.RED).create();
final String results = serializer.serializeResponseAsString(toSerialize);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertThat(json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA).booleanValue(), is(true));
}
@Test
public void shouldSerializeToJsonNullResultReturnsNull() throws Exception {
final ResponseMessage message = ResponseMessage.build(msg).create();
final String results = SERIALIZER.serializeResponseAsString(message);
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.path(SerTokens.TOKEN_REQUEST).asText());
assertEquals(NullNode.getInstance(), json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA));
}
@Test
public void shouldSerializeToJsonIterable() throws Exception {
final ArrayList<FunObject> funList = new ArrayList<>();
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertEquals(2, converted.size());
assertEquals("x", converted.get(0).asText());
assertEquals("y", converted.get(1).asText());
}
@Test
public void shouldSerializeToJsonIterator() throws Exception {
final ArrayList<FunObject> funList = new ArrayList<>();
funList.add(new FunObject("x"));
funList.add(new FunObject("y"));
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertEquals(2, converted.size());
assertEquals("x", converted.get(0).asText());
assertEquals("y", converted.get(1).asText());
}
@Test
public void shouldSerializeToJsonIteratorNullElement() throws Exception {
final ArrayList<FunObject> funList = new ArrayList<>();
funList.add(new FunObject("x"));
funList.add(null);
funList.add(new FunObject("y"));
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(funList.iterator()).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertEquals(3, converted.size());
assertEquals("x", converted.get(0).asText());
assertEquals(NullNode.getInstance(), converted.get(1));
assertEquals("y", converted.get(2).asText());
}
@Test
public void shouldSerializeToJsonMap() throws Exception {
final Map<String, Object> map = new HashMap<>();
final Map<String, String> innerMap = new HashMap<>();
innerMap.put("a", "b");
map.put("x", new FunObject("x"));
map.put("y", "some");
map.put("z", innerMap);
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode jsonObject = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(jsonObject);
assertEquals("some", jsonObject.get("y").asText());
assertEquals("x", jsonObject.get("x").asText());
final JsonNode innerJsonObject = jsonObject.get("z");
assertNotNull(innerJsonObject);
assertEquals("b", innerJsonObject.get("a").asText());
}
@Test
public void shouldShouldSerializeMapEntries() throws Exception {
final Graph graph = TinkerGraph.open();
final Vertex v1 = graph.addVertex();
final Date d = new Date();
final Map<Object, Object> map = new HashMap<>();
map.put("x", 1);
map.put(v1, 100);
map.put(d, "test");
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(IteratorUtils.asList(map)).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode jsonObject = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
jsonObject.elements().forEachRemaining(e -> {
if (e.has("x"))
assertEquals(1, e.get("x").asInt());
else if (e.has(v1.id().toString()))
assertEquals(100, e.get(v1.id().toString()).asInt());
else if (e.has(StdDateFormat.instance.format(d)))
assertEquals("test", e.get(StdDateFormat.instance.format(d)).asText());
else
fail("Map entries contains a key that is not part of what was serialized");
});
}
@Test
public void shouldSerializeEdge() throws Exception {
final Graph g = TinkerGraph.open();
final Vertex v1 = g.addVertex();
final Vertex v2 = g.addVertex();
final Edge e = v1.addEdge("test", v2);
e.property("abc", 123);
final Iterable<Edge> iterable = IteratorUtils.list(g.edges());
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(converted);
assertEquals(1, converted.size());
final JsonNode edgeAsJson = converted.get(0);
assertNotNull(edgeAsJson);
assertEquals(((Long) e.id()).intValue(), edgeAsJson.get(GraphSONTokens.ID).asLong()); // lossy
assertEquals(((Long) v1.id()).intValue(), edgeAsJson.get(GraphSONTokens.OUT).asLong());// lossy
assertEquals(((Long) v2.id()).intValue(), edgeAsJson.get(GraphSONTokens.IN).asLong()); // lossy
assertEquals(e.label(), edgeAsJson.get(GraphSONTokens.LABEL).asText());
assertEquals(GraphSONTokens.EDGE, edgeAsJson.get(GraphSONTokens.TYPE).asText());
final JsonNode properties = edgeAsJson.get(GraphSONTokens.PROPERTIES);
assertNotNull(properties);
assertEquals(123, properties.get("abc").asInt());
}
@Test
public void shouldSerializeEdgeProperty() throws Exception {
final Graph g = TinkerGraph.open();
final Vertex v1 = g.addVertex();
final Vertex v2 = g.addVertex();
final Edge e = v1.addEdge("test", v2);
e.property("abc", 123);
final Iterable<Property<Object>> iterable = IteratorUtils.list(e.properties("abc"));
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(converted);
assertEquals(1, converted.size());
final JsonNode propertyAsJson = converted.get(0);
assertNotNull(propertyAsJson);
assertEquals(123, propertyAsJson.get("value").asInt());
}
@Test
public void shouldSerializeToJsonIteratorWithEmbeddedMap() throws Exception {
final Graph g = TinkerGraph.open();
final Vertex v = g.addVertex();
final Map<String, Object> map = new HashMap<>();
map.put("x", 500);
map.put("y", "some");
final ArrayList<Object> friends = new ArrayList<>();
friends.add("x");
friends.add(5);
friends.add(map);
v.property(VertexProperty.Cardinality.single, "friends", friends);
final Iterable iterable = IteratorUtils.list(g.vertices());
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(iterable).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(converted);
assertEquals(1, converted.size());
final JsonNode vertexAsJson = converted.get(0);
assertNotNull(vertexAsJson);
final JsonNode properties = vertexAsJson.get(GraphSONTokens.PROPERTIES);
assertNotNull(properties);
assertEquals(1, properties.size());
final JsonNode friendProperties = properties.get("friends");
assertEquals(1, friendProperties.size());
final JsonNode friendsProperty = friendProperties.get(0);
assertNotNull(friendsProperty);
assertEquals(3, friends.size());
final String object1 = friendsProperty.get(GraphSONTokens.VALUE).get(0).asText();
assertEquals("x", object1);
final int object2 = friendsProperty.get(GraphSONTokens.VALUE).get(1).asInt();
assertEquals(5, object2);
final JsonNode object3 = friendsProperty.get(GraphSONTokens.VALUE).get(2);
assertEquals(500, object3.get("x").asInt());
assertEquals("some", object3.get("y").asText());
}
@Test
public void shouldSerializeToJsonMapWithElementForKey() throws Exception {
final TinkerGraph graph = TinkerFactory.createClassic();
final GraphTraversalSource g = graph.traversal();
final Map<Vertex, Integer> map = new HashMap<>();
map.put(g.V().has("name", "marko").next(), 1000);
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(map).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(converted);
// with no embedded types the key (which is a vertex) simply serializes out to an id
// {"result":{"1":1000},"code":200,"requestId":"2d62161b-9544-4f39-af44-62ec49f9a595","type":0}
assertEquals(1000, converted.get("1").asInt());
}
@Test
public void shouldDeserializeRequestNicelyWithNoArgs() throws Exception {
final UUID request = UUID.fromString("011CFEE9-F640-4844-AC93-034448AC0E80");
final RequestMessage m = SERIALIZER.deserializeRequest(String.format("{\"requestId\":\"%s\",\"op\":\"eval\"}", request));
assertEquals(request, m.getRequestId());
assertEquals("eval", m.getOp());
assertNotNull(m.getArgs());
assertEquals(0, m.getArgs().size());
}
@Test
public void shouldDeserializeRequestNicelyWithArgs() throws Exception {
final UUID request = UUID.fromString("011CFEE9-F640-4844-AC93-034448AC0E80");
final RequestMessage m = SERIALIZER.deserializeRequest(String.format("{\"requestId\":\"%s\",\"op\":\"eval\",\"args\":{\"x\":\"y\"}}", request));
assertEquals(request, m.getRequestId());
assertEquals("eval", m.getOp());
assertNotNull(m.getArgs());
assertEquals("y", m.getArgs().get("x"));
}
@Test(expected = SerializationException.class)
public void shouldDeserializeRequestParseMessage() throws Exception {
SERIALIZER.deserializeRequest("{\"requestId\":\"%s\",\"op\":\"eval\",\"args\":{\"x\":\"y\"}}");
}
@Test
public void shouldSerializeFullResponseMessage() throws Exception {
final UUID id = UUID.randomUUID();
final Map<String, Object> metaData = new HashMap<>();
metaData.put("test", "this");
metaData.put("one", 1);
final Map<String, Object> attributes = new HashMap<>();
attributes.put("test", "that");
attributes.put("two", 2);
final ResponseMessage response = ResponseMessage.build(id)
.responseMetaData(metaData)
.code(ResponseStatusCode.SUCCESS)
.result("some-result")
.statusAttributes(attributes)
.statusMessage("worked")
.create();
final String results = SERIALIZER.serializeResponseAsString(response);
final ResponseMessage deserialized = SERIALIZER.deserializeResponse(results);
assertEquals(id, deserialized.getRequestId());
assertEquals("this", deserialized.getResult().getMeta().get("test"));
assertEquals(1, deserialized.getResult().getMeta().get("one"));
assertEquals("some-result", deserialized.getResult().getData());
assertEquals("that", deserialized.getStatus().getAttributes().get("test"));
assertEquals(2, deserialized.getStatus().getAttributes().get("two"));
assertEquals(ResponseStatusCode.SUCCESS.getValue(), deserialized.getStatus().getCode().getValue());
assertEquals("worked", deserialized.getStatus().getMessage());
}
@Test
public void shouldSerializeToJsonTree() throws Exception {
final TinkerGraph graph = TinkerFactory.createClassic();
final GraphTraversalSource g = graph.traversal();
final Tree t = g.V(1).out().properties("name").tree().next();
final String results = SERIALIZER.serializeResponseAsString(ResponseMessage.build(msg).result(t).create());
final JsonNode json = mapper.readTree(results);
assertNotNull(json);
assertEquals(msg.getRequestId().toString(), json.get(SerTokens.TOKEN_REQUEST).asText());
final JsonNode converted = json.get(SerTokens.TOKEN_RESULT).get(SerTokens.TOKEN_DATA);
assertNotNull(converted);
//check the first object and it's properties
assertEquals(1, converted.get("1").get("key").get("id").asInt());
assertEquals("marko", converted.get("1").get("key").get("properties").get("name").get(0).get("value").asText());
//check objects tree structure
//check Vertex property
assertEquals("vadas", converted.get("1")
.get("value")
.get("2")
.get("value")
.get("3").get("key").get("value").asText());
assertEquals("name", converted.get("1")
.get("value")
.get("2")
.get("value")
.get("3").get("key").get("label").asText());
// check subitem
assertEquals("lop", converted.get("1")
.get("value")
.get("3")
.get("key")
.get("properties").get("name").get(0).get("value").asText());
}
private class FunObject {
private String val;
public FunObject(String val) {
this.val = val;
}
public String toString() {
return this.val;
}
}
public static class ColorIoRegistry extends AbstractIoRegistry {
public ColorIoRegistry() {
register(GraphSONIo.class, null, new ColorSimpleModule());
}
}
public static class ColorSimpleModule extends SimpleModule {
public ColorSimpleModule() {
super("color-fun");
addSerializer(Color.class, new ColorSerializer());
}
}
public static class ColorSerializer extends StdSerializer<Color> {
public ColorSerializer() {
super(Color.class);
}
@Override
public void serialize(final Color color, final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider) throws IOException, JsonGenerationException {
jsonGenerator.writeBoolean(color.equals(Color.RED));
}
}
}