blob: 3cd7c07f892997602f536d50660a52a126f72506 [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.Buffers.Binary;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Gremlin.Net.Structure;
using Gremlin.Net.Structure.IO.GraphBinary4;
using Xunit;
namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4
{
public class TreeSerializerTests
{
[Fact]
public async Task ShouldRoundTripNestedTree()
{
// marko -> {lop, josh -> {ripple, lop}}
var tree = new Tree();
var marko = tree.GetOrCreateChild("marko");
marko.GetOrCreateChild("lop");
var josh = marko.GetOrCreateChild("josh");
josh.GetOrCreateChild("ripple");
josh.GetOrCreateChild("lop");
var deserialized = await RoundTrip(tree);
Assert.Equal(tree, deserialized);
Assert.True(deserialized.HasChild("marko"));
var rMarko = deserialized.ChildAt("marko");
Assert.True(rMarko.HasChild("lop"));
Assert.True(rMarko.HasChild("josh"));
var rJosh = rMarko.ChildAt("josh");
Assert.True(rJosh.HasChild("ripple"));
Assert.True(rJosh.HasChild("lop"));
Assert.True(rJosh.ChildAt("ripple").IsLeaf());
}
[Fact]
public async Task ShouldRoundTripEmptyTree()
{
var tree = new Tree();
var deserialized = await RoundTrip(tree);
Assert.True(deserialized.IsLeaf());
Assert.Equal(tree, deserialized);
}
[Fact]
public async Task ShouldRoundTripTreeWithNullKey()
{
var tree = new Tree();
tree.GetOrCreateChild(null).GetOrCreateChild("child");
var deserialized = await RoundTrip(tree);
Assert.True(deserialized.HasChild(null));
Assert.True(deserialized.ChildAt(null).HasChild("child"));
Assert.Equal(tree, deserialized);
}
[Fact]
public void PrettyPrintShouldMatchCanonicalStyle()
{
var tree = new Tree();
var marko = tree.GetOrCreateChild("marko");
marko.GetOrCreateChild("lop");
var josh = marko.GetOrCreateChild("josh");
josh.GetOrCreateChild("ripple");
var expected = "|--marko\n |--lop\n |--josh\n |--ripple";
Assert.Equal(expected, tree.PrettyPrint());
}
[Fact]
public async Task ShouldMergeDuplicateSiblingKeys()
{
using var stream = new MemoryStream();
// Tree type-code + non-null value flag.
stream.WriteByte(DataType.Tree.TypeCode);
stream.WriteByte(0x00);
// Root tree with the same key written twice; each child is a leaf.
WriteInt32(stream, 2);
WriteFullyQualifiedString(stream, "dup");
WriteInt32(stream, 0); // bare leaf child
WriteFullyQualifiedString(stream, "dup");
WriteInt32(stream, 0); // bare leaf child
stream.Position = 0;
var reader = new GraphBinaryReader();
var result = await reader.ReadAsync(stream);
var tree = Assert.IsType<Tree>(result);
// The duplicate sibling keys collapse into a single merged entry.
Assert.Single(tree.RootNodes());
Assert.True(tree.HasChild("dup"));
}
private static void WriteFullyQualifiedString(Stream stream, string value)
{
stream.WriteByte(DataType.String.TypeCode);
stream.WriteByte(0x00); // value flag: not null
var bytes = Encoding.UTF8.GetBytes(value);
WriteInt32(stream, bytes.Length);
stream.Write(bytes, 0, bytes.Length);
}
private static void WriteInt32(Stream stream, int value)
{
var bytes = new byte[4];
BinaryPrimitives.WriteInt32BigEndian(bytes, value);
stream.Write(bytes, 0, 4);
}
private static async Task<Tree> RoundTrip(Tree tree)
{
var writer = new GraphBinaryWriter();
var reader = new GraphBinaryReader();
using var stream = new MemoryStream();
await writer.WriteAsync(tree, stream);
stream.Position = 0;
var result = await reader.ReadAsync(stream);
Assert.NotNull(result);
return Assert.IsType<Tree>(result);
}
}
}