You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by co...@apache.org on 2026/03/10 23:14:43 UTC
(tinkerpop) branch master updated: Update JS driver to GraphBinary4 (#3312)
This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/master by this push:
new 991753b507 Update JS driver to GraphBinary4 (#3312)
991753b507 is described below
commit 991753b507b3fdeccb7f84c31a9955f19bbb3ba3
Author: kirill-stepanishin <ki...@improving.com>
AuthorDate: Tue Mar 10 16:14:38 2026 -0700
Update JS driver to GraphBinary4 (#3312)
Migrates the gremlin-javascript GraphBinary serialization layer from v1 to v4 and replaces the test suite.
Serializer changes
Removed serializer files: Traverser, P, TextP, Lambda, TraversalStrategy, BulkSet, OffsetDateTime, LongSerializerNg
Removed DataType constants (had serializer implementations): Traverser (0x21), P (0x1e), TextP (0x28), Lambda (0x1d), TraversalStrategy (0x29), BulkSet (0x2a), Timestamp (0x05), Class (0x06), Barrier (0x13), Binding (0x14), Bytecode (0x15), Cardinality (0x16), Column (0x17), Operator (0x19), Order (0x1a), Pick (0x1b), Pop (0x1c), Scope (0x1f), OffsetDateTime (0x88)
Removed DataType constants (no serializer implementations existed): Metrics (0x2c), TraversalMetrics (0x2d), Merge (0x2e), DT (0x2f), GType (0x30), InetAddress (0x82), Instant (0x83), LocalDate (0x84), LocalDateTime (0x85), LocalTime (0x86), MonthDay (0x87), OffsetTime (0x89), Period (0x8a), Year (0x8b), YearMonth (0x8c), ZonedDateTime (0x8d), ZoneOffset (0x8e), Custom (0x00)
Added: Marker (0xfd), StubSerializer for Tree (0x2b), Graph (0x10), CompositePDT (0xf0), PrimitivePDT (0xf1)
Renamed: ByteBufferSerializer → BinarySerializer (0x25), DATE constant → DATETIME (same code 0x04)
Replaced: DateSerializer and OffsetDateTimeSerializer both removed, replaced by new DateTimeSerializer (0x04) with component format (year/month/day/nanos/offset — 18 bytes) instead of epoch millis
Modified:
Byte: unsigned → signed (writeUInt8 → writeInt8)
EnumSerializer: narrowed to Direction (0x18) and T (0x20) only, uses fully-qualified string values
List/Set: value_flag=0x02 indicates bulked format
Map: value_flag=0x02 indicates ordered, value_flag=0x01 returns null
Edge/Vertex/VertexProperty: labels serialize as List<String> on the wire. Properties field always writes empty List instead of null — properties on graph objects are lost during serialization.
Test rewrite
Replaced per-serializer tests with a model-based approach:
model.js / model-test.js — validates .gbin reference files with three modes: run (byte-exact), runWriteRead (double round-trip idempotency), runRead (deserialize-only)
error-cases-test.js — malformed input cases consolidated from old per-serializer tests
type-detection-test.js — AnySerializer dispatch, canBeUsedFor, number routing boundaries, round-trip extras
null-handling-test.js — null/undefined per type in both fully-qualified and bare formats
Note: GraphBinaryReader and GraphBinaryWriter are not updated in this PR. They will be migrated to the v4 message framing format in a future PR, as they depend on other changes.
---
.../lib/structure/io/binary/GraphBinary.js | 78 +--
.../structure/io/binary/internals/AnySerializer.js | 18 +-
.../io/binary/internals/ArraySerializer.js | 20 +-
...ByteBufferSerializer.js => BinarySerializer.js} | 12 +-
.../io/binary/internals/BulkSetSerializer.js | 125 -----
.../io/binary/internals/ByteSerializer.js | 4 +-
.../lib/structure/io/binary/internals/DataType.js | 44 +-
...DateTimeSerializer.js => DateTimeSerializer.js} | 122 +++--
.../io/binary/internals/EdgeSerializer.js | 28 +-
.../io/binary/internals/EnumSerializer.js | 86 +--
.../io/binary/internals/LambdaSerializer.js | 70 ---
.../io/binary/internals/LongSerializer.js | 3 +-
.../io/binary/internals/LongSerializerNg.js | 103 ----
.../structure/io/binary/internals/MapSerializer.js | 4 +-
.../{DateSerializer.js => MarkerSerializer.js} | 59 +-
.../internals/NumberSerializationStrategy.js | 3 +-
.../structure/io/binary/internals/PSerializer.js | 151 ------
.../structure/io/binary/internals/SetSerializer.js | 19 +-
.../io/binary/internals/StubSerializer.js} | 18 +-
.../io/binary/internals/TextPSerializer.js | 145 -----
.../internals/TraversalStrategySerializer.js | 68 ---
.../io/binary/internals/TraverserSerializer.js | 123 -----
.../binary/internals/VertexPropertySerializer.js | 14 +-
.../io/binary/internals/VertexSerializer.js | 12 +-
.../test/unit/graphbinary/AnySerializer-test.js | 603 ---------------------
.../graphbinary/ArraySerializerTestTemplate.js | 149 -----
.../unit/graphbinary/BigIntegerSerializer-test.js | 199 -------
.../unit/graphbinary/BooleanSerializer-test.js | 140 -----
.../unit/graphbinary/BulkSetSerializer-test.js | 157 ------
.../unit/graphbinary/ByteBufferSerializer-test.js | 154 ------
.../test/unit/graphbinary/ByteSerializer-test.js | 117 ----
.../test/unit/graphbinary/DateSerializer-test.js | 26 -
.../unit/graphbinary/DateSerializerTestTemplate.js | 148 -----
.../test/unit/graphbinary/DoubleSerializer-test.js | 151 ------
.../test/unit/graphbinary/EdgeSerializer-test.js | 169 ------
.../test/unit/graphbinary/EnumSerializer-test.js | 171 ------
.../test/unit/graphbinary/FloatSerializer-test.js | 122 -----
.../unit/graphbinary/GraphBinaryReader-test.js | 128 -----
.../unit/graphbinary/GraphBinaryWriter-test.js | 42 --
.../test/unit/graphbinary/IntSerializer-test.js | 147 -----
.../test/unit/graphbinary/LambdaSerializer-test.js | 93 ----
.../test/unit/graphbinary/ListSerializer-test.js | 26 -
.../test/unit/graphbinary/LongSerializer-test.js | 144 -----
.../test/unit/graphbinary/LongSerializerNg-test.js | 132 -----
.../test/unit/graphbinary/MapSerializer-test.js | 192 -------
.../test/unit/graphbinary/PSerializer-test.js | 196 -------
.../test/unit/graphbinary/PathSerializer-test.js | 244 ---------
.../unit/graphbinary/PropertySerializer-test.js | 140 -----
.../unit/graphbinary/SetSerializerTestTemplate.js | 148 -----
.../test/unit/graphbinary/ShortSerializer-test.js | 121 -----
.../test/unit/graphbinary/StringSerializer-test.js | 26 -
.../graphbinary/StringSerializerTestTemplate.js | 168 ------
.../test/unit/graphbinary/TextPSerializer-test.js | 142 -----
.../unit/graphbinary/TimestampSerializer-test.js | 26 -
.../TraversalStrategySerializer-test.js | 99 ----
.../unit/graphbinary/TraverserSerializer-test.js | 131 -----
.../graphbinary/UnspecifiedNullSerializer-test.js | 101 ----
.../test/unit/graphbinary/UuidSerializer-test.js | 147 -----
.../graphbinary/VertexPropertySerializer-test.js | 142 -----
.../test/unit/graphbinary/VertexSerializer-test.js | 148 -----
.../test/unit/graphbinary/error-cases-test.js | 443 +++++++++++++++
.../test/unit/graphbinary/model-test.js | 251 +++++++++
.../test/unit/graphbinary/model.js | 204 +++++++
.../test/unit/graphbinary/null-handling-test.js | 233 ++++++++
.../test/unit/graphbinary/type-detection-test.js | 397 ++++++++++++++
.../test/unit/graphbinary/utils.js | 32 --
66 files changed, 1754 insertions(+), 6324 deletions(-)
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/GraphBinary.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/GraphBinary.js
index ddd7c07045..b8930f91c4 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/GraphBinary.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/GraphBinary.js
@@ -18,7 +18,7 @@
*/
/**
- * GraphBinary 1.0 support implementation.
+ * GraphBinary 4.0 support implementation.
*
* The officially expected entrypoint is GraphBinaryReader/GraphBinaryWriter pair of classes,
* examine lib/driver/** for use cases.
@@ -27,33 +27,13 @@
* also consider AnySerializer.serialize() unit tests for real examples.
* See NumberSerializationStrategy to understand how it deals with JavaScript numbers' serialization.
*
- * Consider AnySerializer.serialize()/deserialize() unit tests to see what is not implemented,
- * what is ignored, what is not expected to be (de)serialized, etc.
- *
* TODO: it has the following open topics:
- * - [] Should we do anything for application/vnd.graphbinary-v1.0-stringd mime type support?
* Core Data Types support:
* - [] 0x22: BigDecimal
* - [] 0x2b: Tree
- * - [] 0x2c: Metrics
- * - [] 0x2d: TraversalMetrics
- * - [] 0x00: Custom
* Extended Types support:
* - [] 0x80: Char
* - [] 0x81: Duration
- * - [] 0x82: InetAddress
- * - [] 0x83: Instant
- * - [] 0x84: LocalDate
- * - [] 0x85: LocalDateTime
- * - [] 0x86: LocalTime
- * - [] 0x87: MonthDay
- * - [] 0x88: OffsetDateTime
- * - [] 0x89: OffsetTime
- * - [] 0x8a: Period
- * - [] 0x8b: Year
- * - [] 0x8c: YearMonth
- * - [] 0x8d: ZonedDateTime
- * - [] 0x8e: ZoneOffset
*
* @author Igor Ostapenko
*/
@@ -63,10 +43,8 @@ import DataType from './internals/DataType.js';
import * as utils from './internals/utils.js';
import IntSerializer from './internals/IntSerializer.js';
import LongSerializer from './internals/LongSerializer.js';
-import LongSerializerNg from './internals/LongSerializerNg.js';
import StringSerializer from './internals/StringSerializer.js';
-import DateSerializer from './internals/DateSerializer.js';
-import OffsetDateTimeSerializer from './internals/OffsetDateTimeSerializer.js';
+import DateTimeSerializer from './internals/DateTimeSerializer.js';
import DoubleSerializer from './internals/DoubleSerializer.js';
import FloatSerializer from './internals/FloatSerializer.js';
import ArraySerializer from './internals/ArraySerializer.js';
@@ -78,19 +56,15 @@ import PathSerializer from './internals/PathSerializer.js';
import PropertySerializer from './internals/PropertySerializer.js';
import VertexSerializer from './internals/VertexSerializer.js';
import VertexPropertySerializer from './internals/VertexPropertySerializer.js';
-import PSerializer from './internals/PSerializer.js';
-import TraverserSerializer from './internals/TraverserSerializer.js';
-import EnumSerializer from './internals/EnumSerializer.js';
-import LambdaSerializer from './internals/LambdaSerializer.js';
import BigIntegerSerializer from './internals/BigIntegerSerializer.js';
import ByteSerializer from './internals/ByteSerializer.js';
-import ByteBufferSerializer from './internals/ByteBufferSerializer.js';
+import BinarySerializer from './internals/BinarySerializer.js';
import ShortSerializer from './internals/ShortSerializer.js';
import BooleanSerializer from './internals/BooleanSerializer.js';
-import TextPSerializer from './internals/TextPSerializer.js';
-import TraversalStrategySerializer from './internals/TraversalStrategySerializer.js';
-import BulkSetSerializer from './internals/BulkSetSerializer.js';
+import MarkerSerializer from './internals/MarkerSerializer.js';
import UnspecifiedNullSerializer from './internals/UnspecifiedNullSerializer.js';
+import EnumSerializer from './internals/EnumSerializer.js';
+import StubSerializer from './internals/StubSerializer.js';
import NumberSerializationStrategy from './internals/NumberSerializationStrategy.js';
import AnySerializer from './internals/AnySerializer.js';
import GraphBinaryReader from './internals/GraphBinaryReader.js';
@@ -105,12 +79,8 @@ ioc.serializers = {};
ioc.intSerializer = new IntSerializer(ioc);
ioc.longSerializer = new LongSerializer(ioc);
-ioc.longSerializerNg = new LongSerializerNg(ioc);
ioc.stringSerializer = new StringSerializer(ioc, ioc.DataType.STRING);
-ioc.dateSerializer = new DateSerializer(ioc, ioc.DataType.DATE);
-ioc.offsetDateTimeSerializer = new OffsetDateTimeSerializer(ioc, ioc.DataType.OFFSETDATETIME);
-ioc.timestampSerializer = new DateSerializer(ioc, ioc.DataType.TIMESTAMP);
-ioc.classSerializer = new StringSerializer(ioc, ioc.DataType.CLASS);
+ioc.dateTimeSerializer = new DateTimeSerializer(ioc);
ioc.doubleSerializer = new DoubleSerializer(ioc);
ioc.floatSerializer = new FloatSerializer(ioc);
ioc.listSerializer = new ArraySerializer(ioc, ioc.DataType.LIST);
@@ -122,19 +92,20 @@ ioc.pathSerializer = new PathSerializer(ioc);
ioc.propertySerializer = new PropertySerializer(ioc);
ioc.vertexSerializer = new VertexSerializer(ioc);
ioc.vertexPropertySerializer = new VertexPropertySerializer(ioc);
-ioc.pSerializer = new PSerializer(ioc);
-ioc.traverserSerializer = new TraverserSerializer(ioc);
-ioc.enumSerializer = new EnumSerializer(ioc);
-ioc.lambdaSerializer = new LambdaSerializer(ioc);
ioc.bigIntegerSerializer = new BigIntegerSerializer(ioc);
ioc.byteSerializer = new ByteSerializer(ioc);
-ioc.byteBufferSerializer = new ByteBufferSerializer(ioc);
+ioc.binarySerializer = new BinarySerializer(ioc);
ioc.shortSerializer = new ShortSerializer(ioc);
ioc.booleanSerializer = new BooleanSerializer(ioc);
-ioc.textPSerializer = new TextPSerializer(ioc);
-ioc.traversalStrategySerializer = new TraversalStrategySerializer(ioc);
-ioc.bulkSetSerializer = new BulkSetSerializer(ioc);
+ioc.markerSerializer = new MarkerSerializer(ioc);
ioc.unspecifiedNullSerializer = new UnspecifiedNullSerializer(ioc);
+ioc.enumSerializer = new EnumSerializer(ioc);
+
+// Register stub serializers for unimplemented v4 types
+new StubSerializer(ioc, ioc.DataType.TREE, 'Tree');
+new StubSerializer(ioc, ioc.DataType.GRAPH, 'Graph');
+new StubSerializer(ioc, ioc.DataType.COMPOSITEPDT, 'CompositePDT');
+new StubSerializer(ioc, ioc.DataType.PRIMITIVEPDT, 'PrimitivePDT');
ioc.numberSerializationStrategy = new NumberSerializationStrategy(ioc);
ioc.anySerializer = new AnySerializer(ioc);
@@ -148,12 +119,8 @@ export const {
serializers,
intSerializer,
longSerializer,
- longSerializerNg,
stringSerializer,
- dateSerializer,
- offsetDateTimeSerializer,
- timestampSerializer,
- classSerializer,
+ dateTimeSerializer,
doubleSerializer,
floatSerializer,
listSerializer,
@@ -165,19 +132,14 @@ export const {
propertySerializer,
vertexSerializer,
vertexPropertySerializer,
- pSerializer,
- traverserSerializer,
- enumSerializer,
- lambdaSerializer,
bigIntegerSerializer,
byteSerializer,
- byteBufferSerializer,
+ binarySerializer,
shortSerializer,
booleanSerializer,
- textPSerializer,
- traversalStrategySerializer,
- bulkSetSerializer,
+ markerSerializer,
unspecifiedNullSerializer,
+ enumSerializer,
numberSerializationStrategy,
anySerializer,
graphBinaryReader,
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/AnySerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/AnySerializer.js
index c550dc2a9d..f446a37cee 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/AnySerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/AnySerializer.js
@@ -30,15 +30,9 @@ export default class AnySerializer {
// specifically ordered, the first canBeUsedFor=true wins
this.serializers = [
ioc.unspecifiedNullSerializer,
-
ioc.numberSerializationStrategy,
-
ioc.booleanSerializer,
- ioc.offsetDateTimeSerializer,
- ioc.dateSerializer,
- ioc.pSerializer,
- ioc.traverserSerializer,
- ioc.enumSerializer,
+ ioc.dateTimeSerializer,
ioc.setSerializer,
ioc.listSerializer,
ioc.uuidSerializer,
@@ -47,14 +41,10 @@ export default class AnySerializer {
ioc.propertySerializer,
ioc.vertexSerializer,
ioc.vertexPropertySerializer,
+ ioc.enumSerializer,
ioc.stringSerializer,
- ioc.classSerializer,
- ioc.textPSerializer,
- ioc.traversalStrategySerializer,
-
- ioc.byteBufferSerializer, // Buffer instance
- ioc.lambdaSerializer, // any function
- ioc.mapSerializer, // Map or any Object
+ ioc.binarySerializer,
+ ioc.mapSerializer,
];
}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ArraySerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ArraySerializer.js
index abfe28f859..758575f342 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ArraySerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ArraySerializer.js
@@ -70,6 +70,7 @@ export default class ArraySerializer {
deserialize(buffer, fullyQualifiedFormat = true) {
let len = 0;
let cursor = buffer;
+ let isBulked = false;
try {
if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
@@ -95,9 +96,10 @@ export default class ArraySerializer {
if (value_flag === 1) {
return { v: null, len };
}
- if (value_flag !== 0) {
+ if (value_flag !== 0 && value_flag !== 2) {
throw new Error('unexpected {value_flag}');
}
+ isBulked = value_flag === 2;
cursor = cursor.slice(1);
}
@@ -125,7 +127,21 @@ export default class ArraySerializer {
throw err;
}
cursor = cursor.slice(value_len);
- v.push(value);
+
+ if (isBulked) {
+ if (cursor.length < 8) {
+ throw new Error(`{item_${i}}: bulk count is missing`);
+ }
+ const bulkCount = cursor.readBigInt64BE();
+ len += 8;
+ cursor = cursor.slice(8);
+
+ for (let j = 0n; j < bulkCount; j++) {
+ v.push(value);
+ }
+ } else {
+ v.push(value);
+ }
}
return { v, len };
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteBufferSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/BinarySerializer.js
similarity index 90%
rename from gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteBufferSerializer.js
rename to gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/BinarySerializer.js
index 358aa07604..4d51e29f3c 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteBufferSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/BinarySerializer.js
@@ -23,10 +23,10 @@
import { Buffer } from 'buffer';
-export default class ByteBufferSerializer {
+export default class BinarySerializer {
constructor(ioc) {
this.ioc = ioc;
- this.ioc.serializers[ioc.DataType.BYTEBUFFER] = this;
+ this.ioc.serializers[ioc.DataType.BINARY] = this;
}
canBeUsedFor(value) {
@@ -36,14 +36,14 @@ export default class ByteBufferSerializer {
serialize(item, fullyQualifiedFormat = true) {
if (item === undefined || item === null) {
if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.BYTEBUFFER, 0x01]);
+ return Buffer.from([this.ioc.DataType.BINARY, 0x01]);
}
return Buffer.from([0x00, 0x00, 0x00, 0x00]); // {length} = 0
}
const bufs = [];
if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.BYTEBUFFER, 0x00]));
+ bufs.push(Buffer.from([this.ioc.DataType.BINARY, 0x00]));
}
// {length}
@@ -79,7 +79,7 @@ export default class ByteBufferSerializer {
if (fullyQualifiedFormat) {
const type_code = cursor.readUInt8();
len++;
- if (type_code !== this.ioc.DataType.BYTEBUFFER) {
+ if (type_code !== this.ioc.DataType.BINARY) {
throw new Error('unexpected {type_code}');
}
cursor = cursor.slice(1);
@@ -111,7 +111,7 @@ export default class ByteBufferSerializer {
}
cursor = cursor.slice(length_len);
- if (length !== cursor.length) {
+ if (cursor.length < length) {
throw new Error(`{value}: unexpected actual {value} length=${cursor.length} when {length}=${length}`);
}
const v = cursor.slice(0, length);
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/BulkSetSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/BulkSetSerializer.js
deleted file mode 100644
index 89209392f8..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/BulkSetSerializer.js
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-
-export default class BulkSetSerializer {
- constructor(ioc) {
- this.ioc = ioc;
- this.ioc.serializers[ioc.DataType.BULKSET] = this;
- }
-
- deserialize(buffer, fullyQualifiedFormat = true) {
- let len = 0;
- let cursor = buffer;
-
- try {
- if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
- throw new Error('buffer is missing');
- }
- if (buffer.length < 1) {
- throw new Error('buffer is empty');
- }
-
- if (fullyQualifiedFormat) {
- const type_code = cursor.readUInt8();
- len++;
- if (type_code !== this.ioc.DataType.BULKSET) {
- throw new Error('unexpected {type_code}');
- }
- cursor = cursor.slice(1);
-
- if (cursor.length < 1) {
- throw new Error('{value_flag} is missing');
- }
- const value_flag = cursor.readUInt8();
- len++;
- if (value_flag === 1) {
- return { v: null, len };
- }
- if (value_flag !== 0) {
- throw new Error('unexpected {value_flag}');
- }
- cursor = cursor.slice(1);
- }
-
- // {length}
- let length, length_len;
- try {
- ({ v: length, len: length_len } = this.ioc.intSerializer.deserialize(cursor, false));
- len += length_len;
- } catch (err) {
- err.message = '{length}: ' + err.message;
- throw err;
- }
- if (length < 0) {
- throw new Error('{length} is less than zero');
- }
- cursor = cursor.slice(length_len);
-
- // Official GraphBinary 1.0 spec:
- // If the implementing language does not have a BulkSet object to deserialize into,
- // this format can be coerced to a List and still be considered compliant with Gremlin.
- // Simply "expand the bulk" by adding the item to the List the number of times specified by the bulk.
-
- // {item_0}...{item_n}
- let v = new Array();
- for (let i = 0; i < length; i++) {
- let value, value_len;
- try {
- ({ v: value, len: value_len } = this.ioc.anySerializer.deserialize(cursor));
- len += value_len;
- } catch (err) {
- err.message = `{item_${i}} value: ` + err.message;
- throw err;
- }
- cursor = cursor.slice(value_len);
-
- let bulk, bulk_len;
- try {
- ({ v: bulk, len: bulk_len } = this.ioc.longSerializer.deserialize(cursor, false));
- len += bulk_len;
- } catch (err) {
- err.message = `{item_${i}} bulk: ` + err.message;
- throw err;
- }
- if (bulk < 0) {
- throw new Error(`{item_${i}}: bulk is less than zero`);
- }
- if (bulk > 4294967295) {
- // arrayLength of Array() constructor is expected to be an integer between 0 and 2^32 - 1
- throw new Error(`{item_${i}}: bulk is greater than 2^32-1`);
- }
- cursor = cursor.slice(bulk_len);
-
- bulk = Number(bulk); // coersion to Number is required for BigInt if LongSerializerNg is used
- const item = new Array(bulk).fill(value);
- v = v.concat(item);
- }
-
- return { v, len };
- } catch (err) {
- throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
- }
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteSerializer.js
index f704c09cba..aeed10dbd2 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/ByteSerializer.js
@@ -42,7 +42,7 @@ export default class ByteSerializer {
bufs.push(Buffer.from([this.ioc.DataType.BYTE, 0x00]));
}
const v = Buffer.alloc(1);
- v.writeUInt8(item); // if item is not within uint8 limits writeUInt8 will error
+ v.writeInt8(item); // if item is not within int8 limits writeInt8 will error
bufs.push(v);
return Buffer.concat(bufs);
@@ -87,7 +87,7 @@ export default class ByteSerializer {
}
len += 1;
- const v = cursor.readUInt8();
+ const v = cursor.readInt8();
return { v, len };
} catch (err) {
throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DataType.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DataType.js
index bf5ac82b83..b15f714a36 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DataType.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DataType.js
@@ -30,9 +30,7 @@ const DataType = {
INT: 0x01,
LONG: 0x02,
STRING: 0x03,
- DATE: 0x04,
- TIMESTAMP: 0x05,
- CLASS: 0x06,
+ DATETIME: 0x04,
DOUBLE: 0x07,
FLOAT: 0x08,
LIST: 0x09,
@@ -45,54 +43,24 @@ const DataType = {
GRAPH: 0x10,
VERTEX: 0x11,
VERTEXPROPERTY: 0x12,
- BARRIER: 0x13,
- BINDING: 0x14,
- BYTECODE: 0x15,
- CARDINALITY: 0x16,
- COLUMN: 0x17,
DIRECTION: 0x18,
- OPERATOR: 0x19,
- ORDER: 0x1a,
- PICK: 0x1b,
- POP: 0x1c,
- LAMBDA: 0x1d,
- P: 0x1e,
- SCOPE: 0x1f,
T: 0x20,
- TRAVERSER: 0x21,
BIGDECIMAL: 0x22,
BIGINTEGER: 0x23,
BYTE: 0x24,
- BYTEBUFFER: 0x25,
+ BINARY: 0x25,
SHORT: 0x26,
BOOLEAN: 0x27,
- TEXTP: 0x28,
- TRAVERSALSTRATEGY: 0x29,
- BULKSET: 0x2a,
TREE: 0x2b,
- METRICS: 0x2c,
- TRAVERSALMETRICS: 0x2d,
MERGE: 0x2e,
- DT: 0x2f,
- GTYPE: 0x30,
CHAR: 0x80,
DURATION: 0x81,
- INETADDRESS: 0x82,
- INSTANT: 0x83,
- LOCALDATE: 0x84,
- LOCALDATETIME: 0x85,
- LOCALTIME: 0x86,
- MONTHDAY: 0x87,
- OFFSETDATETIME: 0x88,
- OFFSETTIME: 0x89,
- PERIOD: 0x8a,
- YEAR: 0x8b,
- YEARMONTH: 0x8c,
- ZONEDATETIME: 0x8d,
- ZONEOFFSET: 0x8e,
- CUSTOM: 0,
+ COMPOSITEPDT: 0xf0,
+ PRIMITIVEPDT: 0xf1,
+
+ MARKER: 0xfd,
UNSPECIFIED_NULL: 0xfe,
};
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/OffsetDateTimeSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DateTimeSerializer.js
similarity index 50%
rename from gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/OffsetDateTimeSerializer.js
rename to gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DateTimeSerializer.js
index d8a1d62918..a0b3ddd787 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/OffsetDateTimeSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DateTimeSerializer.js
@@ -19,11 +19,11 @@
import { Buffer } from 'buffer';
-export default class OffsetDateTimeSerializer {
- constructor(ioc, ID) {
+export default class DateTimeSerializer {
+ constructor(ioc) {
this.ioc = ioc;
- this.ID = ID;
- this.ioc.serializers[ID] = this;
+ this.ID = ioc.DataType.DATETIME;
+ this.ioc.serializers[this.ID] = this;
}
canBeUsedFor(value) {
@@ -35,7 +35,7 @@ export default class OffsetDateTimeSerializer {
if (fullyQualifiedFormat) {
return Buffer.from([this.ID, 0x01]);
}
- return Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
+ return Buffer.alloc(18);
}
const bufs = [];
@@ -43,39 +43,34 @@ export default class OffsetDateTimeSerializer {
bufs.push(Buffer.from([this.ID, 0x00]));
}
- // NOTE: js Date will always display time in UTC, but regular date/hour getters will return in local system time.
- // To avoid inconsistency we will always serialize the UTC representation of the Date object with offset of 0.
+ const v = Buffer.alloc(18);
+ let offset = 0;
- // {year}
- let v = Buffer.alloc(4);
- v.writeInt32BE(item.getUTCFullYear());
- bufs.push(v);
+ // Year (Int32BE)
+ v.writeInt32BE(item.getUTCFullYear(), offset);
+ offset += 4;
- // {month}
- v = Buffer.alloc(1);
- v.writeUInt8(item.getUTCMonth() + 1); // Java Core DateTime serializer uses 1 - 12 for months, JS uses indices
- bufs.push(v);
+ // Month (UInt8, 1-based)
+ v.writeUInt8(item.getUTCMonth() + 1, offset);
+ offset += 1;
- // {day} - in UTC
- v = Buffer.alloc(1);
- v.writeUInt8(item.getUTCDate());
- bufs.push(v);
+ // Day (UInt8, 1-based)
+ v.writeUInt8(item.getUTCDate(), offset);
+ offset += 1;
- // {nanoseconds}
- const h = item.getUTCHours(); // in UTC
- const m = item.getUTCMinutes();
- const s = item.getUTCSeconds();
- const ms = item.getUTCMilliseconds();
- const ns = h * 60 * 60 * 1e9 + m * 60 * 1e9 + s * 1e9 + ms * 1e6;
- v = Buffer.alloc(8);
- v.writeBigInt64BE(BigInt(ns));
- bufs.push(v);
+ // Nanoseconds since midnight (BigInt64BE)
+ const hours = item.getUTCHours();
+ const minutes = item.getUTCMinutes();
+ const seconds = item.getUTCSeconds();
+ const millis = item.getUTCMilliseconds();
+ const nanos = BigInt(hours * 3600 + minutes * 60 + seconds) * 1_000_000_000n + BigInt(millis) * 1_000_000n;
+ v.writeBigInt64BE(nanos, offset);
+ offset += 8;
- // {zone offset} - UTC is always used for serialization, as such offset will be 0
- v = Buffer.alloc(4);
- v.writeInt32BE(0);
- bufs.push(v);
+ // UTC offset in seconds (Int32BE) - always 0 for JS Date
+ v.writeInt32BE(0, offset);
+ bufs.push(v);
return Buffer.concat(bufs);
}
@@ -113,33 +108,50 @@ export default class OffsetDateTimeSerializer {
cursor = cursor.slice(1);
}
- if (cursor.length < 8) {
+ if (cursor.length < 18) {
throw new Error('unexpected {value} length');
}
len += 18;
- const year = cursor.readInt32BE();
- cursor = cursor.slice(4);
- const month = cursor.readUInt8() - 1;
- cursor = cursor.slice(1);
- const date = cursor.readUInt8();
- cursor = cursor.slice(1);
- const ns = cursor.readBigInt64BE();
- cursor = cursor.slice(8);
- const offset = cursor.readInt32BE();
- cursor.slice(4);
-
- // calculate hour, minute, second, and ms from ns as JS Date doesn't have ns precision
- const totalMS = ns / BigInt(1e6);
- const ms = Number(totalMS) % 1e3;
- const totalS = Math.trunc(Number(totalMS) / 1e3) - offset; // js Date doesn't have a way to set offset properly, account offset here to use UTC
- const s = totalS % 60;
- const totalM = Math.trunc(totalS / 60);
- const m = totalM % 60;
- const h = Math.trunc(totalM / 60);
-
- // use UTC time calculated with offset above
- const v = new Date(Date.UTC(year, month, date, h, m, s, ms));
+ let offset = 0;
+
+ // Read year (Int32BE)
+ const year = cursor.readInt32BE(offset);
+ offset += 4;
+
+ // Read month (UInt8, 1-based)
+ const month = cursor.readUInt8(offset);
+ offset += 1;
+
+ // Read day (UInt8, 1-based)
+ const day = cursor.readUInt8(offset);
+ offset += 1;
+
+ // Read nanoseconds since midnight (BigInt64BE)
+ const nanos = cursor.readBigInt64BE(offset);
+ offset += 8;
+
+ // Read UTC offset in seconds (Int32BE) - JS Date cannot represent non-zero offsets
+ const utcOffset = cursor.readInt32BE(offset);
+ offset += 4;
+
+ // Convert nanos to time components
+ const hours = Number(nanos / 3_600_000_000_000n);
+ const remainingNanos = nanos % 3_600_000_000_000n;
+ const minutes = Number(remainingNanos / 60_000_000_000n);
+ const remainingNanos2 = remainingNanos % 60_000_000_000n;
+ const seconds = Number(remainingNanos2 / 1_000_000_000n);
+ const millis = Number((remainingNanos2 % 1_000_000_000n) / 1_000_000n);
+
+ const v = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds, millis));
+ // Date.UTC treats years 0-99 as 1900-1999, correct it
+ if (year >= 0 && year <= 99) {
+ v.setUTCFullYear(year);
+ }
+ // Adjust for non-zero UTC offset (JS Date is always UTC internally)
+ if (utcOffset !== 0) {
+ v.setTime(v.getTime() - utcOffset * 1000);
+ }
return { v, len };
} catch (err) {
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EdgeSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EdgeSerializer.js
index d32b4a0ef6..339c8b692e 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EdgeSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EdgeSerializer.js
@@ -40,13 +40,13 @@ export default class EdgeSerializer {
return Buffer.from([this.ioc.DataType.EDGE, 0x01]);
}
const id = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00]; // String ''
- const label = [0x00, 0x00, 0x00, 0x00]; // ''
+ const label = [0x00, 0x00, 0x00, 0x00]; // empty list
const inVId = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00]; // String ''
- const inVLabel = [0x00, 0x00, 0x00, 0x00]; // ''
+ const inVLabel = [0x00, 0x00, 0x00, 0x00]; // empty list
const outVId = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00]; // String ''
- const outVLabel = [0x00, 0x00, 0x00, 0x00]; // ''
+ const outVLabel = [0x00, 0x00, 0x00, 0x00]; // empty list
const parent = [0xfe, 0x01]; // null
- const properties = [0xfe, 0x01]; // null
+ const properties = [0x09, 0x00, 0x00, 0x00, 0x00, 0x00]; // empty list
return Buffer.from([...id, ...label, ...inVId, ...inVLabel, ...outVId, ...outVLabel, ...parent, ...properties]);
}
@@ -59,7 +59,8 @@ export default class EdgeSerializer {
bufs.push(this.ioc.anySerializer.serialize(item.id));
// {label}
- bufs.push(this.ioc.stringSerializer.serialize(item.label, false));
+ const labels = Array.isArray(item.label) ? item.label : item.label ? [item.label] : [];
+ bufs.push(this.ioc.listSerializer.serialize(labels, false));
// {inVId}
const inVId = item.inV && item.inV.id;
@@ -67,7 +68,8 @@ export default class EdgeSerializer {
// {inVLabel}
const inVLabel = item.inV && item.inV.label;
- bufs.push(this.ioc.stringSerializer.serialize(inVLabel, false));
+ const inVLabels = Array.isArray(inVLabel) ? inVLabel : inVLabel ? [inVLabel] : [];
+ bufs.push(this.ioc.listSerializer.serialize(inVLabels, false));
// {outVId}
const outVId = item.outV && item.outV.id;
@@ -75,13 +77,14 @@ export default class EdgeSerializer {
// {outVLabel}
const outVLabel = item.outV && item.outV.label;
- bufs.push(this.ioc.stringSerializer.serialize(outVLabel, false));
+ const outVLabels = Array.isArray(outVLabel) ? outVLabel : outVLabel ? [outVLabel] : [];
+ bufs.push(this.ioc.listSerializer.serialize(outVLabels, false));
// {parent}
bufs.push(this.ioc.unspecifiedNullSerializer.serialize(null));
// {properties}
- bufs.push(this.ioc.unspecifiedNullSerializer.serialize(null));
+ bufs.push(this.ioc.listSerializer.serialize([], true));
return Buffer.concat(bufs);
}
@@ -132,7 +135,8 @@ export default class EdgeSerializer {
let label, label_len;
try {
- ({ v: label, len: label_len } = this.ioc.stringSerializer.deserialize(cursor, false));
+ ({ v: label, len: label_len } = this.ioc.listSerializer.deserialize(cursor, false));
+ label = Array.isArray(label) && label.length > 0 ? label[0] : label;
len += label_len;
} catch (err) {
err.message = '{label}: ' + err.message;
@@ -152,7 +156,8 @@ export default class EdgeSerializer {
let inVLabel, inVLabel_len;
try {
- ({ v: inVLabel, len: inVLabel_len } = this.ioc.stringSerializer.deserialize(cursor, false));
+ ({ v: inVLabel, len: inVLabel_len } = this.ioc.listSerializer.deserialize(cursor, false));
+ inVLabel = Array.isArray(inVLabel) && inVLabel.length > 0 ? inVLabel[0] : inVLabel;
len += inVLabel_len;
} catch (err) {
err.message = '{inVLabel}: ' + err.message;
@@ -172,7 +177,8 @@ export default class EdgeSerializer {
let outVLabel, outVLabel_len;
try {
- ({ v: outVLabel, len: outVLabel_len } = this.ioc.stringSerializer.deserialize(cursor, false));
+ ({ v: outVLabel, len: outVLabel_len } = this.ioc.listSerializer.deserialize(cursor, false));
+ outVLabel = Array.isArray(outVLabel) && outVLabel.length > 0 ? outVLabel[0] : outVLabel;
len += outVLabel_len;
} catch (err) {
err.message = '{outVLabel}: ' + err.message;
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EnumSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EnumSerializer.js
index cccbea723c..76f72234e5 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EnumSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/EnumSerializer.js
@@ -22,84 +22,48 @@
*/
import { Buffer } from 'buffer';
-import {
- barrier,
- cardinality,
- column,
- direction,
- dt,
- gType,
- merge,
- operator,
- order,
- pick,
- pop,
- scope,
- t as _t,
- EnumValue,
-} from '../../../../process/traversal.js';
+import { direction, t as _t, merge as _merge, EnumValue } from '../../../../process/traversal.js';
export default class EnumSerializer {
constructor(ioc) {
this.ioc = ioc;
+ // process/traversal.js:toEnum() lowercases element names (e.g. OUT => out) for end users' convenience
+ // but we need original mapping as is for wire format lookup
const to_orig_enum = (obj) => {
- // process/traversal.js:toEnum() changes original element name (e.g. OUT => out) for end users' convenience
- // but we need original mapping as is w/o additional time spent on case-insensititive comparison
const r = {};
Object.values(obj).forEach((e) => (r[e.elementName] = e));
return r;
};
- const DT = ioc.DataType;
- this.types = [
- { name: 'Barrier', code: DT.BARRIER, enum: to_orig_enum(barrier) },
- { name: 'Cardinality', code: DT.CARDINALITY, enum: to_orig_enum(cardinality) },
- { name: 'Column', code: DT.COLUMN, enum: to_orig_enum(column) },
- { name: 'Direction', code: DT.DIRECTION, enum: to_orig_enum(direction) },
- { name: 'DT', code: DT.DT, enum: to_orig_enum(dt) },
- { name: 'GType', code: DT.GTYPE, enum: to_orig_enum(gType) },
- { name: 'Merge', code: DT.MERGE, enum: to_orig_enum(merge) },
- { name: 'Operator', code: DT.OPERATOR, enum: to_orig_enum(operator) },
- { name: 'Order', code: DT.ORDER, enum: to_orig_enum(order) },
- { name: 'Pick', code: DT.PICK, enum: to_orig_enum(pick) },
- { name: 'Pop', code: DT.POP, enum: to_orig_enum(pop) },
- { name: 'Scope', code: DT.SCOPE, enum: to_orig_enum(scope) },
- { name: 'T', code: DT.T, enum: to_orig_enum(_t) },
- ];
- this.byname = {};
- this.bycode = {};
- for (const type of this.types) {
- this.ioc.serializers[type.code] = this;
- this.byname[type.name] = type;
- this.bycode[type.code] = type;
- }
+
+ this.types = {
+ Direction: { code: ioc.DataType.DIRECTION, enum: to_orig_enum(direction) },
+ Merge: { code: ioc.DataType.MERGE, enum: to_orig_enum(_merge) },
+ T: { code: ioc.DataType.T, enum: to_orig_enum(_t) },
+ };
+
+ this.ioc.serializers[ioc.DataType.DIRECTION] = this;
+ this.ioc.serializers[ioc.DataType.MERGE] = this;
+ this.ioc.serializers[ioc.DataType.T] = this;
}
canBeUsedFor(value) {
- if (!(value instanceof EnumValue)) {
- return false;
- }
- if (!this.byname[value.typeName]) {
- throw new Error(`EnumSerializer.serialize: typeName=${value.typeName} is not supported.`);
- }
-
- return true;
+ return value instanceof EnumValue && (value.typeName === 'Direction' || value.typeName === 'Merge' || value.typeName === 'T');
}
serialize(item, fullyQualifiedFormat = true) {
- const type = this.byname[item.typeName];
+ const type = this.types[item.typeName];
if (item.elementName === undefined || item.elementName === null) {
if (fullyQualifiedFormat) {
return Buffer.from([type.code, 0x01]);
}
- return Buffer.from([this.ioc.DataType.STRING, 0x00, 0x00, 0x00, 0x00, 0x00]);
+ return this.ioc.stringSerializer.serialize(null, false);
}
const bufs = [];
if (fullyQualifiedFormat) {
bufs.push(Buffer.from([type.code, 0x00]));
}
-
bufs.push(this.ioc.stringSerializer.serialize(item.elementName, true));
return Buffer.concat(bufs);
@@ -117,12 +81,17 @@ export default class EnumSerializer {
throw new Error('buffer is empty');
}
- let type = undefined;
+ let typeName;
if (fullyQualifiedFormat) {
const type_code = cursor.readUInt8();
len++;
- type = this.bycode[type_code];
- if (!type) {
+ if (type_code === this.ioc.DataType.DIRECTION) {
+ typeName = 'Direction';
+ } else if (type_code === this.ioc.DataType.MERGE) {
+ typeName = 'Merge';
+ } else if (type_code === this.ioc.DataType.T) {
+ typeName = 'T';
+ } else {
throw new Error(`unexpected {type_code}=${type_code}`);
}
cursor = cursor.slice(1);
@@ -149,13 +118,12 @@ export default class EnumSerializer {
err.message = 'elementName: ' + err.message;
throw err;
}
- cursor = cursor.slice(elementName_len);
let v;
- if (!type) {
- v = new EnumValue(undefined, elementName);
+ if (typeName) {
+ v = this.types[typeName].enum[elementName];
} else {
- v = type.enum[elementName]; // users are expected to work with maps like Map.get(T.id), i.e. it must be exactly the same object
+ v = new EnumValue(undefined, elementName);
}
return { v, len };
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LambdaSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LambdaSerializer.js
deleted file mode 100644
index 1e87a9c818..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LambdaSerializer.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-import { valueKey, LambdaSerializer as GraphsonLambdaSerializer } from '../../type-serializers.js';
-
-export default class LambdaSerializer {
- constructor(ioc) {
- this.ioc = ioc;
- // this.ioc.serializers[ioc.DataType.LAMBDA] = this; // it's not expected to be deserialized
- this.graphsonLambdaSerializer = new GraphsonLambdaSerializer();
- }
-
- canBeUsedFor(value) {
- return this.graphsonLambdaSerializer.canBeUsedFor(value);
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.LAMBDA, 0x01]);
- }
- const language = [0x00, 0x00, 0x00, 0x00]; // ''
- const script = [0x00, 0x00, 0x00, 0x00]; // ''
- const arguments_length = [0x00, 0x00, 0x00, 0x00]; // 0
- return Buffer.from([...language, ...script, ...arguments_length]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.LAMBDA, 0x00]));
- }
-
- const graphson = this.graphsonLambdaSerializer.serialize(item);
- const language = graphson[valueKey].language;
- const script = graphson[valueKey].script;
- const arguments_ = graphson[valueKey]['arguments'];
-
- // {language}
- bufs.push(this.ioc.stringSerializer.serialize(language, false));
-
- // {script}
- bufs.push(this.ioc.stringSerializer.serialize(script, false));
-
- // {arguments_length}
- bufs.push(this.ioc.intSerializer.serialize(arguments_, false));
-
- return Buffer.concat(bufs);
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializer.js
index 823a312f0b..745ea58315 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializer.js
@@ -93,8 +93,7 @@ export default class LongSerializer {
let v = cursor.readBigInt64BE();
if (v < Number.MIN_SAFE_INTEGER || v > Number.MAX_SAFE_INTEGER) {
- // TODO: It tries to keep the same contract as GraphSON LongSerializer provides.
- // Is it still appropriate to do so? Should we consider LongSerializerNg?
+ // Keeps the same contract as GraphSON LongSerializer — converts to Number (loses precision beyond 2^53).
v = parseFloat(v.toString());
} else {
v = Number(v);
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializerNg.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializerNg.js
deleted file mode 100644
index fbbde85aac..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/LongSerializerNg.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-
-// TODO: it's based on BigInt native JavaScript type to completely support
-// 64 bits integers, but for backward compatibility with current GraphSON
-// implementation we do not use this for now. Consider its removal.
-export default class LongSerializerNg {
- constructor(ioc) {
- this.ioc = ioc;
- // this.ioc.serializers[ioc.DataType.LONG] = this; // disabled, see AnySerializer.deserialize()
- }
-
- canBeUsedFor() {
- // it's not expected to be used
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.LONG, 0x01]);
- }
- return Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.LONG, 0x00]));
- }
- const v = Buffer.alloc(8);
- v.writeBigInt64BE(BigInt(item));
- bufs.push(v);
-
- return Buffer.concat(bufs);
- }
-
- deserialize(buffer, fullyQualifiedFormat = true) {
- let len = 0;
- let cursor = buffer;
-
- try {
- if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
- throw new Error('buffer is missing');
- }
- if (buffer.length < 1) {
- throw new Error('buffer is empty');
- }
-
- if (fullyQualifiedFormat) {
- const type_code = cursor.readUInt8();
- len++;
- if (type_code !== this.ioc.DataType.LONG) {
- throw new Error('unexpected {type_code}');
- }
- cursor = cursor.slice(1);
-
- if (cursor.length < 1) {
- throw new Error('{value_flag} is missing');
- }
- const value_flag = cursor.readUInt8();
- len++;
- if (value_flag === 1) {
- return { v: null, len };
- }
- if (value_flag !== 0) {
- throw new Error('unexpected {value_flag}');
- }
- cursor = cursor.slice(1);
- }
-
- if (cursor.length < 8) {
- throw new Error('unexpected {value} length');
- }
- len += 8;
-
- const v = cursor.readBigInt64BE();
- return { v, len };
- } catch (err) {
- throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
- }
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MapSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MapSerializer.js
index 9bed8d462f..b9d0b38eaa 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MapSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MapSerializer.js
@@ -99,10 +99,10 @@ export default class MapSerializer {
}
const value_flag = cursor.readUInt8();
len++;
- if (value_flag === 1) {
+ if (value_flag === 0x01) {
return { v: null, len };
}
- if (value_flag !== 0) {
+ if (value_flag !== 0x00 && value_flag !== 0x02) {
throw new Error('unexpected {value_flag}');
}
cursor = cursor.slice(1);
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DateSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MarkerSerializer.js
similarity index 57%
rename from gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DateSerializer.js
rename to gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MarkerSerializer.js
index 076e2d5de7..2b0a785ab7 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/DateSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/MarkerSerializer.js
@@ -17,41 +17,12 @@
* under the License.
*/
-/**
- * @author Igor Ostapenko
- */
-
import { Buffer } from 'buffer';
-export default class DateSerializer {
- constructor(ioc, ID) {
+export default class MarkerSerializer {
+ constructor(ioc) {
this.ioc = ioc;
- this.ID = ID;
- this.ioc.serializers[ID] = this;
- }
-
- canBeUsedFor(value) {
- return value instanceof Date;
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ID, 0x01]);
- }
- return Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ID, 0x00]));
- }
-
- const v = Buffer.alloc(8);
- v.writeBigInt64BE(BigInt(item.getTime()));
- bufs.push(v);
-
- return Buffer.concat(bufs);
+ this.ioc.serializers[ioc.DataType.MARKER] = this;
}
deserialize(buffer, fullyQualifiedFormat = true) {
@@ -62,41 +33,33 @@ export default class DateSerializer {
if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
throw new Error('buffer is missing');
}
- if (buffer.length < 1) {
- throw new Error('buffer is empty');
+ if (buffer.length < (fullyQualifiedFormat ? 3 : 1)) {
+ throw new Error('buffer is too short for marker');
}
if (fullyQualifiedFormat) {
const type_code = cursor.readUInt8();
len++;
- if (type_code !== this.ID) {
+ if (type_code !== this.ioc.DataType.MARKER) {
throw new Error('unexpected {type_code}');
}
cursor = cursor.slice(1);
- if (cursor.length < 1) {
- throw new Error('{value_flag} is missing');
- }
const value_flag = cursor.readUInt8();
len++;
- if (value_flag === 1) {
- return { v: null, len };
- }
if (value_flag !== 0) {
throw new Error('unexpected {value_flag}');
}
cursor = cursor.slice(1);
}
- if (cursor.length < 8) {
- throw new Error('unexpected {value} length');
+ const value = cursor.readUInt8();
+ len++;
+ if (value !== 0) {
+ throw new Error('unexpected marker value');
}
- len += 8;
-
- const ms = cursor.readBigInt64BE();
- const v = new Date(Number(ms));
- return { v, len };
+ return { v: 'marker', len };
} catch (err) {
throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/NumberSerializationStrategy.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/NumberSerializationStrategy.js
index eda906257c..1950ac20f5 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/NumberSerializationStrategy.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/NumberSerializationStrategy.js
@@ -48,7 +48,8 @@ export default class NumberSerializationStrategy {
Number.isNaN(item) ||
item === Number.POSITIVE_INFINITY ||
item === Number.NEGATIVE_INFINITY ||
- !Number.isInteger(item)
+ !Number.isInteger(item) ||
+ Object.is(item, -0)
) {
return this.ioc.doubleSerializer.serialize(item, fullyQualifiedFormat);
}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/PSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/PSerializer.js
deleted file mode 100644
index 58260329e3..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/PSerializer.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-import { P } from '../../../../process/traversal.js';
-
-export default class PSerializer {
- constructor(ioc) {
- this.ioc = ioc;
- this.ioc.serializers[ioc.DataType.P] = this;
- }
-
- canBeUsedFor(value) {
- return value instanceof P;
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.P, 0x01]);
- }
- const name = [0x00, 0x00, 0x00, 0x00]; // ''
- const values_length = [0x00, 0x00, 0x00, 0x00]; // 0
- return Buffer.from([...name, ...values_length]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.P, 0x00]));
- }
-
- // {name}
- bufs.push(this.ioc.stringSerializer.serialize(item.operator, false));
-
- // {values_length}{value_0}...{value_n}
- //
- // This is a tricky part due to the nature of t.P.
- // GraphBinary states that {name} is followed by list only,
- // but t.P may be constructed such way that its item.value can be
- // a usual string or something, that's why we should care here
- // to get it wrapped into a list.
- //
- // It tries to resemble the same if-else structure as
- // GraphSON.PSerializer.serialize() does.
- let list;
- if (item.other === undefined || item.other === null) {
- if (Array.isArray(item.value)) {
- list = item.value;
- } else {
- list = [item.value];
- }
- } else {
- list = [item.value, item.other];
- }
- bufs.push(this.ioc.listSerializer.serialize(list, false));
-
- return Buffer.concat(bufs);
- }
-
- deserialize(buffer, fullyQualifiedFormat = true) {
- let len = 0;
- let cursor = buffer;
-
- try {
- if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
- throw new Error('buffer is missing');
- }
- if (buffer.length < 1) {
- throw new Error('buffer is empty');
- }
-
- if (fullyQualifiedFormat) {
- const type_code = cursor.readUInt8();
- len++;
- if (type_code !== this.ioc.DataType.P) {
- throw new Error('unexpected {type_code}');
- }
- cursor = cursor.slice(1);
-
- if (cursor.length < 1) {
- throw new Error('{value_flag} is missing');
- }
- const value_flag = cursor.readUInt8();
- len++;
- if (value_flag === 1) {
- return { v: null, len };
- }
- if (value_flag !== 0) {
- throw new Error('unexpected {value_flag}');
- }
- cursor = cursor.slice(1);
- }
-
- let name, name_len;
- try {
- ({ v: name, len: name_len } = this.ioc.stringSerializer.deserialize(cursor, false));
- len += name_len;
- } catch (err) {
- err.message = '{name}: ' + err.message;
- throw err;
- }
- cursor = cursor.slice(name_len);
-
- let values, values_len;
- try {
- ({ v: values, len: values_len } = this.ioc.listSerializer.deserialize(cursor, false));
- len += values_len;
- } catch (err) {
- err.message = '{values}: ' + err.message;
- throw err;
- }
- cursor = cursor.slice(values_len);
-
- if (values.length < 1) {
- return { v: new P(''), len };
- }
-
- let v;
- const P_static = P[name];
- if (typeof P_static === 'function') {
- v = P_static(...values); // it's better to follow existing logic which may depend on an operator name
- } else {
- v = new P(name, ...values);
- }
-
- return { v, len };
- } catch (err) {
- throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
- }
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/SetSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/SetSerializer.js
index fa5ddecaf0..623b5ebd11 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/SetSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/SetSerializer.js
@@ -67,6 +67,7 @@ export default class SetSerializer {
deserialize(buffer, fullyQualifiedFormat = true) {
let len = 0;
let cursor = buffer;
+ let isBulked = false;
try {
if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
@@ -92,9 +93,10 @@ export default class SetSerializer {
if (valueFlag === 1) {
return { v: null, len };
}
- if (valueFlag !== 0) {
+ if (valueFlag !== 0 && valueFlag !== 2) {
throw new Error('unexpected {value_flag}');
}
+ isBulked = valueFlag === 2;
cursor = cursor.slice(1);
}
@@ -122,7 +124,20 @@ export default class SetSerializer {
throw err;
}
cursor = cursor.slice(valueLen);
- v.add(value);
+
+ if (isBulked) {
+ if (cursor.length < 8) {
+ throw new Error(`{item_${i}}: bulk count is missing`);
+ }
+ const bulkCount = cursor.readBigInt64BE();
+ len += 8;
+ cursor = cursor.slice(8);
+
+ // Set.add is idempotent; bulk count only affects cardinality, not Set membership
+ v.add(value);
+ } else {
+ v.add(value);
+ }
}
return { v, len };
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/SetSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/StubSerializer.js
similarity index 72%
rename from gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/SetSerializer-test.js
rename to gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/StubSerializer.js
index cfac40b99c..c49c12f4a1 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/SetSerializer-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/StubSerializer.js
@@ -17,10 +17,14 @@
* under the License.
*/
-/**
- * @author Igor Ostapenko
- */
-
-import SetSerializerTestTemplate from './SetSerializerTestTemplate.js';
-
-SetSerializerTestTemplate({ ID: 0x0b, name: 'Set' });
+export default class StubSerializer {
+ constructor(ioc, typeCode, typeName) {
+ this.ioc = ioc;
+ this.typeCode = typeCode;
+ this.typeName = typeName;
+ this.ioc.serializers[typeCode] = this;
+ }
+ deserialize() {
+ throw new Error(`${this.typeName} deserialization is not yet implemented`);
+ }
+}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TextPSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TextPSerializer.js
deleted file mode 100644
index 61acd103dd..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TextPSerializer.js
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-import { TextP } from '../../../../process/traversal.js';
-
-export default class TextPSerializer {
- constructor(ioc) {
- this.ioc = ioc;
- this.ioc.serializers[ioc.DataType.TEXTP] = this;
- }
-
- canBeUsedFor(value) {
- return value instanceof TextP;
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.TEXTP, 0x01]);
- }
- const name = [0x00, 0x00, 0x00, 0x00]; // ''
- const values_length = [0x00, 0x00, 0x00, 0x00]; // 0
- return Buffer.from([...name, ...values_length]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.TEXTP, 0x00]));
- }
-
- // {name} is a String
- bufs.push(this.ioc.stringSerializer.serialize(item.operator, false));
-
- // {values_length}{value_0}...{value_n}
- // It tries to resemble the same if-else structure as
- // GraphSON.TextPSerializer.serialize() does.
- let list;
- if (item.other === undefined || item.other === null) {
- // follows the same idea as for t.P
- if (Array.isArray(item.value)) {
- list = item.value;
- } else {
- list = [item.value];
- }
- } else {
- list = [item.value, item.other];
- }
- bufs.push(this.ioc.listSerializer.serialize(list, false));
-
- return Buffer.concat(bufs);
- }
-
- deserialize(buffer, fullyQualifiedFormat = true) {
- let len = 0;
- let cursor = buffer;
-
- try {
- if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
- throw new Error('buffer is missing');
- }
- if (buffer.length < 1) {
- throw new Error('buffer is empty');
- }
-
- if (fullyQualifiedFormat) {
- const type_code = cursor.readUInt8();
- len++;
- if (type_code !== this.ioc.DataType.TEXTP) {
- throw new Error('unexpected {type_code}');
- }
- cursor = cursor.slice(1);
-
- if (cursor.length < 1) {
- throw new Error('{value_flag} is missing');
- }
- const value_flag = cursor.readUInt8();
- len++;
- if (value_flag === 1) {
- return { v: null, len };
- }
- if (value_flag !== 0) {
- throw new Error('unexpected {value_flag}');
- }
- cursor = cursor.slice(1);
- }
-
- let name, name_len;
- try {
- ({ v: name, len: name_len } = this.ioc.stringSerializer.deserialize(cursor, false));
- len += name_len;
- } catch (err) {
- err.message = '{name}: ' + err.message;
- throw err;
- }
- cursor = cursor.slice(name_len);
-
- let values, values_len;
- try {
- ({ v: values, len: values_len } = this.ioc.listSerializer.deserialize(cursor, false));
- len += values_len;
- } catch (err) {
- err.message = '{values}: ' + err.message;
- throw err;
- }
- cursor = cursor.slice(values_len);
-
- if (values.length < 1) {
- return { v: new TextP(''), len };
- }
-
- let v;
- const TextP_static = TextP[name];
- if (typeof TextP_static === 'function') {
- v = TextP_static(...values); // it's better to follow existing logic which may depend on an operator name
- } else {
- v = new TextP(name, ...values);
- }
-
- return { v, len };
- } catch (err) {
- throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
- }
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TraversalStrategySerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TraversalStrategySerializer.js
deleted file mode 100644
index af82ca0a12..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TraversalStrategySerializer.js
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-
-import { TraversalStrategySerializer as GraphsonTraversalStrategySerializer } from '../../type-serializers.js';
-
-export default class TraversalStrategySerializer {
- constructor(ioc) {
- this.ioc = ioc;
- this.graphsonTraversalStrategySerializer = new GraphsonTraversalStrategySerializer();
- }
-
- canBeUsedFor(value) {
- return this.graphsonTraversalStrategySerializer.canBeUsedFor(value);
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.TRAVERSALSTRATEGY, 0x01]);
- }
- const strategy_class = [0x00, 0x00, 0x00, 0x00]; // ''
- const configuration = [0x00, 0x00, 0x00, 0x00]; // {}
- return Buffer.from([...strategy_class, ...configuration]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.TRAVERSALSTRATEGY, 0x00]));
- }
-
- const conf = {};
- for (const k in item.configuration) {
- if (item.configuration.hasOwnProperty(k)) {
- conf[k] = item.configuration[k];
- }
- }
-
- // {strategy_class}
- bufs.push(this.ioc.classSerializer.serialize(item.constructor, false));
-
- // {configuration}
- bufs.push(this.ioc.mapSerializer.serialize(conf, false));
-
- return Buffer.concat(bufs);
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TraverserSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TraverserSerializer.js
deleted file mode 100644
index 1758d949ee..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/TraverserSerializer.js
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { Buffer } from 'buffer';
-import { Traverser } from '../../../../process/traversal.js';
-
-export default class TraverserSerializer {
- constructor(ioc) {
- this.ioc = ioc;
- this.ioc.serializers[ioc.DataType.TRAVERSER] = this;
- }
-
- canBeUsedFor(value) {
- return value instanceof Traverser;
- }
-
- serialize(item, fullyQualifiedFormat = true) {
- if (item === undefined || item === null) {
- if (fullyQualifiedFormat) {
- return Buffer.from([this.ioc.DataType.TRAVERSER, 0x01]);
- }
- const bulk = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]; // 1
- const value = [0xfe, 0x01]; // null
- return Buffer.from([...bulk, ...value]);
- }
-
- const bufs = [];
- if (fullyQualifiedFormat) {
- bufs.push(Buffer.from([this.ioc.DataType.TRAVERSER, 0x00]));
- }
-
- // {bulk}
- bufs.push(this.ioc.longSerializer.serialize(item.bulk, false));
- // {value}
- bufs.push(this.ioc.anySerializer.serialize(item.object));
-
- return Buffer.concat(bufs);
- }
-
- deserialize(buffer, fullyQualifiedFormat = true) {
- let len = 0;
- let cursor = buffer;
-
- try {
- if (buffer === undefined || buffer === null || !(buffer instanceof Buffer)) {
- throw new Error('buffer is missing');
- }
- if (buffer.length < 1) {
- throw new Error('buffer is empty');
- }
-
- if (fullyQualifiedFormat) {
- const type_code = cursor.readUInt8();
- len++;
- if (type_code !== this.ioc.DataType.TRAVERSER) {
- throw new Error('unexpected {type_code}');
- }
- cursor = cursor.slice(1);
-
- if (cursor.length < 1) {
- throw new Error('{value_flag} is missing');
- }
- const value_flag = cursor.readUInt8();
- len++;
- if (value_flag === 1) {
- return { v: null, len };
- }
- if (value_flag !== 0) {
- throw new Error('unexpected {value_flag}');
- }
- cursor = cursor.slice(1);
- }
-
- let bulk, bulk_len;
- try {
- ({ v: bulk, len: bulk_len } = this.ioc.longSerializer.deserialize(cursor, false));
- len += bulk_len;
- } catch (err) {
- err.message = '{bulk}: ' + err.message;
- throw err;
- }
- if (bulk < 0) {
- throw new Error('{bulk} is less than zero');
- }
- cursor = cursor.slice(bulk_len);
-
- let value, value_len;
- try {
- ({ v: value, len: value_len } = this.ioc.anySerializer.deserialize(cursor));
- len += value_len;
- } catch (err) {
- err.message = '{value}: ' + err.message;
- throw err;
- }
- cursor = cursor.slice(value_len);
-
- const v = new Traverser(value, bulk);
- return { v, len };
- } catch (err) {
- throw this.ioc.utils.des_error({ serializer: this, args: arguments, cursor, err });
- }
- }
-}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js
index 5c529d7283..4e86d5b94b 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexPropertySerializer.js
@@ -41,10 +41,10 @@ export default class VertexPropertySerializer {
}
return Buffer.concat([
this.ioc.unspecifiedNullSerializer.serialize(null), // {id}=null
- this.ioc.stringSerializer.serialize('', false), // {label}=''
+ this.ioc.listSerializer.serialize([], false), // {label}=empty list
this.ioc.unspecifiedNullSerializer.serialize(null), // {value}=null
this.ioc.unspecifiedNullSerializer.serialize(null), // {parent}=null
- this.ioc.unspecifiedNullSerializer.serialize(null), // {properties}=null
+ this.ioc.listSerializer.serialize([], true), // {properties}=empty list
]);
}
@@ -57,7 +57,8 @@ export default class VertexPropertySerializer {
bufs.push(this.ioc.anySerializer.serialize(item.id));
// {label}
- bufs.push(this.ioc.stringSerializer.serialize(item.label, false));
+ const labels = Array.isArray(item.label) ? item.label : item.label ? [item.label] : [];
+ bufs.push(this.ioc.listSerializer.serialize(labels, false));
// {value}
bufs.push(this.ioc.anySerializer.serialize(item.value));
@@ -66,7 +67,7 @@ export default class VertexPropertySerializer {
bufs.push(this.ioc.unspecifiedNullSerializer.serialize(null));
// {properties}
- bufs.push(this.ioc.anySerializer.serialize(item.properties));
+ bufs.push(this.ioc.listSerializer.serialize([], true));
return Buffer.concat(bufs);
}
@@ -116,10 +117,11 @@ export default class VertexPropertySerializer {
}
cursor = cursor.slice(id_len);
- // {label} is a String value
+ // {label} is a List value
let label, label_len;
try {
- ({ v: label, len: label_len } = this.ioc.stringSerializer.deserialize(cursor, false));
+ ({ v: label, len: label_len } = this.ioc.listSerializer.deserialize(cursor, false));
+ label = Array.isArray(label) && label.length > 0 ? label[0] : label;
len += label_len;
} catch (err) {
err.message = '{label}: ' + err.message;
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexSerializer.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexSerializer.js
index 4171b63486..5cd18ae6c0 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexSerializer.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/binary/internals/VertexSerializer.js
@@ -40,8 +40,8 @@ export default class VertexSerializer {
return Buffer.from([this.ioc.DataType.VERTEX, 0x01]);
}
const id = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00]; // String ''
- const label = [0x00, 0x00, 0x00, 0x00]; // ''
- const properties = [0xfe, 0x01]; // null
+ const label = [0x00, 0x00, 0x00, 0x00]; // empty list
+ const properties = [0x09, 0x00, 0x00, 0x00, 0x00, 0x00]; // empty list
return Buffer.from([...id, ...label, ...properties]);
}
@@ -54,10 +54,11 @@ export default class VertexSerializer {
bufs.push(this.ioc.anySerializer.serialize(item.id));
// {label}
- bufs.push(this.ioc.stringSerializer.serialize(item.label, false));
+ const labels = Array.isArray(item.label) ? item.label : item.label ? [item.label] : [];
+ bufs.push(this.ioc.listSerializer.serialize(labels, false));
// {properties}
- bufs.push(this.ioc.anySerializer.serialize(item.properties));
+ bufs.push(this.ioc.listSerializer.serialize([], true));
return Buffer.concat(bufs);
}
@@ -108,7 +109,8 @@ export default class VertexSerializer {
let label, label_len;
try {
- ({ v: label, len: label_len } = this.ioc.stringSerializer.deserialize(cursor, false));
+ ({ v: label, len: label_len } = this.ioc.listSerializer.deserialize(cursor, false));
+ label = Array.isArray(label) && label.length > 0 ? label[0] : label;
len += label_len;
} catch (err) {
err.message = '{label}: ' + err.message;
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/AnySerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/AnySerializer-test.js
deleted file mode 100644
index 9e42fb70cf..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/AnySerializer-test.js
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { DataType, anySerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-import { Vertex, VertexProperty, Edge, Path, Property } from '../../../lib/structure/graph.js';
-import { Traverser, P, TextP, EnumValue } from '../../../lib/process/traversal.js';
-import { OptionsStrategy } from '../../../lib/process/traversal-strategy.js';
-
-import { GraphTraversal } from '../../../lib/process/graph-traversal.js';
-const g = () => new GraphTraversal(undefined, undefined);
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.AnySerializer', () => {
-
- describe('#serialize', () => {
- [
- /*
- This is the most complex part of GraphBinary,
- we are expected to guess right serializer, i.e. right type.
-
- Let's follow existing structure/io/graph-serializer.GraphSON3Writer.adaptObject() logic
- of serializer/type selection and add the rest of the types.
-
- This test suite is the documentation and set of examples of type inference.
- */
-
- // NumberSerializationStrategy
- // Double
- { v:0.1, b:[DataType.DOUBLE,0x00, 0x3F,0xB9,0x99,0x99,0x99,0x99,0x99,0x9A] },
- { v:0.375, b:[DataType.DOUBLE,0x00, 0x3F,0xD8,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:0.00390625, b:[DataType.DOUBLE,0x00, 0x3F,0x70,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:Infinity, b:[DataType.DOUBLE,0x00, 0x7F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:-Infinity, b:[DataType.DOUBLE,0x00, 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:NaN, b:[DataType.DOUBLE,0x00, 0x7F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00] },
- // Int
- { v:0, b:[DataType.INT,0x00, 0x00,0x00,0x00,0x00] },
- { v:1, b:[DataType.INT,0x00, 0x00,0x00,0x00,0x01] },
- { v:2147483647, b:[DataType.INT,0x00, 0x7F,0xFF,0xFF,0xFF] }, // INT32_MAX
- { v:-2147483648, b:[DataType.INT,0x00, 0x80,0x00,0x00,0x00] }, // INT32_MIN
- { v:-1, b:[DataType.INT,0x00, 0xFF,0xFF,0xFF,0xFF] },
- // Long
- { v:2147483648, b:[DataType.LONG,0x00, 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00] }, // INT32_MAX+1
- { v:-2147483649, b:[DataType.LONG,0x00, 0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF] }, // INT32_MIN-1
- { v:9007199254740991, b:[DataType.LONG,0x00, 0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] }, // Number.MAX_SAFE_NUMBER
- { v:-9007199254740991, b:[DataType.LONG,0x00, 0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x01] }, // Number.MIN_SAFE_NUMBER
- // BigInteger
- { v:128n, b:[DataType.BIGINTEGER,0x00, 0x00,0x00,0x00,0x02, 0x00,0x80] },
- { v:-1n, b:[DataType.BIGINTEGER,0x00, 0x00,0x00,0x00,0x01, 0xFF] },
- // BigDecimal
- // TODO
- // Yes, Float and Short are not used
-
- // OffestDateTimeSerializer
- { v:new Date(1651436603000),
- b:[DataType.OFFSETDATETIME,0x00, 0x00,0x00,0x07,0xe6,0x05,0x01,0x00,0x00,0x42,0xc2,0x77,0xbd,0x8e,0x00,0x00,0x00,0x00,0x00] },
- { v:new Date('2023-08-02T01:23:45-07:30'),
- b:[DataType.OFFSETDATETIME,0x00, 0x00,0x00,0x07,0xe7,0x08,0x02,0x00,0x00,0x1d,0x20,0x66,0xbf,0xba,0x00,0x00,0x00,0x00,0x00] },
-
-
-
- // TraverserSerializer
- { v: new Traverser("A1", 16),
- b: [
- DataType.TRAVERSER,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
- DataType.STRING,0x00, 0x00,0x00,0x00,0x02, 0x41,0x31,
- ]
- },
-
- // TraversalStrategySerializer
- { v: new OptionsStrategy({ 'B': 1, 'A': 2 }),
- b: [
- DataType.TRAVERSALSTRATEGY,0x00,
- 0x00,0x00,0x00,0x52, ...from('org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy'),
- 0x00,0x00,0x00,0x02,
- // 'B':1
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42,
- 0x01,0x00, 0x00,0x00,0x00,0x01,
- // 'A':2
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41,
- 0x01,0x00, 0x00,0x00,0x00,0x02,
- ]
- },
-
- // PSerializer
- { v: P.eq('marko'),
- b: [
- DataType.P,0x00,
- 0x00,0x00,0x00,0x02, ...from('eq'),
- 0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('marko'),
- ]
- },
-
- // TextPSerializer
- { v: TextP.containing('ValuE'),
- b: [
- DataType.TEXTP,0x00,
- 0x00,0x00,0x00,0x0A, ...from('containing'),
- 0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('ValuE'),
- ]
- },
-
- // LambdaSerializer
- { v:function() { return 'Script_1'; },
- b:[
- DataType.LAMBDA,0x00,
- 0x00,0x00,0x00,0x0E, ...from('gremlin-groovy'),
- 0x00,0x00,0x00,0x08, ...from('Script_1'),
- 0xFF,0xFF,0xFF,0xFF,
- ]
- },
-
- // EnumSerializer (actually represents different enum like types)
- { v: new EnumValue('Barrier', 'normSack'),
- b: [ DataType.BARRIER,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x08, ...from('normSack') ]
- },
- { v: new EnumValue('Cardinality', 'single'),
- b: [ DataType.CARDINALITY,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x06, ...from('single') ]
- },
- { v: new EnumValue('Column', 'keys'),
- b: [ DataType.COLUMN,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x04, ...from('keys') ]
- },
- { v: new EnumValue('Direction', 'OUT'),
- b: [ DataType.DIRECTION,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x03, ...from('OUT') ]
- },
- { v: new EnumValue('DT', 'minute'),
- b: [ DataType.DT,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x06, ...from('minute') ]
- },
- { v: new EnumValue('Merge', 'onMatch'),
- b: [ DataType.MERGE,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x07, ...from('onMatch') ]
- },
- { v: new EnumValue('GType', 'BYTE'),
- b: [ DataType.GTYPE,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x04, ...from('byte') ]
- },
- { v: new EnumValue('Operator', 'addAll'),
- b: [ DataType.OPERATOR,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x06, ...from('addAll') ]
- },
- { v: new EnumValue('Order', 'desc'),
- b: [ DataType.ORDER,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x04, ...from('desc') ]
- },
- { v: new EnumValue('Pick', 'any'),
- b: [ DataType.PICK,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x03, ...from('any') ]
- },
- { v: new EnumValue('Pop', 'first'),
- b: [ DataType.POP,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x05, ...from('first') ]
- },
- { v: new EnumValue('Scope', 'local'),
- b: [ DataType.SCOPE,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x05, ...from('local') ]
- },
- { v: new EnumValue('T', 'id'),
- b: [ DataType.T,0x00, DataType.STRING,0x00, 0x00,0x00,0x00,0x02, ...from('id') ]
- },
-
- // VertexSerializer
- { v: new Vertex('A', 'Person', []),
- b: [
- DataType.VERTEX,0x00,
- DataType.STRING,0x00, 0x00,0x00,0x00,0x01, 0x41, // {id}
- 0x00,0x00,0x00,0x06, ...from('Person'), // {label}
- 0x09,0x00,0x00,0x00,0x00,0x00, // {properties}
- ]
- },
-
- // EdgeSerializer
- { v:new Edge('A', new Vertex('B','Person',null), 'has', new Vertex('C','Pet',null), []),
- b:[
- DataType.EDGE,0x00,
- DataType.STRING,0x00, 0x00,0x00,0x00,0x01, 0x41, // id
- 0x00,0x00,0x00,0x03, ...from('has'), // label
- DataType.STRING,0x00, 0x00,0x00,0x00,0x01, 0x43, // inVId
- 0x00,0x00,0x00,0x03, ...from('Pet'), // inVLabel
- DataType.STRING,0x00, 0x00,0x00,0x00,0x01, 0x42, // outVId
- 0x00,0x00,0x00,0x06, ...from('Person'), // outVLabel
- 0xFE,0x01, // parent
- 0xFE,0x01, // properties
- ]
- },
-
- // PathSerializer
- { v:new Path([ ['A','B'], ['C','D'] ], [ 1,-1 ]),
- b:[
- DataType.PATH,0x00,
- // {labels}
- DataType.LIST,0x00, 0x00,0x00,0x00,0x02,
- // ['A','B']
- 0x09,0x00, 0x00,0x00,0x00,0x02,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42,
- // ['C','D']
- 0x09,0x00, 0x00,0x00,0x00,0x02,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x43,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x44,
- // {objects}
- DataType.LIST,0x00, 0x00,0x00,0x00,0x02,
- 0x01,0x00, 0x00,0x00,0x00,0x01,
- 0x01,0x00, 0xFF,0xFF,0xFF,0xFF,
- ]
- },
-
- // PropertySerializer
- {
- v:new Property('Key', [ 'value' ]),
- b:[
- DataType.PROPERTY,0x00,
- 0x00,0x00,0x00,0x03, ...from('Key'),
- 0x09,0x00, 0x00,0x00,0x00,0x01, // list
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('value'),
- 0xFE,0x01, // parent
- ]
- },
-
- // GraphSerializer
- // TODO: it's ignored for now
-
- // VertexPropertySerializer
- { v:new VertexProperty('00010203-0405-0607-0809-0a0b0c0d0e0f', 'Label', 42),
- b:[
- 0x12,0x00,
- 0x03,0x00, 0x00,0x00,0x00,0x24, ...from('00010203-0405-0607-0809-0a0b0c0d0e0f'),
- 0x00,0x00,0x00,0x05, ...from('Label'),
- 0x01,0x00, 0x00,0x00,0x00,0x2A,
- 0xFE,0x01,
- 0x09,0x00, 0x00,0x00,0x00,0x00,
- ]
- },
-
- // BindingSerializer
- // TODO: it's ignored for now
-
- // LongSerializer
- // TODO +
-
- // ListSerializer
- { v:[], b:[DataType.LIST,0x00, 0x00,0x00,0x00,0x00] },
- { v:[1], b:[DataType.LIST,0x00, 0x00,0x00,0x00,0x01, 0x01,0x00, 0x00,0x00,0x00,0x01] },
-
- // SetSerializer
- // TODO: It's not expected to be serialized as GraphSON does. Is it still okay?
-
- // MapSerializer
- { v: new Map([ ['A',3] ]),
- b: [
- DataType.MAP,0x00,
- 0x00,0x00,0x00,0x01, // {length}
- 0x03,0x00,0x00,0x00,0x00,0x01,0x41, // A
- 0x01,0x00,0x00,0x00,0x00,0x03 // 3
- ]
- },
-
- // BulkSetSerializer
- // TODO: it's ignored and not expected to be used from serialization point of view
-
- // Default (strings / objects / ...)
- // TODO: align with Java.parse(GraphSON) logic
-
- // ByteSerializer
- // TODO: it's ignored and not expected to be used from serialization point of view
-
- // ByteBufferSerializer
- { v:from([0x00,0x01,0xFF]), b:[DataType.BYTEBUFFER,0x00, 0x00,0x00,0x00,0x03, 0x00,0x01,0xFF]},
-
- // BooleanSerializer
- { v:true, b:[DataType.BOOLEAN,0x00, 0x01] },
- { v:false, b:[DataType.BOOLEAN,0x00, 0x00] },
-
- // StringSerializer
- { v:'A1', b:[DataType.STRING,0x00, 0x00,0x00,0x00,0x02, 0x41,0x31] },
- { v:'', b:[DataType.STRING,0x00, 0x00,0x00,0x00,0x00] },
-
- // Object
- { v: { 'B': 2 },
- b: [
- DataType.MAP,0x00,
- 0x00,0x00,0x00,0x01, // {length}
- 0x03,0x00,0x00,0x00,0x00,0x01,0x42, // B
- 0x01,0x00,0x00,0x00,0x00,0x02 // 2
- ]
- },
-
- // UnspecifiedNullSerializer
- { v:null, fq:1, b:[0xFE,0x01] },
- { v:undefined, fq:1, b:[0xFE,0x01] },
-
- ].forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( anySerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual(anySerializer.serialize(v, true), b);
- assert.deepEqual(anySerializer.serialize(v, false), b.slice(2));
- }));
-
- it(`should error if value is unsupported`, () => assert.throws(
- () => anySerializer.serialize( Symbol('sym1') ),
- { message: "No serializer found to support item where typeof(item)='symbol' and String(item)='Symbol(sym1)'." }
- ));
-
- });
-
- describe('#deserialize', () =>
- [
- { err:/buffer is missing/, b:undefined },
- { err:/buffer is missing/, b:undefined },
- { err:/buffer is missing/, b:null },
- { err:/buffer is missing/, b:null },
- { err:/buffer is empty/, b:[] },
- { err:/buffer is empty/, b:[] },
-
- { err:/unknown {type_code}/, b:[0x40] }, // tests an unassigned type code
- { err:/unknown {type_code}/, b:[0x8F] },
- { err:/unknown {type_code}/, b:[0xFF] },
-
- // this is like a register of supported type deserializers:
-
- // INT
- { v:null, b:[0x01,0x01] },
- { v:1, b:[0x01,0x00, 0x00,0x00,0x00,0x01] },
-
- // LONG
- { v:null, b:[0x02,0x01] },
- { v:1, b:[0x02,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01] },
-
- // STRING
- { v:null, b:[0x03,0x01] },
- { v:'Ab0', b:[0x03,0x00, 0x00,0x00,0x00,0x03, 0x41,0x62,0x30] },
-
- // DATE
- { v:null, b:[0x04,0x01] },
- { v:new Date('1969-12-31T23:59:59.999Z'), b:[0x04,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
-
- // OFFSETDATETIME
- { v:null, b:[0x88,0x01] },
- { v:new Date('2023-08-02T01:30:00-10:00'),
- b:[0x88,0x00,
- 0x00,0x00,0x07,0xe7,
- 0x08,0x02,
- 0x00,0x00,0x04,0xe9,0x49,0x14,0xf0,0x00,
- 0xFF,0xFF,0x73,0x60] },
-
- // TIMESTAMP
- { v:null, b:[0x05,0x01] },
- { v:new Date('1969-12-31T23:59:59.999Z'), b:[0x05,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
-
- // DOUBLE
- { v:null, b:[0x07,0x01] },
- { v:0.00390625, b:[0x07,0x00, 0x3F,0x70,0x00,0x00,0x00,0x00,0x00,0x00] },
-
- // FLOAT
- { v:null, b:[0x08,0x01] },
- { v:0.375, b:[0x08,0x00, 0x3E,0xC0,0x00,0x00] },
-
- // LIST
- { v:null, b:[0x09,0x01] },
- { v:[], b:[0x09,0x00, 0x00,0x00,0x00,0x00] },
-
- // MAP
- { v:null, b:[0x0A,0x01] },
- { v:new Map(), b:[0x0A,0x00, 0x00,0x00,0x00,0x00] },
-
- // SET
- // TODO: Is it still okay to follow GraphSON where Set and List are usual JS ArrayS?
- { v:null, b:[0x0B,0x01] },
- { v:new Set(), b:[0x0B,0x00, 0x00,0x00,0x00,0x00] },
-
- // UUID
- { v:null, b:[0x0C,0x01] },
- { v:'00010203-0405-0607-0809-0a0b0c0d0e0f', b:[0x0C,0x00, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F] },
-
- // EDGE
- { v:null, b:[0x0D,0x01] },
- { v:new Edge(1, new Vertex(2,'Person',null), 'has', new Vertex(3,'Pet',null), []),
- b:[
- 0x0D,0x00,
- 0x01,0x00, 0x00,0x00,0x00,0x01, // id
- 0x00,0x00,0x00,0x03, ...from('has'), // label
- 0x01,0x00, 0x00,0x00,0x00,0x03, // inVId
- 0x00,0x00,0x00,0x03, ...from('Pet'), // inVLabel
- 0x01,0x00, 0x00,0x00,0x00,0x02, // outVId
- 0x00,0x00,0x00,0x06, ...from('Person'), // outVLabel
- 0xFE,0x01, // parent
- 0xFE,0x01, // properties
- ]
- },
-
- // PATH
- { v:null, b:[0x0E,0x01] },
- { v:new Path([ ['B','A'], ['D'] ], [ -1 ]),
- b:[
- 0x0E,0x00,
- // {labels}
- 0x09,0x00, 0x00,0x00,0x00,0x02,
- // ['B','A']
- 0x09,0x00, 0x00,0x00,0x00,0x02,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41,
- // ['D']
- 0x09,0x00, 0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x44,
- // {objects}
- 0x09,0x00, 0x00,0x00,0x00,0x01,
- 0x01,0x00, 0xFF,0xFF,0xFF,0xFF,
- ]
- },
-
- // PROPERTY
- { v:null, b:[0x0F,0x01] },
- {
- v:new Property('Key', [ 'value' ]),
- b:[
- 0x0F,0x00,
- 0x00,0x00,0x00,0x03, ...from('Key'),
- 0x09,0x00, 0x00,0x00,0x00,0x01, // list
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('value'),
- 0xFE,0x01, // parent
- ]
- },
-
- // GRAPH
- // TODO: it's ignored for now
-
- // VERTEX
- { v:null, b:[0x11,0x01] },
- { v:new Vertex('00010203-0405-0607-0809-0a0b0c0d0e0f', 'A', []),
- b:[0x11,0x00, 0x0C,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x00,0x00,0x00,0x01,0x41, 0xFE,0x01]
- },
-
- // VERTEXPROPERTY
- { v:null, b:[0x12,0x01] },
- { v:new VertexProperty('00010203-0405-0607-0809-0a0b0c0d0e0f', 'Label', 42, []),
- b:[
- 0x12,0x00,
- 0x0C,0x00, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
- 0x00,0x00,0x00,0x05, ...from('Label'),
- 0x01,0x00, 0x00,0x00,0x00,0x2A,
- 0xFE,0x01,
- 0xFE,0x01,
- ]
- },
-
- // BARRIER
- { v:null, b:[0x13,0x01] },
- { v:new EnumValue('Barrier','normSack'), b:[0x13,0x00, 0x03,0x00, 0x00,0x00,0x00,0x08, ...from('normSack')] },
-
- // BINDING
- // TODO: it's ignored for now
-
-
-
- // CARDINALITY
- { v:null, b:[0x16,0x01] },
- { v:new EnumValue('Cardinality', 'set'), b:[0x16,0x00, 0x03,0x00, 0x00,0x00,0x00,0x03, ...from('set')] },
-
- // COLUMN
- { v:null, b:[0x17,0x01] },
- { v:new EnumValue('Column','keys'), b:[0x17,0x00, 0x03,0x00, 0x00,0x00,0x00,0x04, ...from('keys')] },
-
- // DIRECTION
- { v:null, b:[0x18,0x01] },
- { v:new EnumValue('Direction','OUT'), b:[0x18,0x00, 0x03,0x00, 0x00,0x00,0x00,0x03, ...from('OUT')] },
-
- // DT
- { v:null, b:[0x2f,0x01] },
- { v:new EnumValue('DT','minute'), b:[0x2f,0x00, 0x03,0x00, 0x00,0x00,0x00,0x06, ...from('minute')] },
-
- // GType
- { v:null, b:[0x30,0x01] },
- { v:new EnumValue('GType','BYTE'), b:[0x30,0x00, 0x03,0x00, 0x00,0x00,0x00,0x04, ...from('BYTE')] },
-
- // MERGE
- { v:null, b:[0x2e,0x01] },
- { v:new EnumValue('Merge','onCreate'), b:[0x2e,0x00, 0x03,0x00, 0x00,0x00,0x00,0x08, ...from('onCreate')] },
-
- // OPERATOR
- { v:null, b:[0x19,0x01] },
- { v:new EnumValue('Operator','addAll'), b:[0x19,0x00, 0x03,0x00, 0x00,0x00,0x00,0x06, ...from('addAll')] },
-
- // ORDER
- { v:null, b:[0x1A,0x01] },
- { v:new EnumValue('Order','desc'), b:[0x1A,0x00, 0x03,0x00, 0x00,0x00,0x00,0x04, ...from('desc')] },
-
- // PICK
- { v:null, b:[0x1B,0x01] },
- { v:new EnumValue('Pick','any'), b:[0x1B,0x00, 0x03,0x00, 0x00,0x00,0x00,0x03, ...from('any')] },
-
- // POP
- { v:null, b:[0x1C,0x01] },
- { v:new EnumValue('Pop','first'), b:[0x1C,0x00, 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('first')] },
-
- // LAMBDA
- // TODO: it's not expected to be deserialized, is it correct assumption?
-
- // P
- { v:P.eq(7), b:[0x1E,0x00, 0x00,0x00,0x00,0x02, ...from('eq'), 0x00,0x00,0x00,0x01, 0x01,0x00,0x00,0x00,0x00,0x07] },
-
- // SCOPE
- { v:null, b:[0x1F,0x01] },
- { v:new EnumValue('Scope','local'), b:[0x1F,0x00, 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('local')] },
-
- // T
- { v:null, b:[0x20,0x01] },
- { v:new EnumValue('T','id'), b:[0x20,0x00, 0x03,0x00, 0x00,0x00,0x00,0x02, ...from('id')] },
-
- // TRAVERSER
- { v:null, b:[0x21,0x01] },
- { v:new Traverser('A', 2), b:[0x21,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, 0x03,0x00,0x00,0x00,0x00,0x01,0x41] },
-
- // BIGINTEGER
- { v:null, b:[0x23,0x01] },
- { v:1n, b:[0x23,0x00, 0x00,0x00,0x00,0x01, 0x01] },
-
- // BYTE
- { v:null, b:[0x24,0x01] },
- { v:255, b:[0x24,0x00, 0xFF] },
-
- // BYTEBUFFER
- { v:null, b:[0x25,0x01] },
- { v:from([0xFF,0x00,0x01]), b:[0x25,0x00, 0x00,0x00,0x00,0x03, 0xFF,0x00,0x01] },
-
- // SHORT
- { v:null, b:[0x26,0x01] },
- { v:32767, b:[0x26,0x00, 0x7F,0xFF] },
-
- // BOOLEAN
- { v:null, b:[0x27,0x01] },
- { v:true, b:[0x27,0x00, 0x01] },
-
- // TEXTP
- { v:null, b:[0x28,0x01] },
- { v:TextP.containing('ValuE'),
- b:[
- 0x28,0x00,
- 0x00,0x00,0x00,0x0A, ...from('containing'),
- 0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('ValuE'),
- ]
- },
-
- // TRAVERSALSTRATEGY
- // It's not expected to be deserialized
-
- // BULKSET
- { v:null, b:[0x2A,0x01] },
- { v:[ 'C', 'C', 'C' ],
- b:[
- 0x2A,0x00,
- 0x00,0x00,0x00,0x01, // {length}
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x43, // 'C'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, // bulk
- ]
- },
-
- // UNSPECIFIED_NULL
- { v:null, b:[0xFE,0x01] },
-
- // TODO: "register" other types
- ]
- .forEach(({ v, b, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- assert.throws(() => anySerializer.deserialize(b), { message: err });
- return;
- }
-
- const len = b.length;
- assert.deepStrictEqual( anySerializer.deserialize(b), {v,len} );
- }))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ArraySerializerTestTemplate.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ArraySerializerTestTemplate.js
deleted file mode 100644
index a300412fb6..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ArraySerializerTestTemplate.js
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { intSerializer, serializers } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-export default ({ ID, name }) => {
-
-describe(`GraphBinary.${name}Serializer`, () => {
-
- const type_code = from([ID]);
- const value_flag = from([0x00]);
-
- const serializer = serializers[ID];
-
- const cases = [
- { v:undefined, fq:1, b:[ID,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:[] },
- { v:null, fq:1, b:[ID,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:[] },
-
- { v:[], b:[0x00,0x00,0x00,0x00] },
- { v:[2147483647], b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x7F,0xFF,0xFF,0xFF] },
- { v:[-1,'A'], b:[0x00,0x00,0x00,0x02, 0x01,0x00,0xFF,0xFF,0xFF,0xFF, 0x03,0x00,0x00,0x00,0x00,0x01,0x41] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID-1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID+1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x89] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x19] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x90] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[ID] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0xFF] },
-
- { des:1, err:/{length} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length} is less than zero/, b:[0x80,0x00,0x00,0x00] },
- ];
-
- describe('#serialize', () => {
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( serializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( serializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( serializer.serialize(v, false), concat([ b]) );
- }));
-
- it.skip('should not error if array length is INT32_MAX'); // TODO: resource heavy
-
- it('should error if array length is greater than INT32_MAX', () => assert.throws(
- () => serializer.serialize(new Array(intSerializer.INT32_MAX+1)),
- { message: new RegExp(`Array length=${intSerializer.INT32_MAX+1} is greater than supported max_length=${intSerializer.INT32_MAX}`) }
- ));
- });
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => serializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => serializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => serializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( serializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( serializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( serializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: [], e: true },
- { v: [0], e: true },
- { v: [undefined], e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( serializer.canBeUsedFor(v), e )
- ))
- );
-
-});
-
-};
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BigIntegerSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BigIntegerSerializer-test.js
deleted file mode 100644
index 8480dbea96..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BigIntegerSerializer-test.js
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { bigIntegerSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.BigIntegerSerializer', () => {
-
- const type_code = from([0x23]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x23,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x01, 0x00], av:0n },
- { v:null, fq:1, b:[0x23,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x01, 0x00], av:0n },
-
- { v:0n, b:[0x00,0x00,0x00,0x01, 0x00] },
- { v:1n, b:[0x00,0x00,0x00,0x01, 0x01] },
- { v:127n, b:[0x00,0x00,0x00,0x01, 0x7F] },
- { v:128n, b:[0x00,0x00,0x00,0x02, 0x00,0x80] },
- { v:160n, b:[0x00,0x00,0x00,0x02, 0x00,0xA0] },
- { v:32767n, b:[0x00,0x00,0x00,0x02, 0x7F,0xFF] },
- { v:32768n, b:[0x00,0x00,0x00,0x03, 0x00,0x80,0x00] },
- { v:8388607n, b:[0x00,0x00,0x00,0x03, 0x7F,0xFF,0xFF] },
- { v:8388608n, b:[0x00,0x00,0x00,0x04, 0x00,0x80,0x00,0x00] },
- { v:2147483647n, b:[0x00,0x00,0x00,0x04, 0x7F,0xFF,0xFF,0xFF] },
- { v:2147483648n, b:[0x00,0x00,0x00,0x05, 0x00,0x80,0x00,0x00,0x00] },
- { v:549755813887n, b:[0x00,0x00,0x00,0x05, 0x7F,0xFF,0xFF,0xFF,0xFF] },
- { v:549755813888n, b:[0x00,0x00,0x00,0x06, 0x00,0x80,0x00,0x00,0x00,0x00] },
- { v:140737488355327n, b:[0x00,0x00,0x00,0x06, 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:140737488355328n, b:[0x00,0x00,0x00,0x07, 0x00,0x80,0x00,0x00,0x00,0x00,0x00] },
- { v:36028797018963967n, b:[0x00,0x00,0x00,0x07, 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:36028797018963968n, b:[0x00,0x00,0x00,0x08, 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:9223372036854775807n, b:[0x00,0x00,0x00,0x08, 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:9223372036854775808n, b:[0x00,0x00,0x00,0x09, 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:2361183241434822606847n, b:[0x00,0x00,0x00,0x09, 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:2361183241434822606848n, b:[0x00,0x00,0x00,0x0A, 0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:604462909807314587353087n, b:[0x00,0x00,0x00,0x0A, 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
-
- { v:-1n, b:[0x00,0x00,0x00,0x01, 0xFF] },
- { v:-128n, b:[0x00,0x00,0x00,0x01, 0x80] },
- { v:-129n, b:[0x00,0x00,0x00,0x02, 0xFF,0x7F] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x02, 0xFF,0xFF] },
- { v:-32768n, b:[0x00,0x00,0x00,0x02, 0x80,0x00] },
- { v:-32769n, b:[0x00,0x00,0x00,0x03, 0xFF,0x7F,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x03, 0xFF,0xFF,0xFF] },
- { v:-8388608n, b:[0x00,0x00,0x00,0x03, 0x80,0x00,0x00] },
- { v:-8388609n, b:[0x00,0x00,0x00,0x04, 0xFF,0x7F,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x04, 0xFF,0xFF,0xFF,0xFF] },
- { v:-2147483648n, b:[0x00,0x00,0x00,0x04, 0x80,0x00,0x00,0x00] },
- { v:-2147483649n, b:[0x00,0x00,0x00,0x05, 0xFF,0x7F,0xFF,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x05, 0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-549755813888n, b:[0x00,0x00,0x00,0x05, 0x80,0x00,0x00,0x00,0x00] },
- { v:-549755813889n, b:[0x00,0x00,0x00,0x06, 0xFF,0x7F,0xFF,0xFF,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x06, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-140737488355328n, b:[0x00,0x00,0x00,0x06, 0x80,0x00,0x00,0x00,0x00,0x00] },
- { v:-140737488355329n, b:[0x00,0x00,0x00,0x07, 0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x07, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-36028797018963968n, b:[0x00,0x00,0x00,0x07, 0x80,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:-36028797018963969n, b:[0x00,0x00,0x00,0x08, 0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x08, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-9223372036854775808n, b:[0x00,0x00,0x00,0x08, 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:-9223372036854775809n, b:[0x00,0x00,0x00,0x09, 0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x09, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-2361183241434822606848n, b:[0x00,0x00,0x00,0x09, 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:-2361183241434822606849n, b:[0x00,0x00,0x00,0x0A, 0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-1n, des:1, b:[0x00,0x00,0x00,0x0A, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-604462909807314587353088n, b:[0x00,0x00,0x00,0x0A, 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:-604462909807314587353089n, b:[0x00,0x00,0x00,0x0B, 0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x03] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x32] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x22] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x24] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x23] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x23,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x23,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x23,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x23,0xFF] },
-
- { des:1, err:/{length}=.* is less than one/, b:[0x00,0x00,0x00,0x00] },
- { des:1, err:/{length}=.* is less than one/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length}=.* is less than one/, b:[0xFF,0xFF,0xFF,0xFE] },
- { des:1, err:/{length}=.* is less than one/, b:[0x80,0x00,0x00,0x00] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( bigIntegerSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( bigIntegerSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( bigIntegerSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => bigIntegerSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => bigIntegerSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => bigIntegerSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( bigIntegerSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( bigIntegerSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( bigIntegerSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [undefined], e: false },
- { v: 0n, e: true },
- { v: BigInt(1), e: true },
- { v: 0, e: false },
- { v: 1, e: false },
- { v: -1, e: false },
- { v: 2147483647, e: false },
- { v: 2147483648, e: false },
- { v: -2147483648, e: false },
- { v: -2147483649, e: false },
- { v: 0.1, e: false },
- { v: Infinity, e: false },
- { v: -Infinity, e: false },
- { v: NaN, e: false },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( bigIntegerSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BooleanSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BooleanSerializer-test.js
deleted file mode 100644
index 96b45d52e1..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BooleanSerializer-test.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { booleanSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.BooleanSerializer', () => {
-
- const type_code = from([0x27]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x27,0x01], av:null },
- { v:undefined, fq:0, b:[0x00], av:false },
- { v:null, fq:1, b:[0x27,0x01] },
- { v:null, fq:0, b:[0x00], av:false },
- { v:false, b:[0x00] },
- { v:true, b:[0x01] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x26] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x28] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x72] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x27] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x27,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x27,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x27,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x27,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x27,0x00] },
-
- { des:1, err:/unexpected boolean byte/, b:[0x02] },
- { des:1, err:/unexpected boolean byte/, b:[0x03] },
- { des:1, err:/unexpected boolean byte/, b:[0x10] },
- { des:1, err:/unexpected boolean byte/, b:[0x0F] },
- { des:1, err:/unexpected boolean byte/, b:[0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( booleanSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( booleanSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( booleanSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => booleanSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => booleanSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => booleanSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( booleanSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( booleanSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( booleanSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: [], e: false },
- { v: [true], e: false },
- { v: 0n, e: false },
- { v: 0, e: false },
- { v: 1, e: false },
- { v: -1, e: false },
- { v: true, e: true },
- { v: false, e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( booleanSerializer.canBeUsedFor(v), e )
- ))
- );
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BulkSetSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BulkSetSerializer-test.js
deleted file mode 100644
index c1288a6f29..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/BulkSetSerializer-test.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { des_title } from './utils.js';
-import assert from 'assert';
-import { bulkSetSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.BulkSetSerializer', () => {
-
- const type_code = from([0x2A]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x2A, 0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:[] },
- { v:null, fq:1, b:[0x2A, 0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:[] },
-
- { v:[],
- b:[0x00,0x00,0x00,0x00,
- ]
- },
-
- { v:[ 'A' ],
- b:[0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // bulk
- ]
- },
-
- { v:[ 'A', 'A' ],
- b:[0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // bulk
- ]
- },
-
- { v:[ ],
- b:[0x00,0x00,0x00,0x01,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // bulk
- ]
- },
-
- { v:[ 'A', 'A' ],
- b:[0x00,0x00,0x00,0x02,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // bulk
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // bulk
- ]
- },
-
- { v:[ 15, 'B' ],
- b:[0x00,0x00,0x00,0x02,
- 0x01,0x00, 0x00,0x00,0x00,0x0F, // 15
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // bulk
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42, // 'B'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // bulk
- ]
- },
-
- { v:[ -1, -1, -1, 'B', [], [] ],
- b:[0x00,0x00,0x00,0x03,
- 0x01,0x00, 0xFF,0xFF,0xFF,0xFF, // -1
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03, // bulk
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42, // 'B'
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, // bulk
- 0x09,0x00, 0x00,0x00,0x00,0x00, // []
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // bulk
- ]
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x09] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xA2] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x29] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x2B] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x20] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x2A] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x2A,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x2A,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x2A,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x2A,0xFF] },
-
- { des:1, err:/{length} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length} is less than zero/, b:[0x80,0x00,0x00,0x00] },
-
- { des:1, err:/{item_0}: bulk is less than zero/, b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x00,0x00,0x00,0x00, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{item_0}: bulk is less than zero/, b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x00,0x00,0x00,0x00, 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { des:1, err:/{item_0}: bulk is greater than 2\^32-1/, b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00] },
- ];
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => bulkSetSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => bulkSetSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => bulkSetSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( bulkSetSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( bulkSetSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( bulkSetSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ByteBufferSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ByteBufferSerializer-test.js
deleted file mode 100644
index affaa69b6f..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ByteBufferSerializer-test.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { byteBufferSerializer, intSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-import { constants } from 'buffer';
-
-describe(`GraphBinary.ByteBufferSerializer`, () => {
-
- const type_code = from([0x25]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x25,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:[] },
- { v:null, fq:1, b:[0x25,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:[] },
-
- { v:[], b:[0x00,0x00,0x00,0x00] },
- { v:[0x01], b:[0x00,0x00,0x00,0x01, 0x01] },
- { v:[0xFF,0x00], b:[0x00,0x00,0x00,0x02, 0xFF,0x00] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x25-1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x25+1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x52] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x25] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x25,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x25,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x25,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x25,0xFF] },
-
- { des:1, err:/{length} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length} is less than zero/, b:[0x80,0x00,0x00,0x00] },
-
- { des:1, err:/unexpected actual {value} length/, b:[0x00,0x00,0x00,0x02, 0x01] },
- ];
-
- describe('#serialize', () => {
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
- if (v)
- v = from(v);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( byteBufferSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( byteBufferSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( byteBufferSerializer.serialize(v, false), concat([ b]) );
- }));
-
- it.skip('should not error if buffer length is INT32_MAX');
-
- // Buffer.size limit depends on Node version and runtime, see https://nodejs.org/docs/latest/api/buffer.html#bufferconstantsmax_length
- if (constants.MAX_LENGTH < intSerializer.INT32_MAX+1)
- it.skip(`should error if buffer length is greater than INT32_MAX - cannot be tested due to buffer.constants.MAX_LENGTH=${constants.MAX_LENGTH} < INT32_MAX+1=${intSerializer.INT32_MAX+1}`);
- else
- it('should error if buffer length is greater than INT32_MAX', () => assert.throws(
- () => byteBufferSerializer.serialize(Buffer.alloc(intSerializer.INT32_MAX+1)),
- { message: new RegExp(`Buffer length=${intSerializer.INT32_MAX+1} is greater than supported max_length=${intSerializer.INT32_MAX}`) }
- ));
- });
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => byteBufferSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => byteBufferSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => byteBufferSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- if (v)
- v = from(v);
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( byteBufferSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( byteBufferSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( byteBufferSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new Buffer([])], e: false },
- { v: new Buffer([]), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( byteBufferSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ByteSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ByteSerializer-test.js
deleted file mode 100644
index bb6eaeb0ed..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ByteSerializer-test.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { byteSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.ByteSerializer', () => {
-
- const type_code = from([0x24]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x24,0x01], av:null },
- { v:undefined, fq:0, b:[0x00], av:0 },
- { v:null, fq:1, b:[0x24,0x01] },
- { v:null, fq:0, b:[0x00], av:0 },
- { v:0, b:[0x00] },
- { v:1, b:[0x01] },
- { v:16, b:[0x10] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x02] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x23] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x25] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x42] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x24] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x24,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x24,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x24,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x24,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x24,0x00] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( byteSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( byteSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( byteSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => byteSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => byteSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => byteSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( byteSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( byteSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( byteSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DateSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DateSerializer-test.js
deleted file mode 100644
index 6ef008bec8..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DateSerializer-test.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import DateSerializerTestTemplate from './DateSerializerTestTemplate.js';
-
-DateSerializerTestTemplate({ ID: 0x04, name: 'Date' });
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DateSerializerTestTemplate.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DateSerializerTestTemplate.js
deleted file mode 100644
index 243ec5620c..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DateSerializerTestTemplate.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { serializers } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-export default ({ ID, name }) => {
-
-describe(`GraphBinary.${name}Serializer`, () => {
-
- const type_code = from([ID]);
- const value_flag = from([0x00]);
-
- const serializer = serializers[ID];
-
- const cases = [
- { v:undefined, fq:1, b:[ID,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:new Date(0) },
- { v:null, fq:1, b:[ID,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:new Date(0) },
-
- { v:new Date('1970-01-01T00:00:00.000Z'), b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:new Date('1969-12-31T23:59:59.999Z'), b:[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID-1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID+1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x40] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x50] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x14] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xF4] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x15] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xF5] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[ID] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[ID,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- { des:1, err:/unexpected {value} length/, b:[0x11,0x22,0x33,0x44, 0x05,0x06,0x07] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( serializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( serializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( serializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => serializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => serializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => serializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( serializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( serializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( serializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new P()], e: false },
- { v: [new Date()], e: false },
- { v: new Date(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( serializer.canBeUsedFor(v), e )
- ))
- );
-
-});
-
-};
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DoubleSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DoubleSerializer-test.js
deleted file mode 100644
index a383d5ad56..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/DoubleSerializer-test.js
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { doubleSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.DoubleSerializer', () => {
-
- const type_code = from([0x07]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x07,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:0 },
- { v:null, fq:1, b:[0x07,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:0 },
-
- { v:1, b:[0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:0.1, b:[0x3F,0xB9,0x99,0x99,0x99,0x99,0x99,0x9A] },
- { v:0.375, b:[0x3F,0xD8,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:0.00390625, b:[0x3F,0x70,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:Infinity, b:[0x7F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:-Infinity, b:[0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:NaN, b:[0x7F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x06] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x08] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x70] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x77] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x07] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x07,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x07,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x07,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x07,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x07,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- { des:1, err:/unexpected {value} length/, b:[0x11,0x22,0x33,0x44,0x55,0x66,0x77] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( doubleSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( doubleSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( doubleSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => doubleSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => doubleSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => doubleSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( doubleSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( doubleSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( doubleSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [undefined], e: false },
- { v: 0n, e: false },
- { v: BigInt(1), e: false },
- { v: 0, e: false },
- { v: 1, e: false },
- { v: -1, e: false },
- { v: 2147483647, e: false },
- { v: 2147483648, e: false },
- { v: -2147483648, e: false },
- { v: -2147483649, e: false },
- { v: 0.1, e: true },
- { v: Infinity, e: true },
- { v: -Infinity, e: true },
- { v: NaN, e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( doubleSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/EdgeSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/EdgeSerializer-test.js
deleted file mode 100644
index b4426ce731..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/EdgeSerializer-test.js
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { edgeSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-import { Edge, Vertex } from '../../../lib/structure/graph.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.EdgeSerializer', () => {
-
- const type_code = from([0x0D]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x0D,0x01], av:null },
- { v:undefined, fq:0,
- b:[
- 0x03,0x00, 0x00,0x00,0x00,0x00, // {id}=''
- 0x00,0x00,0x00,0x00, // {label}=''
- 0x03,0x00, 0x00,0x00,0x00,0x00, // {inVId}=''
- 0x00,0x00,0x00,0x00, // {inVLabel}=''
- 0x03,0x00, 0x00,0x00,0x00,0x00, // {outVId}=''
- 0x00,0x00,0x00,0x00, // {outVLabel}=''
- 0xFE,0x01, // parent
- 0xFE,0x01, // properties
- ],
- av:new Edge('', new Vertex('','',null), '', new Vertex('','',null), []),
- },
- { v:null, fq:1, b:[0x0D,0x01] },
- { v:null, fq:0,
- b:[
- 0x03,0x00, 0x00,0x00,0x00,0x00, // {id}=''
- 0x00,0x00,0x00,0x00, // {label}=''
- 0x03,0x00, 0x00,0x00,0x00,0x00, // {inVId}=''
- 0x00,0x00,0x00,0x00, // {inVLabel}=''
- 0x03,0x00, 0x00,0x00,0x00,0x00, // {outVId}=''
- 0x00,0x00,0x00,0x00, // {outVLabel}=''
- 0xFE,0x01, // parent
- 0xFE,0x01, // properties
- ],
- av:new Edge('', new Vertex('','',null), '', new Vertex('','',null), []),
- },
-
- { v:new Edge('A', new Vertex('B','Person',null), 'has', new Vertex('C','Pet',null), []),
- b:[
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // id
- 0x00,0x00,0x00,0x03, ...from('has'), // label
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x43, // inVId
- 0x00,0x00,0x00,0x03, ...from('Pet'), // inVLabel
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42, // outVId
- 0x00,0x00,0x00,0x06, ...from('Person'), // outVLabel
- 0xFE,0x01, // parent
- 0xFE,0x01, // properties
- ]
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0C] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0E] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xD0] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x0D] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0D,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0D,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0D,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0D,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( edgeSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( edgeSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( edgeSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => edgeSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => edgeSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => edgeSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( edgeSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( edgeSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( edgeSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new Vertex()], e: false },
- { v: new Vertex(), e: false },
- { v: [new Edge()], e: false },
- { v: new Edge(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( edgeSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/EnumSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/EnumSerializer-test.js
deleted file mode 100644
index 379bda0c8f..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/EnumSerializer-test.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { enumSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { barrier, cardinality, column, direction, operator, order, pick, pop, scope, t, n, EnumValue } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.EnumSerializer', () => {
-
- const types = [
- { name: 'Barrier', code: from([0x13]), enum: barrier },
- { name: 'Cardinality', code: from([0x16]), enum: cardinality },
- { name: 'Column', code: from([0x17]), enum: column },
- { name: 'Direction', code: from([0x18]), enum: direction },
- { name: 'Operator', code: from([0x19]), enum: operator },
- { name: 'Order', code: from([0x1A]), enum: order },
- { name: 'Pick', code: from([0x1B]), enum: pick },
- { name: 'Pop', code: from([0x1C]), enum: pop },
- { name: 'Scope', code: from([0x1F]), enum: scope },
- { name: 'T', code: from([0x20]), enum: t },
- ];
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x01], av:null },
- { v:undefined, fq:0, b:[0x03,0x00, 0x00,0x00,0x00,0x00], av:'' },
- { v:null, fq:1, b:[0x01] },
- { v:null, fq:0, b:[0x03,0x00, 0x00,0x00,0x00,0x00], av:'' },
-
- // real cases of serialization covered by AnySerializer#serialize tests
-
- { des:1, err:/buffer is missing/, fq:1, B:undefined },
- { des:1, err:/buffer is missing/, fq:0, B:undefined },
- { des:1, err:/buffer is missing/, fq:1, B:null },
- { des:1, err:/buffer is missing/, fq:0, B:null },
- { des:1, err:/buffer is empty/, fq:1, B:[] },
- { des:1, err:/buffer is empty/, fq:0, B:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0x12] },
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0x14] },
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0x1D] },
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0x21] },
- { des:1, err:/unexpected {type_code}/, fq:1, B:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0xFF] },
-
- { des:1, err:/elementName: .*StringSerializer.* unexpected {value} length/, B:[0x03,0x00, 0x00,0x00,0x00] },
- ];
-
- describe('#serialize', () =>
- types.forEach((type) => describe(`${type.name}`, () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
- v = new EnumValue(type.name, v);
-
- // when fq is under control
- if (fq !== undefined) {
- if (fq)
- b = concat([ type.code, b ]);
- assert.deepEqual( enumSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( enumSerializer.serialize(v, true), concat([type.code, value_flag, b]) );
- assert.deepEqual( enumSerializer.serialize(v, false), concat([ b]) );
- }))
- ))
- );
-
- describe('#deserialize', () => {
- types.forEach((type) => describe(`${type.name}`, () =>
- cases.forEach(({ v, fq, b, B, av, err }, i) => it(des_title({i,b}), () => {
- if (B)
- b = B;
- if (Array.isArray(b)) {
- b = from(b);
- if (fq && B === undefined)
- b = concat([ type.code, b ]);
- }
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => enumSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => enumSerializer.deserialize(concat([type.code, value_flag, b]), true), { message: err });
- assert.throws(() => enumSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- if (v !== undefined && v !== null)
- v = new EnumValue(type.name, v);
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- if (v && !fq)
- v.typeName = undefined;
- assert.deepStrictEqual( enumSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( enumSerializer.deserialize(concat([type.code, value_flag, b]), true), {v,len:len+2} );
- v.typeName = undefined;
- assert.deepStrictEqual( enumSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- ));
-
- types.forEach(type =>
- Object.values(type.enum).forEach(e => it(`should return existing t.EnumValue(${e.typeName}, ${e.elementName}) instance`, () => {
- const b = enumSerializer.serialize(e);
- const r = enumSerializer.deserialize(b);
- assert.strictEqual(r.v, e);
- }))
- );
- });
-
- describe('#canBeUsedFor', () => {
- it('should error if type name is not supported', () => assert.throws(
- () => enumSerializer.canBeUsedFor(new EnumValue('UnknownType', 'asc')),
- { message: /typeName=UnknownType is not supported/ }
- ));
-
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new EnumValue('Barrier'), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( enumSerializer.canBeUsedFor(v), e )
- ));
- });
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/FloatSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/FloatSerializer-test.js
deleted file mode 100644
index 8bfd7ee345..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/FloatSerializer-test.js
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { floatSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.FloatSerializer', () => {
-
- const type_code = from([0x08]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x08,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:0 },
- { v:null, fq:1, b:[0x08,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:0 },
-
- { v:1, b:[0x3F,0x80,0x00,0x00] },
- { v:0.375, b:[0x3E,0xC0,0x00,0x00] },
- { v:Infinity, b:[0x7F,0x80,0x00,0x00] },
- { v:-Infinity, b:[0xFF,0x80,0x00,0x00] },
- { v:NaN, b:[0x7F,0xC0,0x00,0x00] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x07] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x09] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x80] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x88] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x08] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x08,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x08,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x08,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x08,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x08,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- { des:1, err:/unexpected {value} length/, b:[0x11,0x22,0x33] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( floatSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( floatSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( floatSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => floatSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => floatSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => floatSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( floatSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( floatSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( floatSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/GraphBinaryReader-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/GraphBinaryReader-test.js
deleted file mode 100644
index 907c271deb..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/GraphBinaryReader-test.js
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import assert from 'assert';
-import { graphBinaryReader } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-import { Traverser } from '../../../lib/process/traversal.js';
-
-import { GraphTraversal } from '../../../lib/process/graph-traversal.js';
-const g = () => new GraphTraversal(undefined, undefined);
-
-const { from } = Buffer;
-
-describe('GraphBinary.Reader', () => {
-
- describe('#readResponse', () => {
-
- [ undefined, null ].forEach(buffer =>
- it(`should error if buffer is '${buffer}'`, () => assert.throws(
- () => graphBinaryReader.readResponse(buffer),
- { message: /Buffer is missing/ },
- ))
- );
-
- [ '', -1, 0, 42, 3.14, NaN, Infinity, -Infinity, Symbol('') ].forEach((buffer, i) =>
- it(`should error if it is not a Buffer, case #${i}`, () => assert.throws(
- () => graphBinaryReader.readResponse(buffer),
- { message: /Not an instance of Buffer/ },
- ))
- );
-
- it('should error if buffer is empty', () => assert.throws(
- () => graphBinaryReader.readResponse(from([])),
- { message: /Buffer is empty/ },
- ));
-
- [
- [ 0x00 ],
- [ 0x00, 0x81 ],
- [ 0x01 ],
- [ 0x80, 0x81 ],
- [ 0x82, 0x81 ],
- [ 0xFF, 0x00, 0x81 ],
- [ 0x00, 0x81 ],
- [ 0x00, 0x00, 0x81 ],
- [ 0x00, 0x00, 0x00, 0x81 ],
- ].forEach((b, i) => it(`should error if version is incorrect, case #${i}`, () => assert.throws(
- () => graphBinaryReader.readResponse(from(b)),
- { message: /Unsupported version/ },
- )));
-
- [
- { b:[
- // {version}
- 0x81,
- // {request_id} nullable UUID
- 0x00, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,
- // {status_code} is an Int
- 0x00,0x00,0x00,0xC8,
- // {status_message} is a nullable String
- 0x00, 0x00,0x00,0x00,0x02, ...from('OK'),
- // {status_attributes} is a Map
- 0x00,0x00,0x00,0x01,
- // key String
- 0x03,0x00, 0x00,0x00,0x00,0x0C, ...from('life-meaning'),
- // value Int
- 0x01,0x00, 0x00,0x00,0x00,0x2A,
- // {result_meta} is a Map
- 0x00,0x00,0x00,0x02,
- // 1 key String
- 0x03,0x00, 0x00,0x00,0x00,0x02, ...from('m1'),
- // 1 value Int
- 0x03,0x00, 0x00,0x00,0x00,0x00,
- // 2 key String
- 0x03,0x00, 0x00,0x00,0x00,0x02, ...from('m2'),
- // 2 value Int
- 0x03,0x00, 0x00,0x00,0x00,0x03, ...from('a_B'),
- // {result_data} is a fully qualified typed value composed of {type_code}{type_info}{value_flag}{value}
- // list
- 0x09,0x00, 0x00,0x00,0x00,0x01,
- // Traverser
- 0x21,0x00,
- // {bulk}
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
- // {value}
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('marko'),
- ],
- v:{
- requestId: '01020304-0506-0708-090a-0b0c0d0e0f10',
- status: {
- code: 200,
- message: 'OK',
- attributes: new Map([ ['life-meaning',42] ]),
- },
- result: {
- meta: new Map([ ['m1',''], ['m2','a_B'] ]),
- data: [ new Traverser('marko', 3n) ],
- }
- }
- },
- ].forEach(({b,v}, i) => it(`should be able to handle case #${i}`, () => assert.deepEqual(
- graphBinaryReader.readResponse( from(b) ),
- v,
- )));
-
- });
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/GraphBinaryWriter-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/GraphBinaryWriter-test.js
deleted file mode 100644
index 6dacf65bf4..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/GraphBinaryWriter-test.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import assert from 'assert';
-import { graphBinaryWriter } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-
-
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.Writer', () => {
-
- describe('#writeRequest', () =>
- [
- ].forEach(({ r, e }, i) => it(`should be able to handle request of case #${i}`, () => assert.deepEqual(
- graphBinaryWriter.writeRequest(r),
- from(e),
- )))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/IntSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/IntSerializer-test.js
deleted file mode 100644
index b7b2895245..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/IntSerializer-test.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { intSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.IntSerializer', () => {
-
- const type_code = from([0x01]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x01,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:0 },
- { v:null, fq:1, b:[0x01,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:0 },
- { v:0, b:[0x00,0x00,0x00,0x00] },
- { v:1, b:[0x00,0x00,0x00,0x01] },
- { v:256, b:[0x00,0x00,0x01,0x00] },
- { v:65536, b:[0x00,0x01,0x00,0x00] },
- { v:16777216, b:[0x01,0x00,0x00,0x00] },
- { v:2147483647, b:[0x7F,0xFF,0xFF,0xFF] },
- { v:-1, b:[0xFF,0xFF,0xFF,0xFF] },
- { v:-2147483648, b:[0x80,0x00,0x00,0x00] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x02] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1D] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x81] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0F] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x01,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x01,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x01,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x01,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x01,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- { des:1, err:/unexpected {value} length/, b:[0x11,0x22,0x33] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( intSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( intSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( intSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => intSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => intSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => intSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( intSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( intSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( intSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [undefined], e: false },
- { v: 0n, e: false },
- { v: BigInt(1), e: false },
- { v: 0, e: true },
- { v: 1, e: true },
- { v: -1, e: true },
- { v: 2147483647, e: true },
- { v: 2147483648, e: false },
- { v: -2147483648, e: true },
- { v: -2147483649, e: false },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( intSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LambdaSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LambdaSerializer-test.js
deleted file mode 100644
index 302ec98f29..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LambdaSerializer-test.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { lambdaSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.LambdaSerializer', () => {
-
- const type_code = from([0x1D]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x1D,0x01], },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00] },
- { v:null, fq:1, b:[0x1D,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00] },
-
- { v:function() { return 'Script_1'; },
- b:[
- 0x00,0x00,0x00,0x0E, ...from('gremlin-groovy'),
- 0x00,0x00,0x00,0x08, ...from('Script_1'),
- 0xFF,0xFF,0xFF,0xFF,
- ]
- },
-
- { v:function() { return [ 'Script_2', 'Scala' ]; },
- b:[
- 0x00,0x00,0x00,0x05, ...from('Scala'),
- 0x00,0x00,0x00,0x08, ...from('Script_2'),
- 0xFF,0xFF,0xFF,0xFF,
- ]
- },
- ];
-
- describe('#serialize', () =>
- cases
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( lambdaSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( lambdaSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( lambdaSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [function(){}], e: false },
- { v: function(){}, e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( lambdaSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ListSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ListSerializer-test.js
deleted file mode 100644
index 1df3559ad9..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ListSerializer-test.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import ArraySerializerTestTemplate from './ArraySerializerTestTemplate.js';
-
-ArraySerializerTestTemplate({ ID: 0x09, name: 'List' });
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LongSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LongSerializer-test.js
deleted file mode 100644
index 159f08d359..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LongSerializer-test.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { longSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.LongSerializer', () => {
-
- const type_code = from([0x02]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x02,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:0 },
- { v:null, fq:1, b:[0x02,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:0 },
- { v:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:1, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01] },
- { v:256, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00] },
- { v:65536, b:[0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00] },
- { v:16777216, b:[0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00] },
- { v:4294967296, b:[0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00] },
- { v:1099511627776, b:[0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00] },
- { v:281474976710656, b:[0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:9007199254740991, b:[0x00,0x1F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-1, b:[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-9007199254740991, b:[0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x01] },
-
- // Cases for 64bit integer vs. JavaScript Number.MIN/MAX_SAFE_INTEGER
- // 'e' stands for what actually we would expect if we had enough presicion
- { des:1, e:'9007199254740992', // MAX_SAFE_INTEGER + 1
- v: 9007199254740992, b:[0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00] },
- { des:1, e:'9007199254741001', // MAX_SAFE_INTEGER + 10
- v: 9007199254741000, b:[0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x09] },
- { des:1, e:'9007199254741091', // MAX_SAFE_INTEGER + 100
- v: 9007199254741092, b:[0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x63] },
- { des:1, e:'9007199254741991', // MAX_SAFE_INTEGER + 1000
- v: 9007199254741992, b:[0x00,0x20,0x00,0x00,0x00,0x00,0x03,0xE7] },
- { des:1, e:'-9007199254741991',// MIN_SAFE_INTEGER - 1000
- v: -9007199254741992, b:[0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFC,0x19] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x03] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x20] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x82] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x02,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- { des:1, err:/unexpected {value} length/, b:[0x11,0x22,0x33,0x44,0x55,0x66,0x77] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( longSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( longSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( longSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => longSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => longSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => longSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( longSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( longSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( longSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- it.skip('')
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LongSerializerNg-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LongSerializerNg-test.js
deleted file mode 100644
index 1249c3d173..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/LongSerializerNg-test.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { longSerializerNg as longSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.LongSerializerNg', () => {
-
- const type_code = from([0x02]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x02,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:0n },
- { v:null, fq:1, b:[0x02,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], av:0n },
- { v:0n, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:1n, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01] },
- { v:256n, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00] },
- { v:65536n, b:[0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00] },
- { v:16777216n, b:[0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00] },
- { v:4294967296n, b:[0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00] },
- { v:1099511627776n, b:[0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00] },
- { v:281474976710656n, b:[0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:72057594037927936n, b:[0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- { v:9223372036854775807n, b:[0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-1n, b:[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] },
- { v:-9223372036854775808n, b:[0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x03] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x20] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x82] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x02,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x02,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- { des:1, err:/unexpected {value} length/, b:[0x11,0x22,0x33,0x44,0x55,0x66,0x77] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( longSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( longSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( longSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => longSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => longSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => longSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( longSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( longSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( longSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- it.skip('')
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/MapSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/MapSerializer-test.js
deleted file mode 100644
index d123f42d66..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/MapSerializer-test.js
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { mapSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser } from '../../../lib/process/traversal.js';
-
-
-
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.MapSerializer', () => {
-
- const type_code = from([0x0A]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x0A, 0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:{} },
- { v:null, fq:1, b:[0x0A, 0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:{} },
-
- { v:{},
- b:[0x00,0x00,0x00,0x00] },
-
- { v:{ 'a': 'a' },
- b:[0x00,0x00,0x00,0x01, /*'a'*/0x03,0x00,0x00,0x00,0x00,0x01,0x61, /*'a'*/0x03,0x00,0x00,0x00,0x00,0x01,0x61] },
-
- { v:{ 'a': 'A' },
- b:[0x00,0x00,0x00,0x01, /*'a'*/0x03,0x00,0x00,0x00,0x00,0x01,0x61, /*'A'*/0x03,0x00,0x00,0x00,0x00,0x01,0x41] },
-
- { v:{ 'a': 1 },
- b:[0x00,0x00,0x00,0x01, /*'a'*/0x03,0x00,0x00,0x00,0x00,0x01,0x61, /*1*/0x01,0x00,0x00,0x00,0x00,0x01] },
-
- { v:{ 'yz': 'A1' },
- b:[0x00,0x00,0x00,0x01, /*'yz'*/0x03,0x00,0x00,0x00,0x00,0x02,0x79,0x7A, /*'A1'*/0x03,0x00,0x00,0x00,0x00,0x02,0x41,0x31] },
-
- { v:{ 'one': 1, 'two': 2 },
- b:[0x00,0x00,0x00,0x02,
- /*'one'*/0x03,0x00,0x00,0x00,0x00,0x03,0x6F,0x6E,0x65, /*1*/0x01,0x00,0x00,0x00,0x00,0x01,
- /*'two'*/0x03,0x00,0x00,0x00,0x00,0x03,0x74,0x77,0x6F, /*2*/0x01,0x00,0x00,0x00,0x00,0x02,
- ]
- },
-
- { v:{ 'one': 1, 'two': 2, 'int32': new Map([ ['min',-2147483648], ['max',2147483647] ]) },
- b:[0x00,0x00,0x00,0x03,
- /*'one'*/0x03,0x00,0x00,0x00,0x00,0x03,0x6F,0x6E,0x65, /*1*/0x01,0x00,0x00,0x00,0x00,0x01,
- /*'two'*/0x03,0x00,0x00,0x00,0x00,0x03,0x74,0x77,0x6F, /*2*/0x01,0x00,0x00,0x00,0x00,0x02,
- /*'int32'*/ 0x03,0x00, 0x00,0x00,0x00,0x05, 0x69,0x6E,0x74,0x33,0x32,
- /*int32 map*/
- 0x0A,0x00, 0x00,0x00,0x00,0x02,
- /*'min'*/0x03,0x00,0x00,0x00,0x00,0x03,0x6D,0x69,0x6E, /*-2147483648*/0x01,0x00,0x80,0x00,0x00,0x00,
- /*'max'*/0x03,0x00,0x00,0x00,0x00,0x03,0x6D,0x61,0x78, /* 2147483647*/0x01,0x00,0x7F,0xFF,0xFF,0xFF,
- ]
- },
-
-
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x09] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0B] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x8A] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1A] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xA0] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x0A] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0A,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0A,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0A,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0A,0xFF] },
-
- { des:1, err:/{length} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length} is less than zero/, b:[0x80,0x00,0x00,0x00] },
-
- { des:1, err:/{item_0} key:.*buffer is empty/, b:[0x00,0x00,0x00,0x01] },
- { des:1, err:/{item_0} key:.*{value_flag} is missing/, b:[0x00,0x00,0x00,0x01, 0x01] },
- { des:1, err:/{item_0} value:.*buffer is empty/, b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x00,0x00,0x00,0x0F] },
- { des:1, err:/{item_0} value:.*{value_flag} is missing/, b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x00,0x00,0x00,0x0F, 0x01] },
- { des:1, err:/{item_1} key:.*buffer is empty/, b:[0x00,0x00,0x00,0x02, 0x01,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00 ] },
- { des:1, err:/{item_1} key:.*{value_flag} is missing/, b:[0x00,0x00,0x00,0x02, 0x01,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00, 0x0A ] },
- { des:1, err:/{item_1} value:.*buffer is empty/, b:[0x00,0x00,0x00,0x02, 0x01,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0xFF ] },
- { des:1, err:/{item_1} value:.*{value_flag} is missing/, b:[0x00,0x00,0x00,0x02, 0x01,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0xFF, 0x01 ] },
- ];
-
- describe('#serialize', () => {
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- let map;
- if (v)
- map = new Map( Object.entries(v) );
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( mapSerializer.serialize(v, fq), b );
- if (map)
- assert.deepEqual( mapSerializer.serialize(map, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( mapSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( mapSerializer.serialize(v, false), concat([ b]) );
- if (map) {
- assert.deepEqual( mapSerializer.serialize(map, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( mapSerializer.serialize(map, false), concat([ b]) );
- }
- }));
- });
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => mapSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => mapSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => mapSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- if (v)
- v = new Map( Object.entries(v) );
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( mapSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( mapSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( mapSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: true },
- { v: new Traverser(), e: true },
- { v: [], e: false },
- { v: [{}], e: false },
- { v: [new Map()], e: false },
- { v: new Map(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( mapSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PSerializer-test.js
deleted file mode 100644
index 5868e9de36..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PSerializer-test.js
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { pSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { P, Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.PSerializer', () => {
-
- const type_code = from([0x1E]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x1E, 0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:new P('') },
- { v:null, fq:1, b:[0x1E, 0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:new P('') },
-
- // TODO: and
-
- // TODO: or
-
- // within(...[])
- { v: P.within('A', 'b', '3'),
- b: [
- 0x00,0x00,0x00,0x06, ...from('within'),
- 0x00,0x00,0x00,0x03, // {values_length}
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x62, // 'b'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x33, // '3'
- ]
- },
- // within([...])
- { v: P.within([ 'B', 'a', '0' ]),
- b: [
- 0x00,0x00,0x00,0x06, ...from('within'),
- 0x00,0x00,0x00,0x03, // {values_length}
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42, // 'B'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x61, // 'a'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x30, // '0'
- ]
- },
-
- // without(...[])
- { v: P.without('A', 'b', '3'),
- b: [
- 0x00,0x00,0x00,0x07, ...from('without'),
- 0x00,0x00,0x00,0x03, // {values_length}
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41, // 'A'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x62, // 'b'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x33, // '3'
- ]
- },
- // without([...])
- { v: P.without([ 'B', 'a', '0' ]),
- b: [
- 0x00,0x00,0x00,0x07, ...from('without'),
- 0x00,0x00,0x00,0x03, // {values_length}
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42, // 'B'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x61, // 'a'
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x30, // '0'
- ]
- },
-
- ...(['between','eq','gt','gte','inside','lt','lte','neq','not','outside'].map(operator => ({
- v: P[operator]('ValuE', 'OtheR'),
- b: [
- 0x00,0x00,0x00,operator.length, ...from(operator),
- 0x00,0x00,0x00,0x02, // {values_length}
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('ValuE'),
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('OtheR'),
- ]
- }))),
-
- // test
- { v: P.test(1, 2, 3),
- b: [
- 0x00,0x00,0x00,0x04, ...from('test'),
- 0x00,0x00,0x00,0x02, // {values_length}
- 0x01,0x00, 0x00,0x00,0x00,0x01, // 1
- 0x01,0x00, 0x00,0x00,0x00,0x02, // 2
- ],
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1D] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1F] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xE1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0E] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x1E] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x1E,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x1E,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x1E,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x1E,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( pSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( pSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( pSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => pSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => pSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => pSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( pSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( pSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( pSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: true },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new P()], e: false },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( pSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PathSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PathSerializer-test.js
deleted file mode 100644
index ab668dee2a..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PathSerializer-test.js
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { pathSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-import { Path } from '../../../lib/structure/graph.js';
-import * as g from "../../../lib/structure/graph.js";
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.PathSerializer', () => {
-
- const type_code = from([0x0E]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x0E,0x01], av:null },
- { v:undefined, fq:0, b:[0x09,0x00,0x00,0x00,0x00,0x00, 0x09,0x00,0x00,0x00,0x00,0x00], av:new Path([],[]) },
- { v:null, fq:1, b:[0x0E,0x01] },
- { v:null, fq:0, b:[0x09,0x00,0x00,0x00,0x00,0x00, 0x09,0x00,0x00,0x00,0x00,0x00], av:new Path([],[]) },
-
- { v:new Path([ ['A','B'], ['C','D'] ], [ 1,-1 ]),
- b:[
- // {labels}
- 0x09,0x00,0x00,0x00,0x00,0x02, // List.{length}
- // ['A','B']
- 0x09,0x00, 0x00,0x00,0x00,0x02,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42,
- // ['C','D']
- 0x09,0x00, 0x00,0x00,0x00,0x02,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x43,
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x44,
- // {objects}
- 0x09,0x00,0x00,0x00,0x00,0x02, // List.{length}
- 0x01,0x00, 0x00,0x00,0x00,0x01,
- 0x01,0x00, 0xFF,0xFF,0xFF,0xFF,
- ]
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0D] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0F] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xE0] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1E] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x0E] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0E,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0E,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0E,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0E,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( pathSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( pathSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( pathSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => pathSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => pathSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => pathSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( pathSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( pathSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( pathSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new Path()], e: false },
- { v: new Path(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( pathSerializer.canBeUsedFor(v), e )
- ))
- );
-
- // Additional complex path tests with Vertex and Edge objects
- describe('complex V-E-V path round-trip', () => {
- function buildVertex(id, label, propsObj) {
- if (!propsObj) return new g.Vertex(id, label, undefined);
- // build array of VertexProperty entries as expected by Vertex
- const vps = Object.keys(propsObj).map((k, idx) => new g.VertexProperty(idx + 1, k, propsObj[k], undefined));
- return new g.Vertex(id, label, vps);
- }
-
- function buildEdge(id, outV, label, inV, propsObj) {
- // Edge expects properties as a map of key -> g.Property (the constructor extracts .value)
- let props = undefined;
- if (propsObj) {
- props = {};
- for (const k of Object.keys(propsObj)) props[k] = new g.Property(k, propsObj[k]);
- }
- return new g.Edge(id, outV, label, inV, props);
- }
-
- it('should serialize/deserialize Path with V-E-V that includes properties', () => {
- const vOut = buildVertex(1, 'person', { name: 'marko', age: 29 });
- const vIn = buildVertex(3, 'software', { name: 'lop', lang: 'java' });
- const e = buildEdge(9, vOut, 'created', vIn, { weight: 0.4 });
-
- const p = new g.Path([[ 'a' ], [ 'b' ], [ 'c' ]], [ vOut, e, vIn ]);
-
- // round-trip with non-fully-qualified format
- const buf = pathSerializer.serialize(p, false);
- const { v: deser, len } = pathSerializer.deserialize(buf, false);
-
- // sanity on buffer consumed
- assert.strictEqual(len, buf.length);
-
- // assert labels
- assert.strictEqual(deser.labels.length, 3);
- assert.strictEqual(deser.labels[0].length, 1);
- assert.strictEqual(deser.labels[1].length, 1);
- assert.strictEqual(deser.labels[2].length, 1);
-
- // assert objects and their types
- assert.strictEqual(deser.objects.length, 3);
- const a = deser.objects[0];
- const b = deser.objects[1];
- const c = deser.objects[2];
- assert.ok(a instanceof g.Vertex);
- assert.ok(b instanceof g.Edge);
- assert.ok(c instanceof g.Vertex);
-
- // Vertex properties should be present (VertexSerializer preserves them)
- assert.ok(Array.isArray(a.properties));
- assert.ok(a.properties.length > 0);
- assert.ok(Array.isArray(c.properties));
- assert.ok(c.properties.length > 0);
-
- // Edge properties are not serialized in GraphBinary (EdgeSerializer writes null), expect empty object
- assert.ok(b.properties);
- assert.strictEqual(Object.keys(b.properties).length, 0);
- });
-
- it('should serialize/deserialize Path with V-E-V without properties', () => {
- const vOut = buildVertex(1, 'person', undefined);
- const vIn = buildVertex(3, 'software', undefined);
- const e = buildEdge(9, vOut, 'created', vIn, undefined);
-
- const p = new g.Path([[ 'a' ], [ 'b' ], [ 'c' ]], [ vOut, e, vIn ]);
-
- // round-trip with fully-qualified format
- const fqBuf = pathSerializer.serialize(p, true);
- const { v: deser, len } = pathSerializer.deserialize(fqBuf, true);
-
- assert.strictEqual(len, fqBuf.length);
-
- // types
- const a = deser.objects[0];
- const b = deser.objects[1];
- const c = deser.objects[2];
- assert.ok(a instanceof g.Vertex);
- assert.ok(b instanceof g.Edge);
- assert.ok(c instanceof g.Vertex);
-
- // Vertex properties default to [] when null/undefined
- assert.ok(Array.isArray(a.properties));
- assert.strictEqual(a.properties.length, 0);
- assert.ok(Array.isArray(c.properties));
- assert.strictEqual(c.properties.length, 0);
-
- // Edge properties default to {} when null/undefined
- assert.ok(b.properties);
- assert.strictEqual(Object.keys(b.properties).length, 0);
- });
- });
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PropertySerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PropertySerializer-test.js
deleted file mode 100644
index 689da6462d..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/PropertySerializer-test.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { propertySerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-import { Property } from '../../../lib/structure/graph.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.PropertySerializer', () => {
-
- const type_code = from([0x0F]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x0F,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00, 0xFE,0x01, 0xFE,0x01], av:new Property('',null) },
- { v:null, fq:1, b:[0x0F,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00, 0xFE,0x01, 0xFE,0x01], av:new Property('',null) },
-
- { v:new Property('key', 42),
- b:[
- 0x00,0x00,0x00,0x03, ...from('key'),
- 0x01,0x00, 0x00,0x00,0x00,0x2A,
- 0xFE,0x01,
- ]
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0E] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x10] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xF0] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1F] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0F,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0F,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0F,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0F,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( propertySerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( propertySerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( propertySerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => propertySerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => propertySerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => propertySerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( propertySerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( propertySerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( propertySerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new Property()], e: false },
- { v: new Property(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( propertySerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/SetSerializerTestTemplate.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/SetSerializerTestTemplate.js
deleted file mode 100644
index f151ae952d..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/SetSerializerTestTemplate.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import {des_title, cbuf_title, ser_title} from './utils.js';
-import assert from 'assert';
-import {intSerializer, serializers} from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-export default ({ ID, name }) => {
-
-describe(`GraphBinary.${name}Serializer`, () => {
-
- const type_code = from([ID]);
- const value_flag = from([0x00]);
-
- const serializer = serializers[ID];
-
- const cases = [
- { v:undefined, fq:1, b:[ID,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:new Set() },
- { v:null, fq:1, b:[ID,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:new Set() },
-
- { v:new Set(), b:[0x00,0x00,0x00,0x00] },
- { v:new Set([2147483647]), b:[0x00,0x00,0x00,0x01, 0x01,0x00,0x7F,0xFF,0xFF,0xFF] },
- { v:new Set([-1,'A']), b:[0x00,0x00,0x00,0x02, 0x01,0x00,0xFF,0xFF,0xFF,0xFF, 0x03,0x00,0x00,0x00,0x00,0x01,0x41] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID-1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID+1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x89] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x19] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x90] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[ID] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0xFF] },
-
- { des:1, err:/{length} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length} is less than zero/, b:[0x80,0x00,0x00,0x00] },
- ];
-
- describe('#serialize', () => {
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( serializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( serializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( serializer.serialize(v, false), concat([ b]) );
- }));
-
- it.skip('should not error if set length is INT32_MAX');
-
- });
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => serializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => serializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => serializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( serializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( serializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( serializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [undefined], e: false },
- { v: new Set(), e: true },
- { v: new Set([0]), e: true },
- { v: new Set([undefined]), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( serializer.canBeUsedFor(v), e )
- ))
- );
-
-});
-
-};
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ShortSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ShortSerializer-test.js
deleted file mode 100644
index 52b2f3e712..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/ShortSerializer-test.js
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { shortSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.ShortSerializer', () => {
-
- const type_code = from([0x26]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x26,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00], av:0 },
- { v:null, fq:1, b:[0x26,0x01] },
- { v:null, fq:0, b:[0x00,0x00], av:0 },
- { v:0, b:[0x00,0x00] },
- { v:1, b:[0x00,0x01] },
- { v:256, b:[0x01,0x00] },
- { v:32767, b:[0x7F,0xFF] },
- { v:-1, b:[0xFF,0xFF] },
- { v:-32768, b:[0x80,0x00] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x02] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x62] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x25] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x27] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x26] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x26,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x26,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x26,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x26,0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x26,0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x11] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( shortSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( shortSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( shortSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => shortSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => shortSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => shortSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( shortSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( shortSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( shortSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/StringSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/StringSerializer-test.js
deleted file mode 100644
index e46c6aeee0..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/StringSerializer-test.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import StringSerializerTestTemplate from './StringSerializerTestTemplate.js';
-
-StringSerializerTestTemplate({ ID: 0x03, name: 'String' });
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/StringSerializerTestTemplate.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/StringSerializerTestTemplate.js
deleted file mode 100644
index 48a3c39387..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/StringSerializerTestTemplate.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { serializers } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-export default ({ ID, name }) => {
-
-describe(`GraphBinary.${name}Serializer`, () => {
-
- const type_code = from([ID]);
- const value_flag = from([0x00]);
-
- const serializer = serializers[ID];
-
- const cases = [
- { v:undefined, fq:1, b:[ID,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00], av:'' },
- { v:null, fq:1, b:[ID,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00], av:'' },
-
- { v:'', b:[0x00,0x00,0x00,0x00] },
- { v:'Sun', b:[0x00,0x00,0x00,0x03, 0x53,0x75,0x6E] },
- { v:'ήλιος', b:[0x00,0x00,0x00,0x0A, 0xCE,0xAE, 0xCE,0xBB, 0xCE,0xB9, 0xCE,0xBF, 0xCF,0x82] },
-
- // TODO: Should we complain on wrong UTF-8 deserialization?
- // It could be additional latency if we explicitly check entire string for correct encoding (if we avoid custom parser impl).
- // And, probably, it's better to provide something instead of throwing an error and failing entire response.
- // For now invalid byte sequences are stubbed with 0xFFFD according to https://nodejs.org/dist/latest/docs/api/buffer.html#buftostringencoding-start-end
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
- { des:1, err:/buffer is empty/, fq:0, na:1, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID-1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[ID+1] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x10] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x11] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[ID] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0x80] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0x80] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[ID,0xFF] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0xFF] },
-
- { des:1, err:/{length} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF] },
- { des:1, err:/{length} is less than zero/, b:[0x80,0x00,0x00,0x00] },
-
- { des:1, err:/unexpected {text_value} length/, b:[0x00,0x00,0x00,0x01] },
- { des:1, err:/unexpected {text_value} length/, b:[0x00,0x00,0x00,0x02, 0x41] },
- { des:1, err:/unexpected {text_value} length/, b:[0x00,0x00,0x00,0x03, 0x41,0x42] },
-
- { des:1, v:null, fq:0, na:1, b:[0x01] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( serializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( serializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( serializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, na, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => serializer.deserialize(b, fq, na), { message: err });
- else {
- assert.throws(() => serializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => serializer.deserialize(concat([ value_flag, b]), false, true), { message: err });
- assert.throws(() => serializer.deserialize(concat([ b]), false, false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( serializer.deserialize(b, fq, na), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( serializer.deserialize(concat([type_code, value_flag, b]), true, false), {v,len:len+2} );
- assert.deepStrictEqual( serializer.deserialize(concat([type_code, value_flag, b]), true, true), {v,len:len+2} );
- assert.deepStrictEqual( serializer.deserialize(concat([ value_flag, b]), false, true), {v,len:len+1} );
- assert.deepStrictEqual( serializer.deserialize(concat([ b]), false, false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- [
- { v: 'some string', e: true },
- { v: '', e: true },
- { v: 'Z', e: true },
- { v: 'Україна', e: true },
- { v: true, e: false },
- { v: false, e: false },
- { v: null, e: false },
- { v: undefined, e: false },
- { v: Number.MAX_VALUE, e: false },
- { v: 42, e: false },
- { v: 0, e: false },
- { v: Number.MIN_VALUE, e: false },
- { v: NaN, e: false },
- { v: +Infinity, e: false },
- { v: -Infinity, e: false },
- //{ v: Symbol(''), e: false },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () => assert.strictEqual(
- serializer.canBeUsedFor(v),
- e,
- )))
- );
-
-});
-
-};
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TextPSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TextPSerializer-test.js
deleted file mode 100644
index 64b26b36c6..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TextPSerializer-test.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { textPSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { TextP, Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.TextPSerializer', () => {
-
- const type_code = from([0x28]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x28,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:new TextP('') },
- { v:null, fq:1, b:[0x28,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:new TextP('') },
-
- // TODO: and
- // TODO: or
-
- ...(['containing','endingWith','notContaining','notEndingWith','notStartingWith','startingWith'].map(operator => ({
- v: TextP[operator]('ValuE', 'OtheR'),
- b: [
- 0x00,0x00,0x00,operator.length, ...from(operator),
- 0x00,0x00,0x00,0x02, // {values_length}
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('ValuE'),
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('OtheR'),
- ]
- }))),
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x27] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x29] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x82] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x28] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x28,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x28,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x28,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x28,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( textPSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( textPSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( textPSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => textPSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => textPSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => textPSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( textPSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( textPSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( textPSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new TextP()], e: false },
- { v: new TextP(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( textPSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TimestampSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TimestampSerializer-test.js
deleted file mode 100644
index 2502745035..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TimestampSerializer-test.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import DateSerializerTestTemplate from './DateSerializerTestTemplate.js';
-
-DateSerializerTestTemplate({ ID: 0x05, name: 'Timestamp' });
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TraversalStrategySerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TraversalStrategySerializer-test.js
deleted file mode 100644
index 5f28eff0a8..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TraversalStrategySerializer-test.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { traversalStrategySerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-import { ElementIdStrategy, OptionsStrategy, TraversalStrategy } from '../../../lib/process/traversal-strategy.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.TraversalStrategySerializer', () => {
-
- const type_code = from([0x29]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x29,0x01], },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00] },
- { v:null, fq:1, b:[0x29,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00] },
-
- { v:new ElementIdStrategy(),
- b:[
- 0x00,0x00,0x00,0x54, ...from('org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy'),
- 0x00,0x00,0x00,0x00,
- ]
- },
-
- { v:new OptionsStrategy({ 'A': 1, 'B': 2 }),
- b:[
- 0x00,0x00,0x00,0x52, ...from('org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy'),
- 0x00,0x00,0x00,0x02,
- // 'A':1
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x41,
- 0x01,0x00, 0x00,0x00,0x00,0x01,
- // 'B':2
- 0x03,0x00, 0x00,0x00,0x00,0x01, 0x42,
- 0x01,0x00, 0x00,0x00,0x00,0x02,
- ]
- },
- ];
-
- describe('#serialize', () =>
- cases
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( traversalStrategySerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( traversalStrategySerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( traversalStrategySerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [function(){}], e: false },
- { v: function(){}, e: false },
- { v: new TraversalStrategy(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( traversalStrategySerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TraverserSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TraverserSerializer-test.js
deleted file mode 100644
index b3599acdaa..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/TraverserSerializer-test.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { traverserSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.TraverserSerializer', () => {
-
- const type_code = from([0x21]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x21, 0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0xFE,0x01], av:new Traverser(null, 1) },
- { v:null, fq:1, b:[0x21, 0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0xFE,0x01], av:new Traverser(null, 1) },
-
- { v:new Traverser(-1, 0), b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x01,0x00,0xFF,0xFF,0xFF,0xFF], av:new Traverser(-1, 1) }, // check Traverser.constructor() when bulk=0 becomes bulk=1
- { v:new Traverser('abC', 2), b:[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, 0x03,0x00, 0x00,0x00,0x00,0x03, 0x61,0x62,0x43] },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x20] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x22] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x12] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x21] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x21,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x21,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x21,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x21,0xFF] },
-
- { des:1, err:/{bulk} is less than zero/, b:[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] }, // TODO: is it correct expectation that bulk must be >= 0?
- { des:1, err:/{bulk} is less than zero/, b:[0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( traverserSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( traverserSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( traverserSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => traverserSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => traverserSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => traverserSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( traverserSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( traverserSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( traverserSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( traverserSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/UnspecifiedNullSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/UnspecifiedNullSerializer-test.js
deleted file mode 100644
index 6a4ae5bbb5..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/UnspecifiedNullSerializer-test.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { unspecifiedNullSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser } from '../../../lib/process/traversal.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.UnspecifiedNullSerializer', () => {
-
- const cases = [
- { v:undefined, b:[0xFE,0x01], av:null },
- { v:null, b:[0xFE,0x01] },
-
- { des:1, err:/buffer is missing/, b:undefined },
- { des:1, err:/buffer is missing/, b:null },
- { des:1, err:/buffer is empty/, b:[] },
-
- { des:1, err:/unexpected {type_code}/, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, b:[0xEF] },
- { des:1, err:/unexpected {type_code}/, b:[0x0E] },
- { des:1, err:/unexpected {type_code}/, b:[0x81] },
- { des:1, err:/unexpected {type_code}/, b:[0xFD] },
- { des:1, err:/unexpected {type_code}/, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, b:[0xFE] },
- { des:1, err:/unexpected {value_flag}/, b:[0xFE,0x10] },
- { des:1, err:/unexpected {value_flag}/, b:[0xFE,0x00] },
- { des:1, err:/unexpected {value_flag}/, b:[0xFE,0x02] },
- { des:1, err:/unexpected {value_flag}/, b:[0xFE,0x0F] },
- { des:1, err:/unexpected {value_flag}/, b:[0xFE,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
- assert.deepEqual( unspecifiedNullSerializer.serialize(v), b );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- assert.throws(() => unspecifiedNullSerializer.deserialize(b), { message: err });
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // generic case
- assert.deepStrictEqual( unspecifiedNullSerializer.deserialize(b), {v,len} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: true },
- { v: undefined, e: true },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: [], e: false },
- { v: [{}], e: false },
- { v: [new Map()], e: false },
- { v: new Map(), e: false },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( unspecifiedNullSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/UuidSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/UuidSerializer-test.js
deleted file mode 100644
index e3883bc4fe..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/UuidSerializer-test.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title } from './utils.js';
-import assert from 'assert';
-import { uuidSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.UuidSerializer', () => {
-
- const type_code = from([0x0C]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x0C,0x01], av:null },
- { v:undefined, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:'00000000-0000-0000-0000-000000000000' },
- { v:null, fq:1, b:[0x0C,0x01] },
- { v:null, fq:0, b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:'00000000-0000-0000-0000-000000000000' },
-
- { v:'00000000-0000-0000-0000-000000000000', b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00] },
- { v:'00010203-0405-0607-0809-0A0B0C0D0E0F', b:[0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F] },
- { v:'AaBbCcDd-EeFf-1122-3344-556677889900', b:[0xAA,0xBB,0xCC,0xDD, 0xEE,0xFF,0x11,0x22, 0x33,0x44,0x55,0x66, 0x77,0x88,0x99,0x00] },
-
- // string presentation formats
- { v:'000102030405060708090A0B0C0D0E0F', b:[0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F], av:'00010203-0405-0607-0809-0A0B0C0D0E0F' },
- { v:'00010203-0405-0607-0809-0A0B0C0D0E0F', b:[0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F] },
- { v:'{00010203-0405-0607-0809-0A0B0C0D0E0F}', b:[0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F], av:'00010203-0405-0607-0809-0A0B0C0D0E0F' },
- { v:'urn:uuid:00010203-0405-0607-0809-0A0B0C0D0E0F', b:[0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B, 0x0C,0x0D,0x0E,0x0F], av:'00010203-0405-0607-0809-0A0B0C0D0E0F' },
-
- // wrong string presentation
- { v:'AaBbCcDd-EeFf-1122-3344-556677889900FFFF', b:[0xAA,0xBB,0xCC,0xDD, 0xEE,0xFF,0x11,0x22, 0x33,0x44,0x55,0x66, 0x77,0x88,0x99,0x00], av:'AaBbCcDd-EeFf-1122-3344-556677889900' },
- { v:'GHIJKLMN-OPQR-STUV-WXYZ-!@#$%^&*()_+', b:[0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00], av:'00000000-0000-0000-0000-000000000000' },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
- { des:1, err:/buffer is empty/, fq:0, na:1, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0D] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x0B] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x8C] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFC] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x0C] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0C,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0C,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0C,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x0C,0xFF] },
- { des:1, err:/unexpected {value_flag}/, fq:0, na:1, b:[0xFF] },
-
- { des:1, err:/unexpected {value} length/, fq:1, b:[0x0C,0x00] },
- { des:1, err:/unexpected {value} length/, fq:0, na:1, b:[0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x00] },
- { des:1, err:/unexpected {value} length/, b:[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E] },
-
- { des:1, v:null, fq:0, na:1, b:[0x01] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( uuidSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( uuidSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( uuidSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, na, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => uuidSerializer.deserialize(b, fq, na), { message: err });
- else {
- assert.throws(() => uuidSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => uuidSerializer.deserialize(concat([ value_flag, b]), false, true), { message: err });
- assert.throws(() => uuidSerializer.deserialize(concat([ b]), false, false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- if (typeof v === 'string')
- v = v.toLowerCase();
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( uuidSerializer.deserialize(b, fq, na), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( uuidSerializer.deserialize(concat([type_code, value_flag, b]), true, false), {v,len:len+2} );
- assert.deepStrictEqual( uuidSerializer.deserialize(concat([type_code, value_flag, b]), true, true), {v,len:len+2} );
- assert.deepStrictEqual( uuidSerializer.deserialize(concat([ value_flag, b]), false, true), {v,len:len+1} );
- assert.deepStrictEqual( uuidSerializer.deserialize(concat([ b]), false, false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- it.skip('')
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/VertexPropertySerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/VertexPropertySerializer-test.js
deleted file mode 100644
index 41da527c27..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/VertexPropertySerializer-test.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { vertexPropertySerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-import { VertexProperty } from '../../../lib/structure/graph.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.VertexPropertySerializer', () => {
-
- const type_code = from([0x12]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x12,0x01], av:null },
- { v:undefined, fq:0, b:[0xFE,0x01, 0x00,0x00,0x00,0x00, 0xFE,0x01, 0xFE,0x01, 0xFE,0x01], av:new VertexProperty(null,'',null,[]) },
- { v:null, fq:1, b:[0x12,0x01] },
- { v:null, fq:0, b:[0xFE,0x01, 0x00,0x00,0x00,0x00, 0xFE,0x01, 0xFE,0x01, 0xFE,0x01], av:new VertexProperty(null,'',null,[]) },
-
- { v:new VertexProperty('Id', 'Label', 'Value', []),
- b:[
- 0x03,0x00, 0x00,0x00,0x00,0x02, ...from('Id'),
- 0x00,0x00,0x00,0x05, ...from('Label'),
- 0x03,0x00, 0x00,0x00,0x00,0x05, ...from('Value'),
- 0xFE,0x01,
- 0x09,0x00,0x00,0x00,0x00,0x00,
- ]
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x11] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x13] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x21] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x1F] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x12] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x12,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x12,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x12,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x12,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( vertexPropertySerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( vertexPropertySerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( vertexPropertySerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => vertexPropertySerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => vertexPropertySerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => vertexPropertySerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( vertexPropertySerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( vertexPropertySerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( vertexPropertySerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new VertexProperty()], e: false },
- { v: new VertexProperty(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( vertexPropertySerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/VertexSerializer-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/VertexSerializer-test.js
deleted file mode 100644
index 624056b179..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/VertexSerializer-test.js
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { ser_title, des_title, cbuf_title } from './utils.js';
-import assert from 'assert';
-import { vertexSerializer } from '../../../lib/structure/io/binary/GraphBinary.js';
-import { Traverser, P } from '../../../lib/process/traversal.js';
-import { Vertex } from '../../../lib/structure/graph.js';
-
-const { from, concat } = Buffer;
-
-describe('GraphBinary.VertexSerializer', () => {
-
- const type_code = from([0x11]);
- const value_flag = from([0x00]);
-
- const cases = [
- { v:undefined, fq:1, b:[0x11,0x01], av:null },
- { v:undefined, fq:0, b:[0x03,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0xFE,0x01], av:new Vertex('','',[]) },
- { v:null, fq:1, b:[0x11,0x01] },
- { v:null, fq:0, b:[0x03,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0xFE,0x01], av:new Vertex('','',[]) },
-
- { v:new Vertex(42, 'A', -1),
- b:[
- 0x01,0x00, 0x00,0x00,0x00,0x2A, // id
- 0x00,0x00,0x00,0x01, 0x41, // label
- 0x01,0x00, 0xFF,0xFF,0xFF,0xFF // properties
- ]
- },
-
- // real case with id of UUID type, but JS does not have UUID type, it's presented as a string instead
- { des:1,
- v:new Vertex('28f38e3d-7739-4c99-8284-eb43db2a80f1', 'Person', []),
- b:[
- 0x0C,0x00, 0x28,0xF3,0x8E,0x3D, 0x77,0x39, 0x4C,0x99, 0x82,0x84, 0xEB,0x43,0xDB,0x2A,0x80,0xF1, // id
- 0x00,0x00,0x00,0x06, ...from('Person'), // label
- 0xFE,0x01, // properties
- ]
- },
-
- { des:1, err:/buffer is missing/, fq:1, b:undefined },
- { des:1, err:/buffer is missing/, fq:0, b:undefined },
- { des:1, err:/buffer is missing/, fq:1, b:null },
- { des:1, err:/buffer is missing/, fq:0, b:null },
- { des:1, err:/buffer is empty/, fq:1, b:[] },
- { des:1, err:/buffer is empty/, fq:0, b:[] },
-
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x00] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x01] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x10] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0x12] },
- { des:1, err:/unexpected {type_code}/, fq:1, b:[0xFF] },
-
- { des:1, err:/{value_flag} is missing/, fq:1, b:[0x11] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x11,0x10] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x11,0x02] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x11,0x0F] },
- { des:1, err:/unexpected {value_flag}/, fq:1, b:[0x11,0xFF] },
- ];
-
- describe('#serialize', () =>
- cases
- .filter(({des}) => !des)
- .forEach(({ v, fq, b }, i) => it(ser_title({i,v}), () => {
- b = from(b);
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepEqual( vertexSerializer.serialize(v, fq), b );
- return;
- }
-
- // generic case
- assert.deepEqual( vertexSerializer.serialize(v, true), concat([type_code, value_flag, b]) );
- assert.deepEqual( vertexSerializer.serialize(v, false), concat([ b]) );
- }))
- );
-
- describe('#deserialize', () =>
- cases.forEach(({ v, fq, b, av, err }, i) => it(des_title({i,b}), () => {
- if (Array.isArray(b))
- b = from(b);
-
- // wrong binary
- if (err !== undefined) {
- if (fq !== undefined)
- assert.throws(() => vertexSerializer.deserialize(b, fq), { message: err });
- else {
- assert.throws(() => vertexSerializer.deserialize(concat([type_code, value_flag, b]), true), { message: err });
- assert.throws(() => vertexSerializer.deserialize(concat([ b]), false), { message: err });
- }
- return;
- }
-
- if (av !== undefined)
- v = av;
- const len = b.length;
-
- // when fq is under control
- if (fq !== undefined) {
- assert.deepStrictEqual( vertexSerializer.deserialize(b, fq), {v,len} );
- return;
- }
-
- // generic case
- assert.deepStrictEqual( vertexSerializer.deserialize(concat([type_code, value_flag, b]), true), {v,len:len+2} );
- assert.deepStrictEqual( vertexSerializer.deserialize(concat([ b]), false), {v,len:len+0} );
- }))
- );
-
- describe('#canBeUsedFor', () =>
- // most of the cases are implicitly tested via AnySerializer.serialize() tests
- [
- { v: null, e: false },
- { v: undefined, e: false },
- { v: {}, e: false },
- { v: new Traverser(), e: false },
- { v: new P(), e: false },
- { v: [], e: false },
- { v: [0], e: false },
- { v: [new Vertex()], e: false },
- { v: new Vertex(), e: true },
- ].forEach(({ v, e }, i) => it(cbuf_title({i,v}), () =>
- assert.strictEqual( vertexSerializer.canBeUsedFor(v), e )
- ))
- );
-
-});
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/error-cases-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/error-cases-test.js
new file mode 100644
index 0000000000..525809d4b9
--- /dev/null
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/error-cases-test.js
@@ -0,0 +1,443 @@
+/*
+ * 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.
+ */
+
+/*
+ * Error handling tests for GraphBinaryV4 serializers. Validates behavior for
+ * malformed input: invalid buffers, unknown type codes, bad value flags,
+ * truncated data, negative lengths, and unsupported types.
+ */
+
+import { assert } from 'chai';
+import { Buffer } from 'buffer';
+import ioc from '../../../lib/structure/io/binary/GraphBinary.js';
+import { P, TextP, Traverser } from '../../../lib/process/traversal.js';
+import { OptionsStrategy } from '../../../lib/process/traversal-strategy.js';
+
+const { anySerializer, intSerializer, longSerializer, stringSerializer, listSerializer, mapSerializer, uuidSerializer, dateTimeSerializer, floatSerializer, shortSerializer, byteSerializer, bigIntegerSerializer, binarySerializer, setSerializer, enumSerializer } = ioc;
+
+describe('GraphBinary v4 Error Cases', () => {
+ describe('Buffer validation', () => {
+ it('undefined buffer throws error', () => {
+ assert.throws(() => anySerializer.deserialize(undefined), /buffer is missing/);
+ });
+
+ it('null buffer throws error', () => {
+ assert.throws(() => anySerializer.deserialize(null), /buffer is missing/);
+ });
+
+ it('non-Buffer object throws error', () => {
+ assert.throws(() => anySerializer.deserialize('not a buffer'), /buffer is missing/);
+ });
+
+ it('empty buffer throws error', () => {
+ assert.throws(() => anySerializer.deserialize(Buffer.alloc(0)), /buffer is empty/);
+ });
+
+ it('buffer with only type_code, no value_flag throws error', () => {
+ assert.throws(() => anySerializer.deserialize(Buffer.from([0x01])), /value_flag.*missing/);
+ });
+
+ it('individual serializer with undefined buffer throws error', () => {
+ assert.throws(() => intSerializer.deserialize(undefined), /buffer is missing/);
+ });
+
+ it('individual serializer with null buffer throws error', () => {
+ assert.throws(() => intSerializer.deserialize(null), /buffer is missing/);
+ });
+
+ it('individual serializer with empty buffer throws error', () => {
+ assert.throws(() => intSerializer.deserialize(Buffer.alloc(0)), /buffer is empty/);
+ });
+ });
+
+ describe('Type code errors', () => {
+ it('unknown type code throws error', () => {
+ assert.throws(() => anySerializer.deserialize(Buffer.from([0x99, 0x00])), /unknown.*type_code/);
+ });
+
+ it('wrong type code for INT throws error', () => {
+ assert.throws(() => intSerializer.deserialize(Buffer.from([0x02, 0x00, 0x00, 0x00, 0x00, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for LONG throws error', () => {
+ assert.throws(() => longSerializer.deserialize(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for STRING throws error', () => {
+ assert.throws(() => stringSerializer.deserialize(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for DOUBLE throws error', () => {
+ assert.throws(() => ioc.doubleSerializer.deserialize(Buffer.from([0x01, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for BOOLEAN throws error', () => {
+ assert.throws(() => ioc.booleanSerializer.deserialize(Buffer.from([0x01, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for UUID throws error', () => {
+ assert.throws(() => uuidSerializer.deserialize(Buffer.from([0x01, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for LIST throws error', () => {
+ assert.throws(() => listSerializer.deserialize(Buffer.from([0x01, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for MAP throws error', () => {
+ assert.throws(() => mapSerializer.deserialize(Buffer.from([0x01, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for FLOAT throws error', () => {
+ assert.throws(() => floatSerializer.deserialize(Buffer.from([0x09, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for SHORT throws error', () => {
+ assert.throws(() => shortSerializer.deserialize(Buffer.from([0x27, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for BYTE throws error', () => {
+ assert.throws(() => byteSerializer.deserialize(Buffer.from([0x25, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for BIGINTEGER throws error', () => {
+ assert.throws(() => bigIntegerSerializer.deserialize(Buffer.from([0x24, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for BINARY throws error', () => {
+ assert.throws(() => binarySerializer.deserialize(Buffer.from([0x26, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for SET throws error', () => {
+ assert.throws(() => setSerializer.deserialize(Buffer.from([0x0C, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for DATETIME throws error', () => {
+ assert.throws(() => dateTimeSerializer.deserialize(Buffer.from([0x05, 0x00])), /unexpected.*type_code/);
+ });
+
+ it('wrong type code for ENUM throws error', () => {
+ assert.throws(() => enumSerializer.deserialize(Buffer.from([0x19, 0x00])), /unexpected.*type_code/);
+ });
+ });
+
+ describe('Value flag errors', () => {
+ it('invalid value_flag 0x03 for INT throws error', () => {
+ assert.throws(() => intSerializer.deserialize(Buffer.from([0x01, 0x03])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x0F for STRING throws error', () => {
+ assert.throws(() => stringSerializer.deserialize(Buffer.from([0x03, 0x0F])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0xFF for LIST throws error', () => {
+ assert.throws(() => listSerializer.deserialize(Buffer.from([0x09, 0xFF])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x05 for MAP throws error', () => {
+ assert.throws(() => mapSerializer.deserialize(Buffer.from([0x0A, 0x05])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x10 for DOUBLE throws error', () => {
+ assert.throws(() => ioc.doubleSerializer.deserialize(Buffer.from([0x07, 0x10])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x04 for FLOAT throws error', () => {
+ assert.throws(() => floatSerializer.deserialize(Buffer.from([0x08, 0x04])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x06 for SHORT throws error', () => {
+ assert.throws(() => shortSerializer.deserialize(Buffer.from([0x26, 0x06])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x07 for BYTE throws error', () => {
+ assert.throws(() => byteSerializer.deserialize(Buffer.from([0x24, 0x07])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x08 for BIGINTEGER throws error', () => {
+ assert.throws(() => bigIntegerSerializer.deserialize(Buffer.from([0x23, 0x08])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x09 for BINARY throws error', () => {
+ assert.throws(() => binarySerializer.deserialize(Buffer.from([0x25, 0x09])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x0A for SET throws error', () => {
+ assert.throws(() => setSerializer.deserialize(Buffer.from([0x0B, 0x0A])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x0B for DATETIME throws error', () => {
+ assert.throws(() => dateTimeSerializer.deserialize(Buffer.from([0x04, 0x0B])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x0C for UUID throws error', () => {
+ assert.throws(() => uuidSerializer.deserialize(Buffer.from([0x0C, 0x0C])), /unexpected.*value_flag/);
+ });
+
+ it('invalid value_flag 0x0D for ENUM throws error', () => {
+ assert.throws(() => enumSerializer.deserialize(Buffer.from([0x18, 0x0D])), /unexpected.*value_flag/);
+ });
+
+ it('missing value_flag for INT throws error', () => {
+ assert.throws(() => intSerializer.deserialize(Buffer.from([0x01])), /value_flag.*missing/);
+ });
+
+ it('missing value_flag for STRING throws error', () => {
+ assert.throws(() => stringSerializer.deserialize(Buffer.from([0x03])), /value_flag.*missing/);
+ });
+
+ it('missing value_flag for LIST throws error', () => {
+ assert.throws(() => listSerializer.deserialize(Buffer.from([0x09])), /value_flag.*missing/);
+ });
+
+ it('missing value_flag for MAP throws error', () => {
+ assert.throws(() => mapSerializer.deserialize(Buffer.from([0x0A])), /value_flag.*missing/);
+ });
+ });
+
+ describe('Truncated data', () => {
+ it('INT with only 2 of 4 value bytes throws error', () => {
+ assert.throws(() => intSerializer.deserialize(Buffer.from([0x01, 0x00, 0x00, 0x01])), /unexpected.*value.*length/);
+ });
+
+ it('LONG with only 4 of 8 value bytes throws error', () => {
+ assert.throws(() => longSerializer.deserialize(Buffer.from([0x02, 0x00, 0x00, 0x00, 0x00, 0x01])), /unexpected.*value.*length/);
+ });
+
+ it('DOUBLE with only 4 of 8 value bytes throws error', () => {
+ assert.throws(() => ioc.doubleSerializer.deserialize(Buffer.from([0x07, 0x00, 0x00, 0x00, 0x00, 0x01])), /unexpected.*value.*length/);
+ });
+
+ it('FLOAT with only 2 of 4 value bytes throws error', () => {
+ assert.throws(() => ioc.floatSerializer.deserialize(Buffer.from([0x08, 0x00, 0x00, 0x01])), /unexpected.*value.*length/);
+ });
+
+ it('SHORT with only 1 of 2 value bytes throws error', () => {
+ assert.throws(() => ioc.shortSerializer.deserialize(Buffer.from([0x26, 0x00, 0x01])), /unexpected.*value.*length/);
+ });
+
+ it('STRING with length 10 but only 3 bytes throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x03, 0x00]), // STRING, value_flag=0x00
+ Buffer.from([0x00, 0x00, 0x00, 0x0A]), // length=10
+ Buffer.from([0x41, 0x42, 0x43]) // only 3 bytes: "ABC"
+ ]);
+ assert.throws(() => stringSerializer.deserialize(buffer), /unexpected.*text_value.*length/);
+ });
+
+ it('LIST with length 5 but only 1 item throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x09, 0x00]), // LIST, value_flag=0x00
+ Buffer.from([0x00, 0x00, 0x00, 0x05]), // length=5
+ Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x01]) // only 1 INT item
+ ]);
+ assert.throws(() => listSerializer.deserialize(buffer), /item_1.*buffer is empty/);
+ });
+
+ it('MAP with length 3 but only 1 entry throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x0A, 0x00]), // MAP, value_flag=0x00
+ Buffer.from([0x00, 0x00, 0x00, 0x03]), // length=3
+ Buffer.from([0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x6B, 0x65, 0x79]), // key: "key"
+ Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x01]) // value: 1
+ ]);
+ assert.throws(() => mapSerializer.deserialize(buffer), /{item_1}.*buffer is empty/);
+ });
+
+ it('UUID with only 8 of 16 bytes throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x0C, 0x00]), // UUID, value_flag=0x00
+ Buffer.from([0x41, 0xD2, 0xE2, 0x8A, 0x20, 0x13, 0x4E, 0x35]) // only 8 bytes
+ ]);
+ assert.throws(() => uuidSerializer.deserialize(buffer), /unexpected.*value.*length/);
+ });
+
+ it('DATETIME with only 10 of 18 bytes throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x04, 0x00]), // DATETIME, value_flag=0x00
+ Buffer.from([0x07, 0xB2, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) // only 10 bytes
+ ]);
+ assert.throws(() => dateTimeSerializer.deserialize(buffer), /unexpected.*value.*length/);
+ });
+
+ it('BOOLEAN with no value byte throws error', () => {
+ assert.throws(() => ioc.booleanSerializer.deserialize(Buffer.from([0x27, 0x00])), /unexpected.*value.*length/);
+ });
+
+ it('BYTE with no value byte throws error', () => {
+ assert.throws(() => ioc.byteSerializer.deserialize(Buffer.from([0x24, 0x00])), /unexpected.*value.*length/);
+ });
+
+ it('BIGINTEGER with truncated length throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x23, 0x00]), // BIGINTEGER, value_flag=0x00
+ Buffer.from([0x00, 0x00]) // only 2 bytes of length instead of 4
+ ]);
+ assert.throws(() => bigIntegerSerializer.deserialize(buffer), /{length}.*unexpected.*value.*length/);
+ });
+
+ it('BIGINTEGER with length=0 throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x23, 0x00]), // BIGINTEGER, value_flag=0x00
+ Buffer.from([0x00, 0x00, 0x00, 0x00]) // length=0
+ ]);
+ assert.throws(() => bigIntegerSerializer.deserialize(buffer), /{length}=0 is less than one/);
+ });
+
+ it('BINARY with truncated value data throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x25, 0x00]), // BINARY, value_flag=0x00
+ Buffer.from([0x00, 0x00, 0x00, 0x05]), // length=5
+ Buffer.from([0x01, 0x02]) // only 2 bytes instead of 5
+ ]);
+ assert.throws(() => binarySerializer.deserialize(buffer), /{value}.*unexpected.*value.*length/);
+ });
+
+ it('SET with length 5 but only 1 item throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x0B, 0x00]), // SET, value_flag=0x00
+ Buffer.from([0x00, 0x00, 0x00, 0x05]), // length=5
+ Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x01]) // only 1 INT item
+ ]);
+ assert.throws(() => setSerializer.deserialize(buffer), /{item_1}.*buffer is empty/);
+ });
+
+ it('ENUM with truncated elementName throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x18, 0x00]), // DIRECTION, value_flag=0x00
+ Buffer.from([0x03, 0x00, 0x00, 0x00, 0x00, 0x05]) // STRING with length=5 but no data
+ ]);
+ assert.throws(() => enumSerializer.deserialize(buffer), /elementName.*unexpected.*text_value.*length/);
+ });
+ });
+
+ describe('Negative lengths', () => {
+ it('STRING with negative length throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x03, 0x00]), // STRING, value_flag=0x00
+ Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]) // length=-1
+ ]);
+ assert.throws(() => stringSerializer.deserialize(buffer), /length.*less than zero/);
+ });
+
+ it('LIST with negative length throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x09, 0x00]), // LIST, value_flag=0x00
+ Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]) // length=-1
+ ]);
+ assert.throws(() => listSerializer.deserialize(buffer), /length.*less than zero/);
+ });
+
+ it('MAP with negative length throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x0A, 0x00]), // MAP, value_flag=0x00
+ Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]) // length=-1
+ ]);
+ assert.throws(() => mapSerializer.deserialize(buffer), /length.*less than zero/);
+ });
+
+ it('SET with negative length throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x0B, 0x00]), // SET, value_flag=0x00
+ Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]) // length=-1
+ ]);
+ assert.throws(() => ioc.setSerializer.deserialize(buffer), /length.*less than zero/);
+ });
+
+ it('BINARY with negative length throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x25, 0x00]), // BINARY, value_flag=0x00
+ Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]) // length=-1
+ ]);
+ assert.throws(() => ioc.binarySerializer.deserialize(buffer), /length.*less than zero/);
+ });
+ });
+
+ describe('Bulk flag errors', () => {
+ it('LIST with bulk flag but missing bulk count data throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x09, 0x02]), // LIST, value_flag=0x02 (bulk)
+ Buffer.from([0x00, 0x00, 0x00, 0x01]), // length=1
+ Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x01]) // 1 INT item but no bulk count
+ ]);
+ assert.throws(() => listSerializer.deserialize(buffer), /{item_0}.*bulk count is missing/);
+ });
+
+ it('SET with bulk flag but missing bulk count data throws error', () => {
+ const buffer = Buffer.concat([
+ Buffer.from([0x0B, 0x02]), // SET, value_flag=0x02 (bulk)
+ Buffer.from([0x00, 0x00, 0x00, 0x01]), // length=1
+ Buffer.from([0x01, 0x00, 0x00, 0x00, 0x00, 0x01]) // 1 INT item but no bulk count
+ ]);
+ assert.throws(() => setSerializer.deserialize(buffer), /{item_0}.*bulk count is missing/);
+ });
+ });
+
+ describe('Serialization rejection for unsupported types', () => {
+ it('Symbol throws error', () => {
+ assert.throws(() => anySerializer.serialize(Symbol('test')), /No serializer found to support item/);
+ });
+
+ it('function throws error', () => {
+ assert.throws(() => anySerializer.serialize(() => {}), /No serializer found to support item/);
+ });
+
+ it('arrow function throws error', () => {
+ assert.throws(() => anySerializer.serialize((x) => x + 1), /No serializer found to support item/);
+ });
+
+ it('async function throws error', () => {
+ assert.throws(() => anySerializer.serialize(async () => {}), /No serializer found to support item/);
+ });
+
+ it('generator function throws error', () => {
+ assert.throws(() => anySerializer.serialize(function* () {}), /No serializer found to support item/);
+ });
+
+ it('class constructor throws error', () => {
+ class TestClass {}
+ assert.throws(() => anySerializer.serialize(TestClass), /No serializer found to support item/);
+ });
+ });
+
+ describe('v1-removed types serialization behavior', () => {
+ it('P.eq("cole") serializes as Map (v1 types fall through to MapSerializer)', () => {
+ // v1 P types no longer have dedicated serializers, so they serialize as Maps
+ const result = anySerializer.serialize(P.eq('cole'));
+ assert.ok(result.length > 0, 'Should serialize successfully as Map');
+ });
+
+ it('TextP.containing("x") serializes as Map (v1 types fall through to MapSerializer)', () => {
+ // v1 TextP types no longer have dedicated serializers, so they serialize as Maps
+ const result = anySerializer.serialize(TextP.containing('x'));
+ assert.ok(result.length > 0, 'Should serialize successfully as Map');
+ });
+
+ it('new Traverser("cole", 1) serializes as Map (v1 types fall through to MapSerializer)', () => {
+ // v1 Traverser types no longer have dedicated serializers, so they serialize as Maps
+ const result = anySerializer.serialize(new Traverser('cole', 1));
+ assert.ok(result.length > 0, 'Should serialize successfully as Map');
+ });
+
+ it('new OptionsStrategy({}) serializes as Map (v1 types fall through to MapSerializer)', () => {
+ // v1 OptionsStrategy types no longer have dedicated serializers, so they serialize as Maps
+ const result = anySerializer.serialize(new OptionsStrategy({}));
+ assert.ok(result.length > 0, 'Should serialize successfully as Map');
+ });
+ });
+});
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/model-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/model-test.js
new file mode 100644
index 0000000000..afc35a5b06
--- /dev/null
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/model-test.js
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ */
+
+/*
+ * GraphBinaryV4 .gbin reference file validation against expected JS model values.
+ *
+ * Set the IO_TEST_DIRECTORY environment variable to the directory where
+ * the .gbin files that represent the serialized "model" are located.
+ */
+
+import { assert } from 'chai';
+import { readFileSync } from 'fs';
+import { fileURLToPath } from 'url';
+import { model } from './model.js';
+import ioc from '../../../lib/structure/io/binary/GraphBinary.js';
+
+const { anySerializer } = ioc;
+
+const gbinDir = 'gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/graphbinary/';
+const searchPattern = 'gremlin-javascript/src/main';
+const thisFile = fileURLToPath(import.meta.url);
+const defaultDir = thisFile.substring(0, thisFile.indexOf(searchPattern));
+const testResourceDirectory = process.env.IO_TEST_DIRECTORY || (defaultDir + gbinDir);
+
+function readGbinFile(name) {
+ return readFileSync(testResourceDirectory + name + '-v4.gbin');
+}
+
+// byte-exact: deserialize, serialize, round-trip, length tracking
+function run(name, comparator = assertEqual) {
+ describe(name, () => {
+ const fileBytes = readGbinFile(name);
+ const modelValue = model[name];
+
+ it('deserialize .gbin matches model', () => {
+ const result = anySerializer.deserialize(fileBytes);
+ comparator(result.v, modelValue);
+ });
+
+ it('serialize model matches .gbin bytes', () => {
+ const serialized = anySerializer.serialize(modelValue);
+ assert.deepStrictEqual(serialized, fileBytes);
+ });
+
+ it('round-trip serialize(deserialize(fileBytes)) matches .gbin', () => {
+ const deserialized = anySerializer.deserialize(fileBytes);
+ const reserialized = anySerializer.serialize(deserialized.v);
+ assert.deepStrictEqual(reserialized, fileBytes);
+ });
+
+ it('length tracking', () => {
+ const garbageBytes = Buffer.concat([fileBytes, Buffer.from([0xFF])]);
+ const result = anySerializer.deserialize(garbageBytes);
+ assert.strictEqual(result.len, fileBytes.length);
+ });
+ });
+}
+
+// object-level: deserialize, double round-trip idempotency, length tracking
+function runWriteRead(name, comparator = assertEqual) {
+ describe(name, () => {
+ const fileBytes = readGbinFile(name);
+ const modelValue = model[name];
+
+ it('deserialize .gbin matches model', () => {
+ const result = anySerializer.deserialize(fileBytes);
+ comparator(result.v, modelValue);
+ });
+
+ it('double round-trip idempotency', () => {
+ const firstRoundTrip = anySerializer.deserialize(anySerializer.serialize(modelValue));
+ const secondRoundTrip = anySerializer.deserialize(anySerializer.serialize(firstRoundTrip.v));
+ comparator(firstRoundTrip.v, secondRoundTrip.v);
+ });
+
+ it('length tracking', () => {
+ const garbageBytes = Buffer.concat([fileBytes, Buffer.from([0xFF])]);
+ const result = anySerializer.deserialize(garbageBytes);
+ assert.strictEqual(result.len, fileBytes.length);
+ });
+ });
+}
+
+// deserialize-only: deserialize, length tracking
+function runRead(name, comparator = assertEqual) {
+ describe(name, () => {
+ const fileBytes = readGbinFile(name);
+ const modelValue = model[name];
+
+ it('deserialize .gbin matches model', () => {
+ const result = anySerializer.deserialize(fileBytes);
+ comparator(result.v, modelValue);
+ });
+
+ it('length tracking', () => {
+ const garbageBytes = Buffer.concat([fileBytes, Buffer.from([0xFF])]);
+ const result = anySerializer.deserialize(garbageBytes);
+ assert.strictEqual(result.len, fileBytes.length);
+ });
+ });
+}
+
+// unimplemented type
+function skip(name, reason) {
+ describe(name, () => {
+ it.skip(`${reason}`, () => {});
+ });
+}
+
+function assertEqual(actual, expected) {
+ if (Number.isNaN(expected) && Number.isNaN(actual)) return;
+ if (Object.is(expected, -0) && Object.is(actual, -0)) return;
+ if (Buffer.isBuffer(expected) && Buffer.isBuffer(actual)) {
+ assert.isTrue(expected.equals(actual));
+ return;
+ }
+ if (expected instanceof Set && actual instanceof Set) {
+ assert.deepStrictEqual([...expected].sort(), [...actual].sort());
+ return;
+ }
+ if (typeof expected === 'bigint' && typeof actual === 'bigint') {
+ assert.strictEqual(actual, expected);
+ return;
+ }
+ assert.deepStrictEqual(actual, expected);
+}
+
+function nanComparator(actual, expected) {
+ assert.isTrue(Number.isNaN(actual));
+ assert.isTrue(Number.isNaN(expected));
+}
+
+function negZeroComparator(actual, expected) {
+ assert.isTrue(Object.is(actual, -0));
+ assert.isTrue(Object.is(expected, -0));
+}
+
+function setComparator(actual, expected) {
+ assert.instanceOf(actual, Set);
+ assert.instanceOf(expected, Set);
+ assert.deepStrictEqual([...actual].sort(), [...expected].sort());
+}
+
+function setCardinalityComparator(actual, expected) {
+ assert.strictEqual(actual.id, expected.id);
+ assert.strictEqual(actual.label, expected.label);
+ assert.instanceOf(actual.value, Set);
+ assert.instanceOf(expected.value, Set);
+ assert.deepStrictEqual([...actual.value].sort(), [...expected.value].sort());
+ assert.deepStrictEqual(actual.properties, expected.properties);
+}
+
+function invalidDateComparator(actual, expected) {
+ assert.isTrue(actual instanceof Date);
+ assert.isTrue(expected instanceof Date);
+ assert.isTrue(Number.isNaN(actual.getTime()));
+ assert.isTrue(Number.isNaN(expected.getTime()));
+}
+
+describe('GraphBinary v4 Model Tests', () => {
+ // run mode (32 entries)
+ run('pos-biginteger');
+ run('neg-biginteger');
+ run('empty-binary');
+ run('str-binary');
+ run('max-double');
+ run('min-double');
+ run('neg-max-double');
+ run('neg-min-double');
+ run('nan-double', nanComparator);
+ run('pos-inf-double');
+ run('neg-inf-double');
+ run('unspecified-null');
+ run('true-boolean');
+ run('false-boolean');
+ run('single-byte-string');
+ run('mixed-string');
+ run('var-type-list');
+ run('empty-list');
+ run('no-prop-edge');
+ run('max-int');
+ run('min-int');
+ run('min-long');
+ run('empty-map');
+ run('traversal-path');
+ run('empty-path');
+ run('edge-property');
+ run('null-property');
+ run('empty-set');
+ run('no-prop-vertex');
+ run('id-t');
+ run('out-direction');
+ run('neg-zero-double', negZeroComparator);
+
+ // runWriteRead mode (22 entries)
+ runWriteRead('min-byte');
+ runWriteRead('max-byte');
+ runWriteRead('max-float');
+ runWriteRead('min-float');
+ runWriteRead('neg-max-float');
+ runWriteRead('neg-min-float');
+ runWriteRead('nan-float', nanComparator);
+ runWriteRead('pos-inf-float');
+ runWriteRead('neg-inf-float');
+ runWriteRead('var-bulklist');
+ runWriteRead('empty-bulklist');
+ runWriteRead('traversal-edge');
+ runWriteRead('max-long');
+ runWriteRead('var-type-set', setComparator);
+ runWriteRead('max-short');
+ runWriteRead('min-short');
+ runWriteRead('specified-uuid');
+ runWriteRead('nil-uuid');
+ runWriteRead('traversal-vertexproperty');
+ runWriteRead('meta-vertexproperty');
+ runWriteRead('set-cardinality-vertexproperty', setCardinalityComparator);
+ runWriteRead('traversal-vertex');
+
+ // runRead mode (5 entries)
+ runRead('neg-zero-float', negZeroComparator);
+ runRead('max-offsetdatetime', invalidDateComparator);
+ runRead('min-offsetdatetime', invalidDateComparator);
+ runRead('prop-path');
+ runRead('var-type-map');
+
+ // skip mode (8 entries)
+ skip('single-byte-char', 'Char type (0x80) not implemented');
+ skip('multi-byte-char', 'Char type (0x80) not implemented');
+ skip('traversal-tree', 'Tree type not implemented');
+ skip('tinker-graph', 'Graph type not implemented');
+ skip('pos-bigdecimal', 'BigDecimal type not implemented');
+ skip('neg-bigdecimal', 'BigDecimal type not implemented');
+ skip('forever-duration', 'Duration type not implemented');
+ skip('zero-duration', 'Duration type not implemented');
+});
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/model.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/model.js
new file mode 100644
index 0000000000..3ffb6d0c67
--- /dev/null
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/model.js
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+import { Vertex, Edge, Property, VertexProperty, Path } from '../../../lib/structure/graph.js';
+import { direction, t } from '../../../lib/process/traversal.js';
+
+/*
+ * Unsupported types (no map entries, .gbin files exist but types not implemented):
+ * - single-byte-char, multi-byte-char (Char 0x80 not implemented)
+ * - traversal-tree (Tree type not implemented)
+ * - tinker-graph (Graph type not implemented)
+ * - pos-bigdecimal, neg-bigdecimal (BigDecimal type not implemented)
+ * - forever-duration, zero-duration (Duration type not implemented)
+ */
+
+const model = {};
+
+// BigInteger values
+model['pos-biginteger'] = BigInt('123456789987654321123456789987654321');
+model['neg-biginteger'] = BigInt('-123456789987654321123456789987654321');
+
+// Byte values (JS has no byte type, deserializes to Number)
+model['min-byte'] = -128;
+model['max-byte'] = 127;
+
+// Binary values
+model['empty-binary'] = Buffer.from('', 'utf-8');
+model['str-binary'] = Buffer.from('some bytes for you', 'utf-8');
+
+// Double values
+model['max-double'] = 1.7976931348623157e+308;
+model['min-double'] = 5e-324;
+model['neg-max-double'] = -1.7976931348623157e+308;
+model['neg-min-double'] = -5e-324;
+model['nan-double'] = NaN;
+model['pos-inf-double'] = Infinity;
+model['neg-inf-double'] = -Infinity;
+model['neg-zero-double'] = -0;
+
+// Float values (JS has no float type, deserializes to Number with IEEE 754 double representation)
+model['max-float'] = 3.4028234663852886e+38;
+model['min-float'] = 1.401298464324817e-45;
+model['neg-max-float'] = -3.4028234663852886e+38;
+model['neg-min-float'] = -1.401298464324817e-45;
+model['nan-float'] = NaN;
+model['pos-inf-float'] = Infinity;
+model['neg-inf-float'] = -Infinity;
+model['neg-zero-float'] = -0;
+
+// Null
+model['unspecified-null'] = null;
+
+// Boolean values
+model['true-boolean'] = true;
+model['false-boolean'] = false;
+
+// String values
+model['single-byte-string'] = 'abc';
+model['mixed-string'] = 'abc\u0391\u0392\u0393';
+
+// List values
+model['var-bulklist'] = ['marko', 'josh', 'josh'];
+model['empty-bulklist'] = [];
+model['var-type-list'] = [1, 'person', true, null];
+model['empty-list'] = [];
+
+// Edge values
+model['traversal-edge'] = new Edge(
+ 13,
+ new Vertex(1, 'person'), // outV (first in JS constructor)
+ 'develops',
+ new Vertex(10, 'software'), // inV
+ [new Property('since', 2009)]
+);
+model['no-prop-edge'] = new Edge(
+ 13,
+ new Vertex(1, 'person'),
+ 'develops',
+ new Vertex(10, 'software')
+);
+
+// Integer values
+model['max-int'] = 2147483647;
+model['min-int'] = -2147483648;
+
+// Long values (lose precision beyond 2^53 in JS)
+model['max-long'] = 9223372036854776000; // Number, not BigInt
+model['min-long'] = -9223372036854776000;
+
+// Map values
+const dateKey = new Date(Date.UTC(1970, 0, 1, 0, 24, 41, 295)); // 1481295 ms
+model['var-type-map'] = new Map([
+ [null, null],
+ [[1, 2, 3], dateKey],
+ [dateKey, 'red'],
+ ['test', 123]
+]);
+model['empty-map'] = new Map();
+
+// Path values
+model['traversal-path'] = new Path(
+ [new Set(), new Set(), new Set()],
+ [new Vertex(1, 'person'), new Vertex(10, 'software'), new Vertex(11, 'software')]
+);
+model['empty-path'] = new Path([], []);
+
+// Complex path with nested properties
+const propPathVertex = new Vertex(1, 'person', [
+ new VertexProperty(0, 'name', 'marko'),
+ new VertexProperty(6, 'location', 'san diego', [
+ new Property('startTime', 1997),
+ new Property('endTime', 2001)
+ ]),
+ new VertexProperty(7, 'location', 'santa cruz', [
+ new Property('startTime', 2001),
+ new Property('endTime', 2004)
+ ]),
+ new VertexProperty(8, 'location', 'brussels', [
+ new Property('startTime', 2004),
+ new Property('endTime', 2005)
+ ]),
+ new VertexProperty(9, 'location', 'santa fe', [
+ new Property('startTime', 2005)
+ ])
+]);
+const propPathVertex2 = new Vertex(10, 'software', [
+ new VertexProperty(4, 'name', 'gremlin')
+]);
+const propPathVertex3 = new Vertex(11, 'software', [
+ new VertexProperty(5, 'name', 'tinkergraph')
+]);
+model['prop-path'] = new Path(
+ [new Set(), new Set(), new Set()],
+ [propPathVertex, propPathVertex2, propPathVertex3]
+);
+
+// Property values (no parent param in JS)
+model['edge-property'] = new Property('since', 2009);
+model['null-property'] = new Property('', null);
+
+// Set values
+model['var-type-set'] = new Set([2, 'person', true, null]);
+model['empty-set'] = new Set();
+
+// Short values (JS has no short type, deserializes to Number)
+model['max-short'] = 32767;
+model['min-short'] = -32768;
+
+// UUID values (plain strings in JS)
+model['specified-uuid'] = '41d2e28a-20a4-4ab0-b379-d810dede3786';
+model['nil-uuid'] = '00000000-0000-0000-0000-000000000000';
+
+// Vertex values
+model['no-prop-vertex'] = new Vertex(1, 'person');
+
+// VertexProperty values (no parent param, key equals label)
+model['traversal-vertexproperty'] = new VertexProperty(0, 'name', 'marko');
+model['meta-vertexproperty'] = new VertexProperty(1, 'person', 'stephen', [new Property('a', 'b')]);
+model['set-cardinality-vertexproperty'] = new VertexProperty(1, 'person', new Set(['stephen', 'marko']), [new Property('a', 'b')]);
+
+// Enum values
+model['id-t'] = t.id;
+model['out-direction'] = direction.out;
+
+// Complex vertex with properties (from .gbin deserialization structure)
+const name = new VertexProperty(0, 'name', 'marko');
+const sanDiego = new VertexProperty(6, 'location', 'san diego', [
+ new Property('startTime', 1997),
+ new Property('endTime', 2001)
+]);
+const santaCruz = new VertexProperty(7, 'location', 'santa cruz', [
+ new Property('startTime', 2001),
+ new Property('endTime', 2004)
+]);
+const brussels = new VertexProperty(8, 'location', 'brussels', [
+ new Property('startTime', 2004),
+ new Property('endTime', 2005)
+]);
+const santaFe = new VertexProperty(9, 'location', 'santa fe', [
+ new Property('startTime', 2005)
+]);
+model['traversal-vertex'] = new Vertex(1, 'person', [name, sanDiego, santaCruz, brussels, santaFe]);
+
+// DateTime values (invalid dates for overflow cases)
+model['max-offsetdatetime'] = new Date(NaN); // Year 999999999 overflows JS Date
+model['min-offsetdatetime'] = new Date(NaN); // Year -999999999 overflows JS Date
+
+export { model };
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/null-handling-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/null-handling-test.js
new file mode 100644
index 0000000000..c7961e6d0b
--- /dev/null
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/null-handling-test.js
@@ -0,0 +1,233 @@
+/*
+ * 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.
+ */
+
+/*
+ * Null and undefined handling tests for GraphBinaryV4. Validates
+ * fully-qualified and bare null serialization/deserialization for
+ * every supported type.
+ */
+
+import { assert } from 'chai';
+import ioc from '../../../lib/structure/io/binary/GraphBinary.js';
+const { anySerializer, DataType } = ioc;
+
+describe('GraphBinary v4 Null Handling Tests', () => {
+ describe('anySerializer level', () => {
+ it('serialize null', () => {
+ const result = anySerializer.serialize(null);
+ assert.deepStrictEqual(result, Buffer.from([0xFE, 0x01]));
+ });
+
+ it('serialize undefined', () => {
+ const result = anySerializer.serialize(undefined);
+ assert.deepStrictEqual(result, Buffer.from([0xFE, 0x01]));
+ });
+
+ it('deserialize unspecified null', () => {
+ const result = anySerializer.deserialize(Buffer.from([0xFE, 0x01]));
+ assert.strictEqual(result.v, null);
+ assert.strictEqual(result.len, 2);
+ });
+ });
+
+ describe('per-type fully-qualified null', () => {
+ const types = [
+ { name: 'INT', code: DataType.INT, serializer: 'intSerializer' },
+ { name: 'LONG', code: DataType.LONG, serializer: 'longSerializer' },
+ { name: 'STRING', code: DataType.STRING, serializer: 'stringSerializer' },
+ { name: 'DOUBLE', code: DataType.DOUBLE, serializer: 'doubleSerializer' },
+ { name: 'FLOAT', code: DataType.FLOAT, serializer: 'floatSerializer' },
+ { name: 'BOOLEAN', code: DataType.BOOLEAN, serializer: 'booleanSerializer' },
+ { name: 'SHORT', code: DataType.SHORT, serializer: 'shortSerializer' },
+ { name: 'BYTE', code: DataType.BYTE, serializer: 'byteSerializer' },
+ { name: 'UUID', code: DataType.UUID, serializer: 'uuidSerializer' },
+ { name: 'BIGINTEGER', code: DataType.BIGINTEGER, serializer: 'bigIntegerSerializer' },
+ { name: 'DATETIME', code: DataType.DATETIME, serializer: 'dateTimeSerializer' },
+ { name: 'BINARY', code: DataType.BINARY, serializer: 'binarySerializer' },
+ { name: 'LIST', code: DataType.LIST, serializer: 'listSerializer' },
+ { name: 'SET', code: DataType.SET, serializer: 'setSerializer' },
+ { name: 'MAP', code: DataType.MAP, serializer: 'mapSerializer' },
+ { name: 'VERTEX', code: DataType.VERTEX, serializer: 'vertexSerializer' },
+ { name: 'EDGE', code: DataType.EDGE, serializer: 'edgeSerializer' },
+ { name: 'PROPERTY', code: DataType.PROPERTY, serializer: 'propertySerializer' },
+ { name: 'VERTEXPROPERTY', code: DataType.VERTEXPROPERTY, serializer: 'vertexPropertySerializer' },
+ { name: 'PATH', code: DataType.PATH, serializer: 'pathSerializer' }
+ ];
+
+ types.forEach(({ name, code, serializer }) => {
+ describe(name, () => {
+ it('serialize null fully-qualified', () => {
+ const result = ioc[serializer].serialize(null, true);
+ assert.deepStrictEqual(result, Buffer.from([code, 0x01]));
+ });
+
+ it('serialize undefined fully-qualified', () => {
+ const result = ioc[serializer].serialize(undefined, true);
+ assert.deepStrictEqual(result, Buffer.from([code, 0x01]));
+ });
+
+ it('deserialize fully-qualified null', () => {
+ const result = ioc[serializer].deserialize(Buffer.from([code, 0x01]), true);
+ assert.strictEqual(result.v, null);
+ assert.strictEqual(result.len, 2);
+ });
+ });
+ });
+
+ // EnumSerializer has special null handling - it doesn't support null/undefined directly
+ describe('DIRECTION', () => {
+ it('deserialize fully-qualified null', () => {
+ const result = ioc.enumSerializer.deserialize(Buffer.from([DataType.DIRECTION, 0x01]), true);
+ assert.strictEqual(result.v, null);
+ assert.strictEqual(result.len, 2);
+ });
+ });
+
+ describe('T', () => {
+ it('deserialize fully-qualified null', () => {
+ const result = ioc.enumSerializer.deserialize(Buffer.from([DataType.T, 0x01]), true);
+ assert.strictEqual(result.v, null);
+ assert.strictEqual(result.len, 2);
+ });
+ });
+
+ describe('MERGE', () => {
+ it('deserialize fully-qualified null', () => {
+ const result = ioc.enumSerializer.deserialize(Buffer.from([DataType.MERGE, 0x01]), true);
+ assert.strictEqual(result.v, null);
+ assert.strictEqual(result.len, 2);
+ });
+ });
+ });
+
+ describe('per-type bare null', () => {
+ const bareNullTests = [
+ { name: 'INT', serializer: 'intSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: 0 },
+ { name: 'LONG', serializer: 'longSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), defaultValue: 0 },
+ { name: 'STRING', serializer: 'stringSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: '' },
+ { name: 'DOUBLE', serializer: 'doubleSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), defaultValue: 0.0 },
+ { name: 'FLOAT', serializer: 'floatSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: 0.0 },
+ { name: 'BOOLEAN', serializer: 'booleanSerializer', expected: Buffer.from([0x00]), defaultValue: false },
+ { name: 'SHORT', serializer: 'shortSerializer', expected: Buffer.from([0x00, 0x00]), defaultValue: 0 },
+ { name: 'BYTE', serializer: 'byteSerializer', expected: Buffer.from([0x00]), defaultValue: 0 },
+ { name: 'UUID', serializer: 'uuidSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), defaultValue: '00000000-0000-0000-0000-000000000000' },
+ { name: 'BIGINTEGER', serializer: 'bigIntegerSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x01, 0x00]), defaultValue: BigInt(0) },
+ { name: 'DATETIME', serializer: 'dateTimeSerializer', expected: Buffer.alloc(18), defaultValue: null },
+ { name: 'BINARY', serializer: 'binarySerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: Buffer.alloc(0) }
+ ];
+
+ bareNullTests.forEach(({ name, serializer, expected, defaultValue }) => {
+ describe(name, () => {
+ it('serialize null bare', () => {
+ const result = ioc[serializer].serialize(null, false);
+ assert.deepStrictEqual(result, expected);
+ });
+
+ it('serialize undefined bare', () => {
+ const result = ioc[serializer].serialize(undefined, false);
+ assert.deepStrictEqual(result, expected);
+ });
+
+ it('deserialize bare null', () => {
+ const result = ioc[serializer].deserialize(expected, false);
+ if (defaultValue === null) {
+ // DATETIME: 18 zero bytes produce a valid Date object but with implementation-defined value
+ assert.instanceOf(result.v, Date);
+ } else if (typeof defaultValue === 'bigint') {
+ assert.strictEqual(result.v, defaultValue);
+ } else if (Buffer.isBuffer(defaultValue)) {
+ assert.isTrue(Buffer.isBuffer(result.v));
+ assert.isTrue(result.v.equals(defaultValue));
+ } else if (defaultValue instanceof Date) {
+ assert.instanceOf(result.v, Date);
+ } else {
+ assert.strictEqual(result.v, defaultValue);
+ }
+ assert.strictEqual(result.len, expected.length);
+ });
+ });
+ });
+
+ // Collection types have different bare null behavior
+ const collectionTests = [
+ { name: 'LIST', serializer: 'listSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: [] },
+ { name: 'SET', serializer: 'setSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: new Set() },
+ { name: 'MAP', serializer: 'mapSerializer', expected: Buffer.from([0x00, 0x00, 0x00, 0x00]), defaultValue: new Map() }
+ ];
+
+ collectionTests.forEach(({ name, serializer, expected, defaultValue }) => {
+ describe(name, () => {
+ it('serialize null bare', () => {
+ const result = ioc[serializer].serialize(null, false);
+ assert.deepStrictEqual(result, expected);
+ });
+
+ it('serialize undefined bare', () => {
+ const result = ioc[serializer].serialize(undefined, false);
+ assert.deepStrictEqual(result, expected);
+ });
+
+ it('deserialize bare null', () => {
+ const result = ioc[serializer].deserialize(expected, false);
+ if (defaultValue instanceof Set) {
+ assert.instanceOf(result.v, Set);
+ assert.strictEqual(result.v.size, 0);
+ } else if (defaultValue instanceof Map) {
+ assert.instanceOf(result.v, Map);
+ assert.strictEqual(result.v.size, 0);
+ } else if (Array.isArray(defaultValue)) {
+ assert.isArray(result.v);
+ assert.strictEqual(result.v.length, 0);
+ }
+ assert.strictEqual(result.len, expected.length);
+ });
+ });
+ });
+
+ // Graph types serialize to empty structures
+ const graphTests = [
+ { name: 'VERTEX', serializer: 'vertexSerializer' },
+ { name: 'EDGE', serializer: 'edgeSerializer' },
+ { name: 'PROPERTY', serializer: 'propertySerializer' },
+ { name: 'VERTEXPROPERTY', serializer: 'vertexPropertySerializer' },
+ { name: 'PATH', serializer: 'pathSerializer' }
+ ];
+
+ graphTests.forEach(({ name, serializer }) => {
+ describe(name, () => {
+ it('serialize null bare produces non-empty bytes', () => {
+ const result = ioc[serializer].serialize(null, false);
+ assert.isTrue(result.length > 0);
+ });
+
+ it('serialize undefined bare produces non-empty bytes', () => {
+ const result = ioc[serializer].serialize(undefined, false);
+ assert.isTrue(result.length > 0);
+ });
+
+ it('deserialize bare null produces default object', () => {
+ const nullBytes = ioc[serializer].serialize(null, false);
+ const result = ioc[serializer].deserialize(nullBytes, false);
+ assert.isNotNull(result.v);
+ assert.strictEqual(result.len, nullBytes.length);
+ });
+ });
+ });
+ });
+});
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/type-detection-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/type-detection-test.js
new file mode 100644
index 0000000000..121568e850
--- /dev/null
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/type-detection-test.js
@@ -0,0 +1,397 @@
+/*
+ * 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.
+ */
+
+/*
+ * Type detection and dispatch tests for GraphBinaryV4. Verifies that
+ * anySerializer routes each JS type to the correct serializer type code,
+ * canBeUsedFor rejects wrong types, and round-trip extras not covered
+ * by .gbin reference files.
+ */
+
+import { assert } from 'chai';
+import { Vertex, Edge, Property, VertexProperty, Path } from '../../../lib/structure/graph.js';
+import { direction, t, merge } from '../../../lib/process/traversal.js';
+import ioc, { DataType } from '../../../lib/structure/io/binary/GraphBinary.js';
+
+const { anySerializer } = ioc;
+
+describe('Type Detection Tests', () => {
+ describe('Number routing (NumberSerializationStrategy)', () => {
+ it('Integer in Int32 range → INT (0x01)', () => {
+ const result = anySerializer.serialize(42);
+ assert.strictEqual(result[0], DataType.INT);
+ });
+
+ it('Integer at Int32 boundaries → INT (0x01)', () => {
+ assert.strictEqual(anySerializer.serialize(2147483647)[0], DataType.INT);
+ assert.strictEqual(anySerializer.serialize(-2147483648)[0], DataType.INT);
+ });
+
+ it('Integer beyond Int32 but in Int64 → LONG (0x02)', () => {
+ const result = anySerializer.serialize(2147483648);
+ assert.strictEqual(result[0], DataType.LONG);
+ });
+
+ it('Number.MAX_SAFE_INTEGER → LONG (0x02)', () => {
+ const result = anySerializer.serialize(Number.MAX_SAFE_INTEGER);
+ assert.strictEqual(result[0], DataType.LONG);
+ });
+
+ it('Number.MIN_SAFE_INTEGER → LONG (0x02)', () => {
+ const result = anySerializer.serialize(Number.MIN_SAFE_INTEGER);
+ assert.strictEqual(result[0], DataType.LONG);
+ });
+
+ it('Non-integer → DOUBLE (0x07)', () => {
+ assert.strictEqual(anySerializer.serialize(3.14)[0], DataType.DOUBLE);
+ assert.strictEqual(anySerializer.serialize(0.1)[0], DataType.DOUBLE);
+ });
+
+ it('NaN → DOUBLE (0x07)', () => {
+ const result = anySerializer.serialize(NaN);
+ assert.strictEqual(result[0], DataType.DOUBLE);
+ });
+
+ it('±Infinity → DOUBLE (0x07)', () => {
+ assert.strictEqual(anySerializer.serialize(Infinity)[0], DataType.DOUBLE);
+ assert.strictEqual(anySerializer.serialize(-Infinity)[0], DataType.DOUBLE);
+ });
+
+ it('-0 → DOUBLE (0x07) preserving sign', () => {
+ const result = anySerializer.serialize(-0);
+ assert.strictEqual(result[0], DataType.DOUBLE);
+ const deserialized = anySerializer.deserialize(result);
+ assert.isTrue(Object.is(deserialized.v, -0));
+ });
+
+ it('BigInt within Int64 range → BIGINTEGER (0x23)', () => {
+ assert.strictEqual(anySerializer.serialize(123n)[0], DataType.BIGINTEGER);
+ assert.strictEqual(anySerializer.serialize(-456n)[0], DataType.BIGINTEGER);
+ });
+
+ it('BigInt at Int64 boundaries → BIGINTEGER (0x23)', () => {
+ assert.strictEqual(anySerializer.serialize(2n**63n - 1n)[0], DataType.BIGINTEGER);
+ assert.strictEqual(anySerializer.serialize(-(2n**63n))[0], DataType.BIGINTEGER);
+ });
+
+ it('BigInt beyond Int64 → BIGINTEGER (0x23)', () => {
+ assert.strictEqual(anySerializer.serialize(2n**63n)[0], DataType.BIGINTEGER);
+ assert.strictEqual(anySerializer.serialize(-(2n**63n) - 1n)[0], DataType.BIGINTEGER);
+ });
+ });
+
+ describe('Type dispatch', () => {
+ it('boolean → BOOLEAN (0x27)', () => {
+ assert.strictEqual(anySerializer.serialize(true)[0], DataType.BOOLEAN);
+ assert.strictEqual(anySerializer.serialize(false)[0], DataType.BOOLEAN);
+ });
+
+ it('string → STRING (0x03)', () => {
+ const result = anySerializer.serialize('hello');
+ assert.strictEqual(result[0], DataType.STRING);
+ });
+
+ it('Date → DATETIME (0x04)', () => {
+ const result = anySerializer.serialize(new Date());
+ assert.strictEqual(result[0], DataType.DATETIME);
+ });
+
+ it('Array → LIST (0x09)', () => {
+ const result = anySerializer.serialize([1, 2, 3]);
+ assert.strictEqual(result[0], DataType.LIST);
+ });
+
+ it('Set → SET (0x0b)', () => {
+ const result = anySerializer.serialize(new Set([1, 2, 3]));
+ assert.strictEqual(result[0], DataType.SET);
+ });
+
+ it('Map → MAP (0x0a)', () => {
+ const result = anySerializer.serialize(new Map([['a', 1]]));
+ assert.strictEqual(result[0], DataType.MAP);
+ });
+
+ it('Plain object → MAP (0x0a)', () => {
+ const result = anySerializer.serialize({});
+ assert.strictEqual(result[0], DataType.MAP);
+ });
+
+ it('Buffer → BINARY (0x25)', () => {
+ const result = anySerializer.serialize(Buffer.from('test'));
+ assert.strictEqual(result[0], DataType.BINARY);
+ });
+
+ it('null → UNSPECIFIED_NULL (0xfe)', () => {
+ const result = anySerializer.serialize(null);
+ assert.strictEqual(result[0], DataType.UNSPECIFIED_NULL);
+ });
+
+ it('undefined → UNSPECIFIED_NULL (0xfe)', () => {
+ const result = anySerializer.serialize(undefined);
+ assert.strictEqual(result[0], DataType.UNSPECIFIED_NULL);
+ });
+
+ it('Vertex → VERTEX (0x11)', () => {
+ const vertex = new Vertex(1, 'person');
+ const result = anySerializer.serialize(vertex);
+ assert.strictEqual(result[0], DataType.VERTEX);
+ });
+
+ it('Edge → EDGE (0x0d)', () => {
+ const edge = new Edge(1, new Vertex(1, 'person'), 'knows', new Vertex(2, 'person'));
+ const result = anySerializer.serialize(edge);
+ assert.strictEqual(result[0], DataType.EDGE);
+ });
+
+ it('Property → PROPERTY (0x0f)', () => {
+ const property = new Property('name', 'marko');
+ const result = anySerializer.serialize(property);
+ assert.strictEqual(result[0], DataType.PROPERTY);
+ });
+
+ it('VertexProperty → VERTEXPROPERTY (0x12)', () => {
+ const vp = new VertexProperty(1, 'name', 'marko');
+ const result = anySerializer.serialize(vp);
+ assert.strictEqual(result[0], DataType.VERTEXPROPERTY);
+ });
+
+ it('Path → PATH (0x0e)', () => {
+ const path = new Path([new Set()], [1]);
+ const result = anySerializer.serialize(path);
+ assert.strictEqual(result[0], DataType.PATH);
+ });
+
+ it('direction.out → DIRECTION (0x18)', () => {
+ const result = anySerializer.serialize(direction.out);
+ assert.strictEqual(result[0], DataType.DIRECTION);
+ });
+
+ it('t.id → T (0x20)', () => {
+ const result = anySerializer.serialize(t.id);
+ assert.strictEqual(result[0], DataType.T);
+ });
+
+ it('merge.onCreate → MERGE (0x2e)', () => {
+ const result = anySerializer.serialize(merge.onCreate);
+ assert.strictEqual(result[0], DataType.MERGE);
+ });
+ });
+
+ describe('canBeUsedFor negative cases', () => {
+ it('intSerializer rejects non-numbers', () => {
+ assert.isFalse(ioc.intSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.intSerializer.canBeUsedFor(true));
+ assert.isFalse(ioc.intSerializer.canBeUsedFor([]));
+ });
+
+ it('stringSerializer rejects non-strings', () => {
+ assert.isFalse(ioc.stringSerializer.canBeUsedFor(42));
+ assert.isFalse(ioc.stringSerializer.canBeUsedFor(true));
+ assert.isFalse(ioc.stringSerializer.canBeUsedFor([]));
+ });
+
+ it('booleanSerializer rejects non-booleans', () => {
+ assert.isFalse(ioc.booleanSerializer.canBeUsedFor(42));
+ assert.isFalse(ioc.booleanSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.booleanSerializer.canBeUsedFor([]));
+ });
+
+ it('vertexSerializer rejects non-vertices', () => {
+ assert.isFalse(ioc.vertexSerializer.canBeUsedFor(new Edge(1, new Vertex(1, 'p'), 'knows', new Vertex(2, 'p'))));
+ assert.isFalse(ioc.vertexSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.vertexSerializer.canBeUsedFor(42));
+ });
+
+ it('edgeSerializer rejects non-edges', () => {
+ assert.isFalse(ioc.edgeSerializer.canBeUsedFor(new Vertex(1, 'person')));
+ assert.isFalse(ioc.edgeSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.edgeSerializer.canBeUsedFor(42));
+ });
+
+ it('setSerializer rejects non-sets', () => {
+ assert.isFalse(ioc.setSerializer.canBeUsedFor([]));
+ assert.isFalse(ioc.setSerializer.canBeUsedFor({}));
+ assert.isFalse(ioc.setSerializer.canBeUsedFor('string'));
+ });
+
+ it('listSerializer rejects non-arrays', () => {
+ assert.isFalse(ioc.listSerializer.canBeUsedFor(new Set()));
+ assert.isFalse(ioc.listSerializer.canBeUsedFor({}));
+ assert.isFalse(ioc.listSerializer.canBeUsedFor('string'));
+ });
+
+ it('dateTimeSerializer rejects non-dates', () => {
+ assert.isFalse(ioc.dateTimeSerializer.canBeUsedFor(42));
+ assert.isFalse(ioc.dateTimeSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.dateTimeSerializer.canBeUsedFor([]));
+ });
+
+ it('mapSerializer rejects non-maps/non-objects', () => {
+ assert.isFalse(ioc.mapSerializer.canBeUsedFor(42));
+ assert.isFalse(ioc.mapSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.mapSerializer.canBeUsedFor([]));
+ });
+
+ it('binarySerializer rejects non-buffers', () => {
+ assert.isFalse(ioc.binarySerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.binarySerializer.canBeUsedFor(42));
+ assert.isFalse(ioc.binarySerializer.canBeUsedFor([]));
+ });
+
+ it('pathSerializer rejects non-paths', () => {
+ assert.isFalse(ioc.pathSerializer.canBeUsedFor(new Vertex(1, 'person')));
+ assert.isFalse(ioc.pathSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.pathSerializer.canBeUsedFor(42));
+ });
+
+ it('propertySerializer rejects non-properties', () => {
+ assert.isFalse(ioc.propertySerializer.canBeUsedFor(new Vertex(1, 'person')));
+ assert.isFalse(ioc.propertySerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.propertySerializer.canBeUsedFor(42));
+ });
+
+ it('vertexPropertySerializer rejects non-vertex-properties', () => {
+ assert.isFalse(ioc.vertexPropertySerializer.canBeUsedFor(new Vertex(1, 'person')));
+ assert.isFalse(ioc.vertexPropertySerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.vertexPropertySerializer.canBeUsedFor(42));
+ });
+
+ it('enumSerializer rejects non-enums', () => {
+ assert.isFalse(ioc.enumSerializer.canBeUsedFor('string'));
+ assert.isFalse(ioc.enumSerializer.canBeUsedFor(42));
+ assert.isFalse(ioc.enumSerializer.canBeUsedFor(new Vertex(1, 'person')));
+ });
+ });
+
+ describe('Round-trip extras', () => {
+ it('nested collections', () => {
+ const value = [1, [2, 3], new Map([['a', [4]]])];
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.deepStrictEqual(deserialized.v, value);
+ });
+
+ it('empty containers', () => {
+ const values = [[], new Set(), new Map(), ''];
+ values.forEach(value => {
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.deepStrictEqual(deserialized.v, value);
+ });
+ });
+
+ it('JS-specific label construction survives round-trip', () => {
+ const vertex = new Vertex(123, 'person');
+ const serialized = anySerializer.serialize(vertex);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v.label, 'person');
+ });
+
+ it('Unicode strings', () => {
+ const value = '🚀 Hello 世界';
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v, value);
+ });
+
+ it('boundary integers', () => {
+ const values = [0, -1, 1];
+ values.forEach(value => {
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v, value);
+ });
+ });
+
+ it('NaN round-trip', () => {
+ const serialized = anySerializer.serialize(NaN);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.isTrue(Number.isNaN(deserialized.v));
+ });
+
+ it('complex nested structure', () => {
+ const value = new Map([
+ ['numbers', [1, 2.5, BigInt(123)]],
+ ['sets', new Set(['a', 'b'])],
+ ['map', new Map([[1, 'one'], [2, 'two']])],
+ ['nested', new Map([['inner', [true, false, null]]])]
+ ]);
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.deepStrictEqual(deserialized.v, value);
+ });
+
+ it('mixed type array', () => {
+ const value = [1, 'string', true, null, new Date(0), Buffer.from('test')];
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v.length, value.length);
+ assert.strictEqual(deserialized.v[0], 1);
+ assert.strictEqual(deserialized.v[1], 'string');
+ assert.strictEqual(deserialized.v[2], true);
+ assert.strictEqual(deserialized.v[3], null);
+ assert.deepStrictEqual(deserialized.v[4], new Date(0));
+ assert.isTrue(Buffer.isBuffer(deserialized.v[5]));
+ assert.isTrue(deserialized.v[5].equals(Buffer.from('test')));
+ });
+
+ it('graph elements with properties', () => {
+ const vertex = new Vertex(1, ['person'], [new VertexProperty(1, ['name'], 'marko')]);
+ const serialized = anySerializer.serialize(vertex);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v.id, 1);
+ assert.strictEqual(deserialized.v.label, 'person');
+ });
+
+ it('path with multiple labels', () => {
+ const path = new Path([new Set(['a']), new Set(['b', 'c'])], [1, 2]);
+ const serialized = anySerializer.serialize(path);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.deepStrictEqual(deserialized.v.labels, path.labels);
+ assert.deepStrictEqual(deserialized.v.objects, path.objects);
+ });
+
+ it('large numbers', () => {
+ const values = [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, 2n**100n];
+ values.forEach(value => {
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v, value);
+ });
+ });
+
+ it('special float values', () => {
+ const values = [Infinity, -Infinity];
+ values.forEach(value => {
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v, value);
+ });
+ });
+
+ it('enum values', () => {
+ const values = [direction.out, direction.in, direction.both, t.id, t.key, t.label, t.value, merge.onCreate, merge.onMatch, merge.outV, merge.inV];
+ values.forEach(value => {
+ const serialized = anySerializer.serialize(value);
+ const deserialized = anySerializer.deserialize(serialized);
+ assert.strictEqual(deserialized.v, value);
+ });
+ });
+ });
+});
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/utils.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/utils.js
deleted file mode 100644
index 50fc82bb50..0000000000
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/graphbinary/utils.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @author Igor Ostapenko
- */
-
-import { inspect } from 'util';
-
-export const ser_title = ({ i, v }) =>
- `should be able to handle case #${i}: ${inspect(v, { depth: 1, breakLength: Infinity })}`;
-
-export const des_title = ({ i, b }) => `should be able to handle case #${i}: ${b ? Buffer.from(b).toString('hex') : b}`;
-
-export const cbuf_title = ({ i, v }) =>
- `should be able to handle case #${i}: ${inspect(v, { depth: 1, breakLength: Infinity })}`;