97 lines
3.8 KiB
C#
97 lines
3.8 KiB
C#
// <copyright file="HlcMergeServiceTests.MergeOrdering.cs" company="StellaOps">
|
|
// Copyright (c) StellaOps. Licensed under BUSL-1.1.
|
|
// </copyright>
|
|
using FluentAssertions;
|
|
using StellaOps.AirGap.Sync.Models;
|
|
using Xunit;
|
|
|
|
namespace StellaOps.AirGap.Sync.Tests;
|
|
|
|
public sealed partial class HlcMergeServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task MergeAsync_TwoNodes_MergesByHlcOrderAsync()
|
|
{
|
|
var nodeA = CreateNodeLog("node-a", new[]
|
|
{
|
|
CreateEntry("node-a", 100, 0, Guid.Parse("aaaaaaaa-0001-0000-0000-000000000000")),
|
|
CreateEntry("node-a", 102, 0, Guid.Parse("aaaaaaaa-0003-0000-0000-000000000000"))
|
|
});
|
|
var nodeB = CreateNodeLog("node-b", new[]
|
|
{
|
|
CreateEntry("node-b", 101, 0, Guid.Parse("bbbbbbbb-0002-0000-0000-000000000000")),
|
|
CreateEntry("node-b", 103, 0, Guid.Parse("bbbbbbbb-0004-0000-0000-000000000000"))
|
|
});
|
|
|
|
var result = await _sut.MergeAsync(new[] { nodeA, nodeB });
|
|
|
|
result.MergedEntries.Should().HaveCount(4);
|
|
result.MergedEntries[0].THlc.PhysicalTime.Should().Be(100);
|
|
result.MergedEntries[1].THlc.PhysicalTime.Should().Be(101);
|
|
result.MergedEntries[2].THlc.PhysicalTime.Should().Be(102);
|
|
result.MergedEntries[3].THlc.PhysicalTime.Should().Be(103);
|
|
result.SourceNodes.Should().HaveCount(2);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task MergeAsync_SamePhysicalTime_OrdersByLogicalCounterAsync()
|
|
{
|
|
var nodeA = CreateNodeLog("node-a", new[]
|
|
{
|
|
CreateEntry("node-a", 100, 0, Guid.Parse("aaaaaaaa-0000-0000-0000-000000000001")),
|
|
CreateEntry("node-a", 100, 2, Guid.Parse("aaaaaaaa-0000-0000-0000-000000000003"))
|
|
});
|
|
var nodeB = CreateNodeLog("node-b", new[]
|
|
{
|
|
CreateEntry("node-b", 100, 1, Guid.Parse("bbbbbbbb-0000-0000-0000-000000000002")),
|
|
CreateEntry("node-b", 100, 3, Guid.Parse("bbbbbbbb-0000-0000-0000-000000000004"))
|
|
});
|
|
|
|
var result = await _sut.MergeAsync(new[] { nodeA, nodeB });
|
|
|
|
result.MergedEntries.Should().HaveCount(4);
|
|
result.MergedEntries[0].THlc.LogicalCounter.Should().Be(0);
|
|
result.MergedEntries[1].THlc.LogicalCounter.Should().Be(1);
|
|
result.MergedEntries[2].THlc.LogicalCounter.Should().Be(2);
|
|
result.MergedEntries[3].THlc.LogicalCounter.Should().Be(3);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task MergeAsync_SameTimeAndCounter_OrdersByNodeIdAsync()
|
|
{
|
|
var nodeA = CreateNodeLog("alpha-node", new[]
|
|
{
|
|
CreateEntry("alpha-node", 100, 0, Guid.Parse("aaaaaaaa-0000-0000-0000-000000000001"))
|
|
});
|
|
var nodeB = CreateNodeLog("beta-node", new[]
|
|
{
|
|
CreateEntry("beta-node", 100, 0, Guid.Parse("bbbbbbbb-0000-0000-0000-000000000002"))
|
|
});
|
|
|
|
var result = await _sut.MergeAsync(new[] { nodeA, nodeB });
|
|
|
|
result.MergedEntries.Should().HaveCount(2);
|
|
result.MergedEntries[0].SourceNodeId.Should().Be("alpha-node");
|
|
result.MergedEntries[1].SourceNodeId.Should().Be("beta-node");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task MergeAsync_RecomputesUnifiedChainAsync()
|
|
{
|
|
var nodeLog = CreateNodeLog("node-a", new[]
|
|
{
|
|
CreateEntry("node-a", 100, 0, Guid.Parse("11111111-1111-1111-1111-111111111111")),
|
|
CreateEntry("node-a", 200, 0, Guid.Parse("22222222-2222-2222-2222-222222222222"))
|
|
});
|
|
|
|
var result = await _sut.MergeAsync(new[] { nodeLog });
|
|
|
|
result.MergedEntries.Should().HaveCount(2);
|
|
result.MergedEntries[0].MergedLink.Should().NotBeNull();
|
|
result.MergedEntries[1].MergedLink.Should().NotBeNull();
|
|
result.MergedChainHead.Should().NotBeNull();
|
|
result.MergedEntries[0].MergedLink.Should().HaveCount(32);
|
|
result.MergedChainHead.Should().BeEquivalentTo(result.MergedEntries[1].MergedLink);
|
|
}
|
|
}
|