You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2026/08/20 18:29:44 UTC
(tinkerpop) 05/09: Broaden TinkerStorage TCK: value types, ids, varints, unicode round-trips
This is an automated email from the ASF dual-hosted git repository.
spmallette pushed a commit to branch tinkergraph-storage
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit f32a598ea3d247db9bc22f052fe1ac77fe3f7142
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Wed Aug 19 16:24:13 2026 +0000
Broaden TinkerStorage TCK: value types, ids, varints, unicode round-trips
Add conformance round-trip coverage for the storage codec's breadth: a
value-type matrix (int/long/float/double/boolean/byte/short/char/string/UUID/
BigInteger/BigDecimal/OffsetDateTime/Duration), collection-valued properties
(List/Map/Set), null values, heterogeneous same-key types, non-Long (UUID and
String) element ids, unicode keys and values, and a large-schema graph whose
>127 distinct keys and >127 values under one key exercise the multi-byte varint
path that small graphs never reach.
Assisted-by: Claude Code:claude-opus-4-8
---
.../AbstractTinkerStorageConformanceTest.java | 206 +++++++++++++++++++++
1 file changed, 206 insertions(+)
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/storage/AbstractTinkerStorageConformanceTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/storage/AbstractTinkerStorageConformanceTest.java
index 552cd37da4..f5ec5033f4 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/storage/AbstractTinkerStorageConformanceTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/storage/AbstractTinkerStorageConformanceTest.java
@@ -32,15 +32,26 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.Duration;
+import java.time.OffsetDateTime;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -284,6 +295,201 @@ public abstract class AbstractTinkerStorageConformanceTest {
}
}
+ @Test
+ public void shouldRoundTripDiverseValueTypes() {
+ final Map<String, Object> values = new LinkedHashMap<>();
+ values.put("int", 42);
+ values.put("long", 42L);
+ values.put("float", 1.5f);
+ values.put("double", 2.5d);
+ values.put("bool", true);
+ values.put("byte", (byte) 7);
+ values.put("short", (short) 9);
+ values.put("char", 'x');
+ values.put("string", "hello");
+ values.put("uuid", new UUID(12L, 34L));
+ values.put("bigint", new BigInteger("123456789012345678901234567890"));
+ values.put("bigdec", new BigDecimal("3.14159265358979"));
+ values.put("datetime", OffsetDateTime.parse("2020-01-02T03:04:05Z"));
+ values.put("duration", Duration.ofSeconds(90));
+
+ TinkerStorageGraph graph = open();
+ try {
+ final Vertex v = graph.addVertex(T.id, 1);
+ values.forEach(v::property);
+ graph.tx().commit();
+ } finally {
+ graph.close();
+ }
+ graph = open();
+ try {
+ final Vertex v = graph.vertices(1).next();
+ values.forEach((k, expected) -> assertEquals(k, expected, v.value(k)));
+ } finally {
+ graph.close();
+ }
+ }
+
+ @Test
+ public void shouldRoundTripCollectionValuedProperties() {
+ final List<Object> list = Arrays.asList(1, "two", 3.0d);
+ final Map<String, Object> map = new LinkedHashMap<>();
+ map.put("a", 1);
+ map.put("b", "two");
+ final Set<Object> set = new LinkedHashSet<>(Arrays.asList("x", "y", "z"));
+
+ TinkerStorageGraph graph = open();
+ try {
+ final Vertex v = graph.addVertex(T.id, 1);
+ v.property("list", list);
+ v.property("map", map);
+ v.property("set", set);
+ graph.tx().commit();
+ } finally {
+ graph.close();
+ }
+ graph = open();
+ try {
+ final Vertex v = graph.vertices(1).next();
+ assertEquals(list, v.value("list"));
+ assertEquals(map, v.value("map"));
+ assertEquals(set, v.value("set"));
+ } finally {
+ graph.close();
+ }
+ }
+
+ @Test
+ public void shouldRoundTripNullPropertyValue() {
+ final Configuration conf = config();
+ conf.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_ALLOW_NULL_PROPERTY_VALUES, true);
+ TinkerStorageGraph graph = TinkerStorageGraph.open(conf);
+ try {
+ final Vertex v = graph.addVertex(T.id, 1);
+ v.property("maybe", null);
+ graph.tx().commit();
+ } finally {
+ graph.close();
+ }
+ graph = TinkerStorageGraph.open(conf);
+ try {
+ final VertexProperty<Object> vp = graph.vertices(1).next().<Object>properties("maybe").next();
+ assertTrue(vp.isPresent());
+ assertNull(vp.value());
+ } finally {
+ graph.close();
+ }
+ }
+
+ @Test
+ public void shouldRoundTripHeterogeneousSameKeyTypes() {
+ TinkerStorageGraph graph = open();
+ try {
+ graph.addVertex(T.id, 1, "k", 42); // Integer
+ graph.addVertex(T.id, 2, "k", 42L); // Long
+ graph.tx().commit();
+ } finally {
+ graph.close();
+ }
+ graph = open();
+ try {
+ assertEquals(Integer.valueOf(42), graph.vertices(1).next().value("k"));
+ assertEquals(Long.valueOf(42L), graph.vertices(2).next().value("k"));
+ } finally {
+ graph.close();
+ }
+ }
+
+ @Test
+ public void shouldRoundTripUuidElementIds() {
+ roundTripElementIds(new UUID(0L, 1L), new UUID(0L, 2L), new UUID(0L, 10L));
+ }
+
+ @Test
+ public void shouldRoundTripStringElementIds() {
+ roundTripElementIds("v-1", "v-2", "e-10");
+ }
+
+ // uses the default ANY id manager so any id type is accepted verbatim; the point is that the storage codec
+ // round-trips non-Long element ids through its scalar id encoding
+ private void roundTripElementIds(final Object outId, final Object inId, final Object edgeId) {
+ TinkerStorageGraph graph = open();
+ try {
+ final Vertex a = graph.addVertex(T.id, outId, "name", "a");
+ final Vertex b = graph.addVertex(T.id, inId, "name", "b");
+ a.addEdge("knows", b, T.id, edgeId, "weight", 0.5d);
+ graph.tx().commit();
+ } finally {
+ graph.close();
+ }
+ graph = open();
+ try {
+ assertEquals("a", graph.vertices(outId).next().value("name"));
+ assertEquals(outId, graph.vertices(outId).next().id());
+ final Edge e = graph.edges(edgeId).next();
+ assertEquals("knows", e.label());
+ assertEquals(outId, e.outVertex().id());
+ assertEquals(inId, e.inVertex().id());
+ } finally {
+ graph.close();
+ }
+ }
+
+ @Test
+ public void shouldRoundTripLargeSchemaAcrossVarintBoundary() {
+ // >127 distinct keys and >127 values under one key push dictionary refs and counts past the single-byte
+ // LEB128 range, exercising the multi-byte varint path that small graphs never reach
+ final int n = 200;
+ // list cardinality so the >127 values under "multi" survive reopen (reconstruction takes cardinality from
+ // graph config, not the stored record)
+ final Configuration conf = config();
+ conf.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, "list");
+ TinkerStorageGraph graph = TinkerStorageGraph.open(conf);
+ try {
+ final Vertex v = graph.addVertex(T.id, 1);
+ for (int i = 0; i < n; i++)
+ v.property("key" + i, i);
+ for (int i = 0; i < n; i++)
+ v.property(VertexProperty.Cardinality.list, "multi", i);
+ graph.tx().commit();
+ graph.compact(); // also exercises a dictionary header with >127 entries
+ } finally {
+ graph.close();
+ }
+ graph = TinkerStorageGraph.open(conf);
+ try {
+ final Vertex v = graph.vertices(1).next();
+ for (int i = 0; i < n; i++)
+ assertEquals("key" + i, Integer.valueOf(i), v.value("key" + i));
+ assertEquals(n, countOf(v.properties("multi")));
+ } finally {
+ graph.close();
+ }
+ }
+
+ @Test
+ public void shouldRoundTripUnicodeKeysAndValues() {
+ TinkerStorageGraph graph = open();
+ try {
+ final Vertex v = graph.addVertex(T.id, 1);
+ v.property("naïve", "café");
+ v.property("日本語", "テスト");
+ v.property("emoji", "party🎉");
+ graph.tx().commit();
+ } finally {
+ graph.close();
+ }
+ graph = open();
+ try {
+ final Vertex v = graph.vertices(1).next();
+ assertEquals("café", v.value("naïve"));
+ assertEquals("テスト", v.value("日本語"));
+ assertEquals("party🎉", v.value("emoji"));
+ } finally {
+ graph.close();
+ }
+ }
+
private static long countOf(final Iterator<?> it) {
long count = 0;
while (it.hasNext()) {