251 lines
8.0 KiB
C#
251 lines
8.0 KiB
C#
|
|
using Robotico.Graph;
|
||
|
|
using Robotico.Nexus.Client.Tests.TestSupport;
|
||
|
|
using Robotico.Result.Errors;
|
||
|
|
using Xunit;
|
||
|
|
|
||
|
|
namespace Robotico.Nexus.Client.Tests.Graph;
|
||
|
|
|
||
|
|
public class NexusGraphSessionTests : IAsyncLifetime
|
||
|
|
{
|
||
|
|
private NexusTestHost _host = null!;
|
||
|
|
private NexusClient _client = null!;
|
||
|
|
private IGraphSession _session = null!;
|
||
|
|
|
||
|
|
public async Task InitializeAsync()
|
||
|
|
{
|
||
|
|
_host = await NexusTestHost.StartAsync();
|
||
|
|
Robotico.Result.Result<NexusClient> connected = NexusClient.Connect(_host.ConnectionUri(NexusUriSchemes.Graph));
|
||
|
|
Assert.True(connected.IsSuccess(out NexusClient? client, out _));
|
||
|
|
_client = client!;
|
||
|
|
Robotico.Result.Result<IGraphSession> opened = _client.Graph.Open("session-db");
|
||
|
|
Assert.True(opened.IsSuccess(out IGraphSession? session, out _));
|
||
|
|
_session = session!;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task DisposeAsync()
|
||
|
|
{
|
||
|
|
_session.Dispose();
|
||
|
|
_client.Dispose();
|
||
|
|
await _host.DisposeAsync();
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void RegisterLabel_Succeeds()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result result = _session.RegisterLabel("Person");
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess());
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void RegisterLabel_Fails_WhenBlank()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result result = _session.RegisterLabel(" ");
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void RegisterEdgeType_Succeeds()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result result = _session.RegisterEdgeType("WorksAt");
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess());
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void RegisterEdgeType_Fails_WhenBlank()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result result = _session.RegisterEdgeType(string.Empty);
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void UpsertVertex_ThenGetVertex_RoundTrips()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<ulong> upserted = _session.UpsertVertex(1, ["Person"]);
|
||
|
|
Assert.True(upserted.IsSuccess());
|
||
|
|
|
||
|
|
Robotico.Result.Result<GraphVertex> fetched = _session.GetVertex(1);
|
||
|
|
|
||
|
|
Assert.True(fetched.IsSuccess(out GraphVertex? vertex, out _));
|
||
|
|
Assert.Equal(1ul, vertex!.VertexId);
|
||
|
|
Assert.Contains("Person", vertex.Labels);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void UpsertVertex_Fails_WhenNoLabels()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<ulong> result = _session.UpsertVertex(1, []);
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void GetVertex_Fails_WhenNotFound()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<GraphVertex> result = _session.GetVertex(999);
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(NexusErrors.NotFound, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void DeleteVertex_Succeeds()
|
||
|
|
{
|
||
|
|
_session.UpsertVertex(2, ["Person"]);
|
||
|
|
|
||
|
|
Robotico.Result.Result<ulong> result = _session.DeleteVertex(2);
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess());
|
||
|
|
Assert.True(_session.GetVertex(2).IsError(out _));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void UpsertEdge_ThenGetEdge_RoundTrips()
|
||
|
|
{
|
||
|
|
_session.UpsertVertex(1, ["Person"]);
|
||
|
|
_session.UpsertVertex(2, ["Company"]);
|
||
|
|
|
||
|
|
Robotico.Result.Result<ulong> upserted = _session.UpsertEdge(1, 2, "WorksAt");
|
||
|
|
Assert.True(upserted.IsSuccess());
|
||
|
|
|
||
|
|
Robotico.Result.Result<GraphEdge> fetched = _session.GetEdge(1, 2, "WorksAt");
|
||
|
|
|
||
|
|
Assert.True(fetched.IsSuccess(out GraphEdge? edge, out _));
|
||
|
|
Assert.Equal(1ul, edge!.SourceVertexId);
|
||
|
|
Assert.Equal(2ul, edge.TargetVertexId);
|
||
|
|
Assert.Equal("WorksAt", edge.EdgeTypeName);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void UpsertEdge_Fails_WhenEdgeTypeBlank()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<ulong> result = _session.UpsertEdge(1, 2, string.Empty);
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void DeleteEdge_Succeeds()
|
||
|
|
{
|
||
|
|
_session.UpsertVertex(1, ["Person"]);
|
||
|
|
_session.UpsertVertex(2, ["Company"]);
|
||
|
|
_session.UpsertEdge(1, 2, "WorksAt");
|
||
|
|
|
||
|
|
Robotico.Result.Result<ulong> result = _session.DeleteEdge(1, 2, "WorksAt");
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess());
|
||
|
|
Assert.True(_session.GetEdge(1, 2, "WorksAt").IsError(out _));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void DeleteEdge_Fails_WhenEdgeTypeBlank()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<ulong> result = _session.DeleteEdge(1, 2, " ");
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void GetEdge_Fails_WhenEdgeTypeBlank()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<GraphEdge> result = _session.GetEdge(1, 2, string.Empty);
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void GetEdge_Fails_WhenNotFound()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<GraphEdge> result = _session.GetEdge(1, 2, "Missing");
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(NexusErrors.NotFound, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void GetNeighborhood_ReturnsStartVertex()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<GraphNeighborhood> result = _session.GetNeighborhood(1, maxDepth: 2, edgeTypeName: "WorksAt");
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess(out GraphNeighborhood? neighborhood, out _));
|
||
|
|
Assert.Equal(1ul, neighborhood!.StartVertexId);
|
||
|
|
Assert.Contains(1ul, neighborhood.VisitOrder);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void GetNeighborhood_Succeeds_WithoutOptionalArguments()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<GraphNeighborhood> result = _session.GetNeighborhood(1);
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess());
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void ListVerticesByLabel_ReturnsMatchingVertices()
|
||
|
|
{
|
||
|
|
_session.UpsertVertex(10, ["Person"]);
|
||
|
|
_session.UpsertVertex(11, ["Person"]);
|
||
|
|
_session.UpsertVertex(12, ["Company"]);
|
||
|
|
|
||
|
|
Robotico.Result.Result<GraphVertexPage> result = _session.ListVerticesByLabel("Person", skip: 0, limit: 25);
|
||
|
|
|
||
|
|
Assert.True(result.IsSuccess(out GraphVertexPage? page, out _));
|
||
|
|
Assert.Equal("Person", page!.LabelName);
|
||
|
|
Assert.Equal(2, page.TotalCount);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void ListVerticesByLabel_Fails_WhenLabelBlank()
|
||
|
|
{
|
||
|
|
Robotico.Result.Result<GraphVertexPage> result = _session.ListVerticesByLabel(string.Empty);
|
||
|
|
|
||
|
|
Assert.True(result.IsError(out IError? error));
|
||
|
|
Assert.Equal(GraphErrors.InvalidArgument, error!.Code);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public void AllOperations_Fail_AfterDispose()
|
||
|
|
{
|
||
|
|
_session.Dispose();
|
||
|
|
|
||
|
|
Assert.True(_session.RegisterLabel("x").IsError(out IError? e1));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e1!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.RegisterEdgeType("x").IsError(out IError? e2));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e2!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.UpsertVertex(1, ["A"]).IsError(out IError? e3));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e3!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.DeleteVertex(1).IsError(out IError? e4));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e4!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.GetVertex(1).IsError(out IError? e5));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e5!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.UpsertEdge(1, 2, "x").IsError(out IError? e6));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e6!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.DeleteEdge(1, 2, "x").IsError(out IError? e7));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e7!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.GetEdge(1, 2, "x").IsError(out IError? e8));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e8!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.GetNeighborhood(1).IsError(out IError? e9));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e9!.Code);
|
||
|
|
|
||
|
|
Assert.True(_session.ListVerticesByLabel("x").IsError(out IError? e10));
|
||
|
|
Assert.Equal(NexusErrors.Disposed, e10!.Code);
|
||
|
|
}
|
||
|
|
}
|