blob: 8fc76c75606e5d86d380bc77cad4e7646c6211fe [file]
#region License
/*
* 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.
*/
#endregion
using System.IO;
using System.Threading.Tasks;
using Gremlin.Net.Driver.Exceptions;
using Gremlin.Net.Process.Traversal;
using Gremlin.Net.Structure.IO.GraphBinary4;
using Xunit;
namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4
{
public class ResponseMessageSerializerTests
{
[Fact]
public async Task ShouldDeserializeNonBulkedResponse()
{
// Build a response: version(0x84) + bulked(0x00) + int value 42 + marker + status footer
using var stream = new MemoryStream();
var writer = new GraphBinaryWriter();
// Version byte
await stream.WriteByteAsync(0x84);
// Bulked = false
await stream.WriteByteAsync(0x00);
// Fully-qualified int value: type_code(0x01) + value_flag(0x00) + int32(42)
await stream.WriteByteAsync(0x01); // DataType.Int
await stream.WriteByteAsync(0x00); // value_flag = not null
await stream.WriteIntAsync(42);
// Marker: type_code(0xFD) + value_flag(0x00) + value(0x00)
await stream.WriteByteAsync(0xFD);
await stream.WriteByteAsync(0x00); // value_flag
await stream.WriteByteAsync(0x00); // marker value
// Status footer: status code 200
await stream.WriteIntAsync(200);
// Nullable status message: null (value_flag = 1)
await stream.WriteByteAsync(0x01);
// Nullable exception: null (value_flag = 1)
await stream.WriteByteAsync(0x01);
stream.Position = 0;
var reader = new GraphBinaryReader();
var serializer = new ResponseMessageSerializer();
var result = await serializer.ReadValueAsync(stream, reader);
Assert.False(result.Bulked);
Assert.Single(result.Result);
Assert.Equal(42, result.Result[0]);
Assert.Equal(200, result.StatusCode);
Assert.Null(result.StatusMessage);
Assert.Null(result.Exception);
}
[Fact]
public async Task ShouldDeserializeBulkedResponseWithTraverserWrapping()
{
using var stream = new MemoryStream();
// Version byte
await stream.WriteByteAsync(0x84);
// Bulked = true
await stream.WriteByteAsync(0x01);
// Fully-qualified string value: type_code(0x03) + value_flag(0x00) + string "hello"
await stream.WriteByteAsync(0x03); // DataType.String
await stream.WriteByteAsync(0x00); // value_flag
var helloBytes = System.Text.Encoding.UTF8.GetBytes("hello");
await stream.WriteIntAsync(helloBytes.Length);
await stream.WriteAsync(helloBytes);
// Bulk count as fully-qualified Long: type_code(0x02) + value_flag(0x00) + long(3)
await stream.WriteByteAsync(0x02); // DataType.Long
await stream.WriteByteAsync(0x00); // value_flag = not null
await stream.WriteLongAsync(3);
// Marker: type_code(0xFD) + value_flag(0x00) + value(0x00)
await stream.WriteByteAsync(0xFD);
await stream.WriteByteAsync(0x00); // value_flag
await stream.WriteByteAsync(0x00); // marker value
// Status footer
await stream.WriteIntAsync(200);
await stream.WriteByteAsync(0x01); // null message
await stream.WriteByteAsync(0x01); // null exception
stream.Position = 0;
var reader = new GraphBinaryReader();
var serializer = new ResponseMessageSerializer();
var result = await serializer.ReadValueAsync(stream, reader);
Assert.True(result.Bulked);
Assert.Single(result.Result);
var traverser = Assert.IsType<Traverser>(result.Result[0]);
Assert.Equal("hello", (string)traverser.Object);
Assert.Equal(3L, traverser.Bulk);
}
[Fact]
public async Task ShouldThrowResponseExceptionOnErrorStatus()
{
using var stream = new MemoryStream();
// Version byte
await stream.WriteByteAsync(0x84);
// Bulked = false
await stream.WriteByteAsync(0x00);
// No result data — go straight to marker: type_code(0xFD) + value_flag(0x00) + value(0x00)
await stream.WriteByteAsync(0xFD);
await stream.WriteByteAsync(0x00); // value_flag
await stream.WriteByteAsync(0x00); // marker value
// Status footer: status code 500
await stream.WriteIntAsync(500);
// Status message: "Server error"
await stream.WriteByteAsync(0x00); // value_flag = not null
var msgBytes = System.Text.Encoding.UTF8.GetBytes("Server error");
await stream.WriteIntAsync(msgBytes.Length);
await stream.WriteAsync(msgBytes);
// Exception: "java.lang.RuntimeException"
await stream.WriteByteAsync(0x00); // value_flag = not null
var excBytes = System.Text.Encoding.UTF8.GetBytes("java.lang.RuntimeException");
await stream.WriteIntAsync(excBytes.Length);
await stream.WriteAsync(excBytes);
stream.Position = 0;
var reader = new GraphBinaryReader();
var serializer = new ResponseMessageSerializer();
var ex = await Assert.ThrowsAsync<ResponseException>(
() => serializer.ReadValueAsync(stream, reader));
Assert.Equal(500, ex.StatusCode);
Assert.Equal("Server error", ex.Message);
Assert.Equal("java.lang.RuntimeException", ex.ServerException);
}
[Fact]
public async Task ShouldThrowOnInvalidVersionByte()
{
using var stream = new MemoryStream();
// Invalid version byte (MSB not set)
await stream.WriteByteAsync(0x01);
stream.Position = 0;
var reader = new GraphBinaryReader();
var serializer = new ResponseMessageSerializer();
await Assert.ThrowsAsync<IOException>(
() => serializer.ReadValueAsync(stream, reader));
}
[Fact]
public async Task ShouldDeserializeMultipleNonBulkedResults()
{
using var stream = new MemoryStream();
// Version + non-bulked
await stream.WriteByteAsync(0x84);
await stream.WriteByteAsync(0x00);
// First result: int 1
await stream.WriteByteAsync(0x01);
await stream.WriteByteAsync(0x00);
await stream.WriteIntAsync(1);
// Second result: int 2
await stream.WriteByteAsync(0x01);
await stream.WriteByteAsync(0x00);
await stream.WriteIntAsync(2);
// Third result: int 3
await stream.WriteByteAsync(0x01);
await stream.WriteByteAsync(0x00);
await stream.WriteIntAsync(3);
// Marker: type_code(0xFD) + value_flag(0x00) + value(0x00)
await stream.WriteByteAsync(0xFD);
await stream.WriteByteAsync(0x00); // value_flag
await stream.WriteByteAsync(0x00); // marker value
// Status footer: 200, null, null
await stream.WriteIntAsync(200);
await stream.WriteByteAsync(0x01);
await stream.WriteByteAsync(0x01);
stream.Position = 0;
var reader = new GraphBinaryReader();
var serializer = new ResponseMessageSerializer();
var result = await serializer.ReadValueAsync(stream, reader);
Assert.Equal(3, result.Result.Count);
Assert.Equal(1, result.Result[0]);
Assert.Equal(2, result.Result[1]);
Assert.Equal(3, result.Result[2]);
}
}
}