This is an automated email from the ASF dual-hosted git repository. Cole-Greer pushed a commit to branch simplePDT in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 7aa8ead58fc2e5e7bc684bdc22e947f0f6263163 Author: Cole Greer <[email protected]> AuthorDate: Wed Jun 24 14:12:37 2026 -0700 Add server-side PrimitivePDT test fixtures and integration coverage Adds gremlin-server test fixtures and end-to-end integration coverage for PrimitivePDT, mirroring the composite fixtures. - Uint32 (long-backed unsigned 32-bit) + Uint32Adapter (PrimitivePDTAdapter; toValue=Long.toUnsignedString, fromValue parses with 0..4294967295 range validation). - TinkerId (String-backed, non-numeric) + TinkerIdAdapter, proving the adapter generalizes beyond numbers. - Measurement: a @ProviderDefined composite fixture containing a Uint32 field, exercising primitive-nested-in-composite. - Primitive adapters registered via the unified META-INF/services/...ProviderDefinedTypeAdapter file so the server/test registry discovers them through ServiceLoader. - GremlinServerPrimitivePdtIntegrateTest: injects PDT("Uint32","..."), PDT("TinkerId","..."), a Measurement containing a nested Uint32, and a collection, asserting correct round-trip/hydration. tinkerpop-2gy.7 Assisted-by: Kiro:claude-opus-4.8 --- .../GremlinServerPrimitivePdtIntegrateTest.java | 125 +++++++++++++++++++++ .../tinkerpop/gremlin/server/pdt/Measurement.java | 38 +++++++ .../tinkerpop/gremlin/server/pdt/TinkerId.java | 57 ++++++++++ .../gremlin/server/pdt/TinkerIdAdapter.java | 47 ++++++++ .../tinkerpop/gremlin/server/pdt/Uint32.java | 57 ++++++++++ .../gremlin/server/pdt/Uint32Adapter.java | 50 +++++++++ ...lin.structure.io.pdt.ProviderDefinedTypeAdapter | 2 + 7 files changed, 376 insertions(+) diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerPrimitivePdtIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerPrimitivePdtIntegrateTest.java new file mode 100644 index 0000000000..def25a2935 --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerPrimitivePdtIntegrateTest.java @@ -0,0 +1,125 @@ +/* + * 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.server; + +import org.apache.tinkerpop.gremlin.driver.Client; +import org.apache.tinkerpop.gremlin.driver.Cluster; +import org.apache.tinkerpop.gremlin.driver.Result; +import org.apache.tinkerpop.gremlin.server.pdt.TinkerId; +import org.apache.tinkerpop.gremlin.server.pdt.Uint32; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitiveProviderDefinedType; +import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; + +/** + * Integration tests for PrimitivePDT round-trip through gremlin-server. + * Exercises Uint32 (numeric), TinkerId (non-numeric), and a composite containing a primitive. + */ +public class GremlinServerPrimitivePdtIntegrateTest extends AbstractGremlinServerIntegrationTest { + + private Cluster cluster; + private Client client; + + @Before + public void openConnection() { + cluster = TestClientFactory.build().create(); + client = cluster.connect(); + } + + @After + public void closeConnection() { + if (cluster != null) cluster.close(); + } + + @Test + public void shouldRoundTripUint32PrimitivePdt() throws Exception { + final List<Result> results = client.submit( + "g.inject(PDT(\"Uint32\",\"4294967295\"))").all().get(); + + assertEquals(1, results.size()); + final Object obj = results.get(0).getObject(); + // With Uint32Adapter on classpath, the reader hydrates to Uint32 + assertThat(obj, instanceOf(Uint32.class)); + assertEquals(4294967295L, ((Uint32) obj).getValue()); + } + + @Test + public void shouldRoundTripUint32ZeroValue() throws Exception { + final List<Result> results = client.submit( + "g.inject(PDT(\"Uint32\",\"0\"))").all().get(); + + assertEquals(1, results.size()); + final Object obj = results.get(0).getObject(); + assertThat(obj, instanceOf(Uint32.class)); + assertEquals(0L, ((Uint32) obj).getValue()); + } + + @Test + public void shouldRoundTripTinkerIdPrimitivePdt() throws Exception { + final List<Result> results = client.submit( + "g.inject(PDT(\"TinkerId\",\"abc-123-def\"))").all().get(); + + assertEquals(1, results.size()); + final Object obj = results.get(0).getObject(); + // With TinkerIdAdapter on classpath, the reader hydrates to TinkerId + assertThat(obj, instanceOf(TinkerId.class)); + assertEquals("abc-123-def", ((TinkerId) obj).getId()); + } + + @Test + public void shouldRoundTripPrimitiveNestedInComposite() throws Exception { + final List<Result> results = client.submit( + "g.inject(PDT(\"Measurement\",[\"unit\":\"meters\",\"quantity\":PDT(\"Uint32\",\"100\")]))").all().get(); + + assertEquals(1, results.size()); + final Object obj = results.get(0).getObject(); + // Measurement has no adapter registered, so outer is raw ProviderDefinedType + assertThat(obj, instanceOf(ProviderDefinedType.class)); + final ProviderDefinedType pdt = (ProviderDefinedType) obj; + assertEquals("Measurement", pdt.getName()); + assertEquals("meters", pdt.getFields().get("unit")); + // Nested primitive is hydrated to Uint32 + final Object quantity = pdt.getFields().get("quantity"); + assertThat(quantity, instanceOf(Uint32.class)); + assertEquals(100L, ((Uint32) quantity).getValue()); + } + + @Test + public void shouldRoundTripMultiplePrimitivePdtsInCollection() throws Exception { + final List<Result> results = client.submit( + "g.inject([PDT(\"Uint32\",\"42\"),PDT(\"TinkerId\",\"x-1\")])").all().get(); + + assertEquals(1, results.size()); + final List<?> list = (List<?>) results.get(0).getObject(); + assertEquals(2, list.size()); + assertThat(list.get(0), instanceOf(Uint32.class)); + assertEquals(42L, ((Uint32) list.get(0)).getValue()); + assertThat(list.get(1), instanceOf(TinkerId.class)); + assertEquals("x-1", ((TinkerId) list.get(1)).getId()); + } +} diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Measurement.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Measurement.java new file mode 100644 index 0000000000..961dccf406 --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Measurement.java @@ -0,0 +1,38 @@ +/* + * 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.server.pdt; + +import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefined; + +/** + * A composite test fixture containing a primitive PDT field ({@link Uint32}). + * Used to exercise primitive-nested-in-composite round-trip in integration tests. + */ +@ProviderDefined(name = "Measurement") +public class Measurement { + public String unit; + public Uint32 quantity; + + public Measurement() {} + + public Measurement(final String unit, final Uint32 quantity) { + this.unit = unit; + this.quantity = quantity; + } +} diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/TinkerId.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/TinkerId.java new file mode 100644 index 0000000000..883ceebbba --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/TinkerId.java @@ -0,0 +1,57 @@ +/* + * 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.server.pdt; + +import java.util.Objects; + +/** + * A non-numeric test fixture representing an opaque string identifier. + * Used to prove PrimitivePDT generalizes beyond numeric types. + */ +public final class TinkerId { + + private final String id; + + public TinkerId(final String id) { + if (id == null || id.isEmpty()) + throw new IllegalArgumentException("TinkerId cannot be null or empty"); + this.id = id; + } + + public String getId() { + return id; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof TinkerId)) return false; + return id.equals(((TinkerId) o).id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public String toString() { + return "TinkerId(" + id + ")"; + } +} diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/TinkerIdAdapter.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/TinkerIdAdapter.java new file mode 100644 index 0000000000..a6be6d1f57 --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/TinkerIdAdapter.java @@ -0,0 +1,47 @@ +/* + * 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.server.pdt; + +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitivePDTAdapter; + +/** + * Adapter for {@link TinkerId} primitive PDT. The string value is the ID itself. + */ +public final class TinkerIdAdapter implements PrimitivePDTAdapter<TinkerId> { + + @Override + public String typeName() { + return "TinkerId"; + } + + @Override + public Class<TinkerId> targetClass() { + return TinkerId.class; + } + + @Override + public String toValue(final TinkerId obj) { + return obj.getId(); + } + + @Override + public TinkerId fromValue(final String value) { + return new TinkerId(value); + } +} diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Uint32.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Uint32.java new file mode 100644 index 0000000000..330b93fe03 --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Uint32.java @@ -0,0 +1,57 @@ +/* + * 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.server.pdt; + +import java.util.Objects; + +/** + * A test fixture representing an unsigned 32-bit integer, backed by a {@code long}. + * Used to exercise PrimitivePDT numeric round-trip in integration tests. + */ +public final class Uint32 { + + private final long value; + + public Uint32(final long value) { + if (value < 0 || value > 4294967295L) + throw new IllegalArgumentException("Uint32 value out of range: " + value); + this.value = value; + } + + public long getValue() { + return value; + } + + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (!(o instanceof Uint32)) return false; + return value == ((Uint32) o).value; + } + + @Override + public int hashCode() { + return Objects.hash(value); + } + + @Override + public String toString() { + return "Uint32(" + value + ")"; + } +} diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Uint32Adapter.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Uint32Adapter.java new file mode 100644 index 0000000000..56c9de1b83 --- /dev/null +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/pdt/Uint32Adapter.java @@ -0,0 +1,50 @@ +/* + * 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.server.pdt; + +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitivePDTAdapter; + +/** + * Adapter for {@link Uint32} primitive PDT. Serializes as the unsigned decimal string representation. + */ +public final class Uint32Adapter implements PrimitivePDTAdapter<Uint32> { + + @Override + public String typeName() { + return "Uint32"; + } + + @Override + public Class<Uint32> targetClass() { + return Uint32.class; + } + + @Override + public String toValue(final Uint32 obj) { + return Long.toUnsignedString(obj.getValue()); + } + + @Override + public Uint32 fromValue(final String value) { + final long parsed = Long.parseUnsignedLong(value); + if (Long.compareUnsigned(parsed, 4294967295L) > 0) + throw new IllegalArgumentException("Value exceeds Uint32 range: " + value); + return new Uint32(parsed); + } +} diff --git a/gremlin-server/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter b/gremlin-server/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter new file mode 100644 index 0000000000..83eb396324 --- /dev/null +++ b/gremlin-server/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter @@ -0,0 +1,2 @@ +org.apache.tinkerpop.gremlin.server.pdt.Uint32Adapter +org.apache.tinkerpop.gremlin.server.pdt.TinkerIdAdapter
