blob: 6c277708dd3df5cc6de5b25ca7d3794219430167 [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.structure.io.graphson;
import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
import org.apache.tinkerpop.gremlin.util.function.Lambda;
import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.MonthDay;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Period;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__;
import static org.hamcrest.Matchers.either;
import static org.hamcrest.core.IsNot.not;
import static org.hamcrest.core.StringStartsWith.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeThat;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
@RunWith(Parameterized.class)
public class GraphSONMapperEmbeddedTypeTest extends AbstractGraphSONTest {
@Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"v1", GraphSONMapper.build().version(GraphSONVersion.V1_0).typeInfo(TypeInfo.PARTIAL_TYPES).create().createMapper()},
{"v2", GraphSONMapper.build().version(GraphSONVersion.V2_0)
.addCustomModule(GraphSONXModuleV2d0.build().create(false))
.typeInfo(TypeInfo.PARTIAL_TYPES).create().createMapper()},
{"v3", GraphSONMapper.build().version(GraphSONVersion.V3_0)
.addCustomModule(GraphSONXModuleV3d0.build().create(false))
.typeInfo(TypeInfo.PARTIAL_TYPES).create().createMapper()}
});
}
@Parameterized.Parameter(1)
public ObjectMapper mapper;
@Parameterized.Parameter(0)
public String version;
@Test
public void shouldHandleTraversalExplanation() throws Exception {
assumeThat(version, not(startsWith("v1")));
final TraversalExplanation o = __().out().outV().outE().explain();
final TraversalExplanation deser = serializeDeserialize(mapper, o, TraversalExplanation.class);
assertEquals(o.prettyPrint(), deser.prettyPrint());
}
@Test
public void shouldHandleNumberConstants() throws Exception {
assumeThat(version, not(startsWith("v1")));
final List<Object> o = new ArrayList<>();
o.add(123.321d);
o.add(Double.NaN);
o.add(Double.NEGATIVE_INFINITY);
o.add(Double.POSITIVE_INFINITY);
assertEquals(o, serializeDeserialize(mapper, o, List.class));
}
@Test
public void shouldHandleMap() throws Exception {
assumeThat(version, startsWith("v3"));
final Map<Object,Object> o = new LinkedHashMap<>();
o.put("string key", "string value");
o.put(1, 1);
o.put(1L, 1L);
final List<Object> l = Arrays.asList("test", 1, 5L);
o.put(l, "crazy");
assertEquals(o, serializeDeserialize(mapper, o, Map.class));
}
@Test
public void shouldHandleList() throws Exception {
assumeThat(version, startsWith("v3"));
final List<Object> o = new ArrayList<>();
o.add("test");
o.add(1);
o.add(1);
o.add(1L);
o.add(1L);
final List<Object> l = Arrays.asList("test", 1, 5L);
o.add(l);
assertEquals(o, serializeDeserialize(mapper, o, List.class));
}
@Test
public void shouldHandleSet() throws Exception {
assumeThat(version, startsWith("v3"));
final Set<Object> o = new LinkedHashSet<>();
o.add("test");
o.add(1);
o.add(1);
o.add(1L);
o.add(1L);
final List<Object> l = Arrays.asList("test", 1, 5L);
o.add(l);
assertEquals(o, serializeDeserialize(mapper, o, Set.class));
}
@Test
public void shouldHandleBiFunctionLambda() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Lambda o = (Lambda) Lambda.biFunction("x,y -> 'test'");
assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
}
@Test
public void shouldHandleComparatorLambda() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Lambda o = (Lambda) Lambda.comparator("x,y -> x <=> y");
assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
}
@Test
public void shouldHandleConsumerLambda() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Lambda o = (Lambda) Lambda.consumer("x -> x");
assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
}
@Test
public void shouldHandleFunctionLambda() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Lambda o = (Lambda) Lambda.function("x -> x");
assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
}
@Test
public void shouldHandlePredicateLambda() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Lambda o = (Lambda) Lambda.predicate("x -> true");
assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
}
@Test
public void shouldHandleSupplierLambda() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Lambda o = (Lambda) Lambda.supplier("'test'");
assertEquals(o, serializeDeserialize(mapper, o, Lambda.class));
}
@Test
public void shouldHandleBytecodeBinding() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Bytecode.Binding<String> o = new Bytecode.Binding<>("test", "testing");
assertEquals(o, serializeDeserialize(mapper, o, Bytecode.Binding.class));
}
@Test
public void shouldHandleTraverser() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final Traverser<String> o = new DefaultRemoteTraverser<>("test", 100);
assertEquals(o, serializeDeserialize(mapper, o, Traverser.class));
}
@Test
public void shouldHandleDuration() throws Exception {
final Duration o = Duration.ZERO;
assertEquals(o, serializeDeserialize(mapper, o, Duration.class));
}
@Test
public void shouldHandleInstant() throws Exception {
final Instant o = Instant.ofEpochMilli(System.currentTimeMillis());
assertEquals(o, serializeDeserialize(mapper, o, Instant.class));
}
@Test
public void shouldHandleLocalDate() throws Exception {
final LocalDate o = LocalDate.now();
assertEquals(o, serializeDeserialize(mapper, o, LocalDate.class));
}
@Test
public void shouldHandleLocalDateTime() throws Exception {
final LocalDateTime o = LocalDateTime.now();
assertEquals(o, serializeDeserialize(mapper, o, LocalDateTime.class));
}
@Test
public void shouldHandleLocalTime() throws Exception {
final LocalTime o = LocalTime.now();
assertEquals(o, serializeDeserialize(mapper, o, LocalTime.class));
}
@Test
public void shouldHandleMonthDay() throws Exception {
final MonthDay o = MonthDay.now();
assertEquals(o, serializeDeserialize(mapper, o, MonthDay.class));
}
@Test
public void shouldHandleOffsetDateTime() throws Exception {
final OffsetDateTime o = OffsetDateTime.now();
assertEquals(o, serializeDeserialize(mapper, o, OffsetDateTime.class));
}
@Test
public void shouldHandleOffsetTime() throws Exception {
final OffsetTime o = OffsetTime.now();
assertEquals(o, serializeDeserialize(mapper, o, OffsetTime.class));
}
@Test
public void shouldHandlePeriod() throws Exception {
final Period o = Period.ofDays(3);
assertEquals(o, serializeDeserialize(mapper, o, Period.class));
}
@Test
public void shouldHandleYear() throws Exception {
final Year o = Year.now();
assertEquals(o, serializeDeserialize(mapper, o, Year.class));
}
@Test
public void shouldHandleYearMonth() throws Exception {
final YearMonth o = YearMonth.now();
assertEquals(o, serializeDeserialize(mapper, o, YearMonth.class));
}
@Test
public void shouldHandleZonedDateTime() throws Exception {
final ZonedDateTime o = ZonedDateTime.now();
assertEquals(o, serializeDeserialize(mapper, o, ZonedDateTime.class));
}
@Test
public void shouldHandleZonedOffset() throws Exception {
final ZoneOffset o = ZonedDateTime.now().getOffset();
assertEquals(o, serializeDeserialize(mapper, o, ZoneOffset.class));
}
@Test
public void shouldHandleBigInteger() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final BigInteger o = new BigInteger("123456789987654321123456789987654321");
assertEquals(o, serializeDeserialize(mapper, o, BigInteger.class));
}
@Test
public void shouldReadBigIntegerAsString() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final BigInteger o = new BigInteger("123456789987654321123456789987654321");
assertEquals(o, mapper.readValue("{\"@type\": \"gx:BigInteger\", \"@value\": \"123456789987654321123456789987654321\"}", Object.class));
}
@Test
public void shouldReadBigIntegerAsNumber() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
// this was the original GraphSON 2.0/3.0 format published for BigInteger but jackson is flexible enough to
// do it as a string. the string approach is probably better for most language variants so while this tests
// enforces this approach but leaves open the opportunity to accept either. at some point in the future
// perhaps it can switch fully - TINKERPOP-2156
final BigInteger o = new BigInteger("123456789987654321123456789987654321");
assertEquals(o, mapper.readValue("{\"@type\": \"gx:BigInteger\", \"@value\": 123456789987654321123456789987654321}", Object.class));
}
@Test
public void shouldHandleBigDecimal() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final BigDecimal o = new BigDecimal("123456789987654321123456789987654321");
assertEquals(o, serializeDeserialize(mapper, o, BigDecimal.class));
}
@Test
public void shouldHandlePMultiValue() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final P o = P.within(1,2,3);
assertEquals(o, serializeDeserialize(mapper, o, P.class));
}
@Test
public void shouldHandlePSingleValue() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final P o = P.within(1);
assertEquals(o, serializeDeserialize(mapper, o, P.class));
}
@Test
public void shouldHandlePMultiValueAsCollection() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final P o = P.within(Arrays.asList(1,2,3));
assertEquals(o, serializeDeserialize(mapper, o, P.class));
}
@Test
public void shouldReadPWithJsonArray() throws Exception {
// for some reason v3 is forgiving about the naked json array - leaving this here for backward compaitiblity,
// but should be a g:List (i think)
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final P o = P.within(Arrays.asList(1,2,3));
assertEquals(o, mapper.readValue("{\"@type\": \"g:P\", \"@value\": {\"predicate\": \"within\", \"value\": [{\"@type\": \"g:Int32\", \"@value\": 1},{\"@type\": \"g:Int32\", \"@value\": 2},{\"@type\": \"g:Int32\", \"@value\": 3}]}}", Object.class));
}
@Test
public void shouldReadPWithGraphSONList() throws Exception {
assumeThat(version, startsWith("v3"));
final P o = P.within(Arrays.asList(1,2,3));
assertEquals(o, mapper.readValue("{\"@type\": \"g:P\", \"@value\": {\"predicate\": \"within\", \"value\": {\"@type\": \"g:List\", \"@value\": [{\"@type\": \"g:Int32\", \"@value\": 1},{\"@type\": \"g:Int32\", \"@value\": 2},{\"@type\": \"g:Int32\", \"@value\": 3}]}}}", Object.class));
}
@Test
public void shouldReadBigDecimalAsString() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
final BigDecimal o = new BigDecimal("123456789987654321123456789987654321");
assertEquals(o, mapper.readValue("{\"@type\": \"gx:BigDecimal\", \"@value\": \"123456789987654321123456789987654321\"}", Object.class));
}
@Test
public void shouldReadBigDecimalAsNumber() throws Exception {
assumeThat(version, either(startsWith("v2")).or(startsWith("v3")));
// this was the original GraphSON 2.0/3.0 format published for BigDecimal but jackson is flexible enough to
// do it as a string. the string approach is probably better for most language variants so while this tests
// enforces this approach but leaves open the opportunity to accept either. at some point in the future
// perhaps it can switch fully - TINKERPOP-2156
final BigDecimal o = new BigDecimal("123456789987654321123456789987654321");
assertEquals(o, mapper.readValue("{\"@type\": \"gx:BigDecimal\", \"@value\": 123456789987654321123456789987654321}", Object.class));
}
}