2024-03-21 11:18:04 +00:00
|
|
|
|
using Logging;
|
|
|
|
|
using Moq;
|
|
|
|
|
using NethereumWorkflow;
|
2024-03-21 15:26:48 +00:00
|
|
|
|
using NethereumWorkflow.BlockUtils;
|
2024-03-21 11:18:04 +00:00
|
|
|
|
using NUnit.Framework;
|
|
|
|
|
|
|
|
|
|
namespace FrameworkTests.NethereumWorkflow
|
|
|
|
|
{
|
|
|
|
|
[TestFixture]
|
|
|
|
|
public class BlockTimeFinderTests
|
|
|
|
|
{
|
2024-03-21 15:11:28 +00:00
|
|
|
|
private readonly Mock<ILog> log = new Mock<ILog>();
|
2024-03-21 11:18:04 +00:00
|
|
|
|
private Mock<IWeb3Blocks> web3 = new Mock<IWeb3Blocks>();
|
2024-03-21 15:11:28 +00:00
|
|
|
|
private Dictionary<ulong, Block> blocks = new Dictionary<ulong, Block>();
|
2024-03-21 11:18:04 +00:00
|
|
|
|
|
|
|
|
|
private BlockTimeFinder finder = null!;
|
|
|
|
|
|
2024-03-21 15:11:28 +00:00
|
|
|
|
private void SetupBlockchain()
|
2024-03-21 11:18:04 +00:00
|
|
|
|
{
|
2024-03-21 15:11:28 +00:00
|
|
|
|
var start = DateTime.UtcNow.AddDays(-1).AddSeconds(-30);
|
|
|
|
|
blocks = new Dictionary<ulong, Block>();
|
2024-10-18 08:00:20 +00:00
|
|
|
|
|
|
|
|
|
Block? prev = null;
|
2024-03-21 15:11:28 +00:00
|
|
|
|
for (ulong i = 0; i < 30; i++)
|
2024-03-21 11:18:04 +00:00
|
|
|
|
{
|
2024-03-21 15:11:28 +00:00
|
|
|
|
ulong d = 100 + i;
|
2024-10-18 08:00:20 +00:00
|
|
|
|
var newBlock = new Block(d, start + TimeSpan.FromSeconds(i * 2));
|
|
|
|
|
blocks.Add(d, newBlock);
|
|
|
|
|
|
|
|
|
|
if (prev != null)
|
|
|
|
|
{
|
|
|
|
|
prev.Next = newBlock;
|
|
|
|
|
newBlock.Previous = prev;
|
|
|
|
|
}
|
|
|
|
|
prev = newBlock;
|
2024-03-21 11:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[SetUp]
|
|
|
|
|
public void SetUp()
|
|
|
|
|
{
|
2024-03-21 15:11:28 +00:00
|
|
|
|
SetupBlockchain();
|
2024-03-21 11:18:04 +00:00
|
|
|
|
|
|
|
|
|
web3 = new Mock<IWeb3Blocks>();
|
|
|
|
|
web3.Setup(w => w.GetCurrentBlockNumber()).Returns(blocks.Keys.Max());
|
2024-03-21 15:11:28 +00:00
|
|
|
|
web3.Setup(w => w.GetTimestampForBlock(It.IsAny<ulong>())).Returns<ulong>(d =>
|
2024-03-21 11:18:04 +00:00
|
|
|
|
{
|
|
|
|
|
if (blocks.ContainsKey(d)) return blocks[d].Time;
|
|
|
|
|
return null;
|
|
|
|
|
});
|
|
|
|
|
|
2024-03-21 15:26:48 +00:00
|
|
|
|
finder = new BlockTimeFinder(new BlockCache(), web3.Object, log.Object);
|
2024-03-21 11:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FindsMiddleOfChain()
|
|
|
|
|
{
|
|
|
|
|
var b1 = blocks[115];
|
|
|
|
|
var b2 = blocks[116];
|
|
|
|
|
|
|
|
|
|
var momentBetween = b1.JustAfter;
|
|
|
|
|
|
|
|
|
|
var b1Number = finder.GetHighestBlockNumberBefore(momentBetween);
|
|
|
|
|
var b2Number = finder.GetLowestBlockNumberAfter(momentBetween);
|
|
|
|
|
|
|
|
|
|
Assert.That(b1Number, Is.EqualTo(b1.Number));
|
|
|
|
|
Assert.That(b2Number, Is.EqualTo(b2.Number));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FindsFrontOfChain_Lowest()
|
|
|
|
|
{
|
|
|
|
|
var first = blocks.First().Value;
|
|
|
|
|
|
|
|
|
|
var firstNumber = finder.GetLowestBlockNumberAfter(first.JustBefore);
|
|
|
|
|
|
|
|
|
|
Assert.That(firstNumber, Is.EqualTo(first.Number));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FindsFrontOfChain_Highest()
|
|
|
|
|
{
|
|
|
|
|
var first = blocks.First().Value;
|
|
|
|
|
|
|
|
|
|
var firstNumber = finder.GetHighestBlockNumberBefore(first.JustAfter);
|
|
|
|
|
|
|
|
|
|
Assert.That(firstNumber, Is.EqualTo(first.Number));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FindsTailOfChain_Lowest()
|
|
|
|
|
{
|
|
|
|
|
var last = blocks.Last().Value;
|
|
|
|
|
|
|
|
|
|
var lastNumber = finder.GetLowestBlockNumberAfter(last.JustBefore);
|
|
|
|
|
|
|
|
|
|
Assert.That(lastNumber, Is.EqualTo(last.Number));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FindsTailOfChain_Highest()
|
|
|
|
|
{
|
|
|
|
|
var last = blocks.Last().Value;
|
|
|
|
|
|
|
|
|
|
var lastNumber = finder.GetHighestBlockNumberBefore(last.JustAfter);
|
|
|
|
|
|
|
|
|
|
Assert.That(lastNumber, Is.EqualTo(last.Number));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
2024-10-18 08:00:20 +00:00
|
|
|
|
public void FindsGenesisBlockAtFrontOfChain()
|
2024-03-21 11:18:04 +00:00
|
|
|
|
{
|
|
|
|
|
var first = blocks.First().Value;
|
|
|
|
|
|
2024-10-18 08:00:20 +00:00
|
|
|
|
var firstNumber = finder.GetHighestBlockNumberBefore(first.Time);
|
2024-03-21 11:18:04 +00:00
|
|
|
|
|
2024-10-18 08:00:20 +00:00
|
|
|
|
Assert.That(firstNumber, Is.EqualTo(first.Number));
|
2024-03-21 11:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
2024-10-18 08:00:20 +00:00
|
|
|
|
public void FindsCurrentBlockAtTailOfChain()
|
2024-03-21 11:18:04 +00:00
|
|
|
|
{
|
|
|
|
|
var last = blocks.Last().Value;
|
|
|
|
|
|
2024-10-18 08:00:20 +00:00
|
|
|
|
var lastNumber = finder.GetLowestBlockNumberAfter(last.Time);
|
2024-03-21 11:18:04 +00:00
|
|
|
|
|
2024-10-18 08:00:20 +00:00
|
|
|
|
Assert.That(lastNumber, Is.EqualTo(last.Number));
|
2024-03-21 11:18:04 +00:00
|
|
|
|
}
|
2024-04-01 11:21:21 +00:00
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FailsToFindBlockBeforeFrontOfChain_history()
|
|
|
|
|
{
|
|
|
|
|
var first = blocks.First().Value;
|
|
|
|
|
|
|
|
|
|
var notFound = finder.GetHighestBlockNumberBefore(first.JustBefore);
|
|
|
|
|
|
|
|
|
|
Assert.That(notFound, Is.Null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void FailsToFindBlockAfterTailOfChain_future()
|
|
|
|
|
{
|
|
|
|
|
var last = blocks.Last().Value;
|
|
|
|
|
|
|
|
|
|
var notFound = finder.GetLowestBlockNumberAfter(last.JustAfter);
|
|
|
|
|
|
|
|
|
|
Assert.That(notFound, Is.Null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void RunThrough()
|
|
|
|
|
{
|
|
|
|
|
foreach (var pair in blocks)
|
|
|
|
|
{
|
2024-10-18 08:00:20 +00:00
|
|
|
|
var block = pair.Value;
|
|
|
|
|
|
|
|
|
|
AssertLink(block.Previous, finder.GetHighestBlockNumberBefore(block.JustBefore));
|
|
|
|
|
AssertLink(block, finder.GetHighestBlockNumberBefore(block.Time));
|
|
|
|
|
AssertLink(block, finder.GetHighestBlockNumberBefore(block.JustAfter));
|
|
|
|
|
|
|
|
|
|
AssertLink(block, finder.GetLowestBlockNumberAfter(block.JustBefore));
|
|
|
|
|
AssertLink(block, finder.GetLowestBlockNumberAfter(block.Time));
|
|
|
|
|
AssertLink(block.Next, finder.GetLowestBlockNumberAfter(block.JustAfter));
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-01 11:21:21 +00:00
|
|
|
|
|
2024-10-18 08:00:20 +00:00
|
|
|
|
private void AssertLink(Block? expected, ulong? actual)
|
|
|
|
|
{
|
|
|
|
|
if (expected == null)
|
|
|
|
|
{
|
|
|
|
|
Assert.That(actual, Is.Null);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Assert.That(expected.Number, Is.EqualTo(actual!.Value));
|
2024-04-01 11:21:21 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-03-21 11:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class Block
|
|
|
|
|
{
|
2024-03-21 15:11:28 +00:00
|
|
|
|
public Block(ulong number, DateTime time)
|
2024-03-21 11:18:04 +00:00
|
|
|
|
{
|
|
|
|
|
Number = number;
|
|
|
|
|
Time = time;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-21 15:11:28 +00:00
|
|
|
|
public ulong Number { get; }
|
2024-03-21 11:18:04 +00:00
|
|
|
|
public DateTime Time { get; }
|
|
|
|
|
public DateTime JustBefore { get { return Time.AddSeconds(-1); } }
|
|
|
|
|
public DateTime JustAfter { get { return Time.AddSeconds(1); } }
|
2024-04-01 11:42:07 +00:00
|
|
|
|
|
2024-10-18 08:00:20 +00:00
|
|
|
|
public Block? Next { get; set; }
|
|
|
|
|
public Block? Previous { get; set; }
|
|
|
|
|
|
2024-04-01 11:42:07 +00:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return $"[{Number}]";
|
|
|
|
|
}
|
2024-03-21 11:18:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|