using XFESystem.Network; namespace XFESystem.Network.Tests; public sealed class DeadlineAndAcknowledgementTests { static void Deliver(PacketFixture peer, E1000HardwareFixture hardware) { byte[] frame = new byte[2048]; int length; while ((length = peer.Receive(frame)) > 0) hardware.Receive(frame[..length]); } static (Ipv4Network Stack, E1000Device Device, E1000HardwareFixture Hardware, PacketFixture Peer, TestPlatform Clock) Wired() { var clock = new TestPlatform(); var hardware = new E1000HardwareFixture(); var device = new E1000Device(hardware, clock, 40); var peer = new PacketFixture(); hardware.OnTransmit = frame => { peer.Send(frame, long.MaxValue); Deliver(peer, hardware); }; return (new Ipv4Network(device, clock, Ipv4Configuration.QemuUserNat), device, hardware, peer, clock); } [Fact] public void RealDriverHungArpTransmitCannotReplaceTheTcpOpenDeadline() { var state = Wired(); using var hardware = state.Hardware; using var device = state.Device; hardware.CompleteTx = false; Assert.Throws(() => state.Stack.OpenTcpUntil("1.2.3.4", 443, 40, 40)); Assert.Equal(40, state.Clock.Milliseconds); } [Fact] public void RealDriverHungReceiveAckCannotExceedReadTimeout() { var state = Wired(); using var hardware = state.Hardware; using var device = state.Device; Stream stream = state.Stack.OpenTcp("1.2.3.4", 443, 1000); stream.ReadTimeout = stream.WriteTimeout = 40; state.Peer.QueueData("actual received bytes"); Deliver(state.Peer, hardware); hardware.CompleteTx = false; Assert.Throws(() => stream.Read(new byte[100])); Assert.Equal(40, state.Clock.Milliseconds); long closing = state.Clock.Milliseconds; stream.Dispose(); Assert.InRange(state.Clock.Milliseconds - closing, 0, 40); } [Fact] public void RealDriverHungWriteAndCloseEachKeepTheirSingleConfiguredBudget() { var state = Wired(); using var hardware = state.Hardware; using var device = state.Device; Stream stream = state.Stack.OpenTcp("1.2.3.4", 443, 1000); stream.WriteTimeout = 35; stream.ReadTimeout = 40; hardware.CompleteTx = false; Assert.Throws(() => stream.Write("not completed"u8)); Assert.Equal(35, state.Clock.Milliseconds); stream.Dispose(); Assert.Equal(70, state.Clock.Milliseconds); stream.Dispose(); Assert.Equal(70, state.Clock.Milliseconds); } [Theory] [InlineData(true, false)] [InlineData(false, true)] public void ResetAndLinkInitializationUseTheAbsoluteOpenDeadline(bool resetStuck, bool linkDown) { using var hardware = new E1000HardwareFixture { ResetStuck = resetStuck, LinkUp = !linkDown }; var clock = new TestPlatform(); Assert.Throws(() => new E1000Device(hardware, clock, 25)); Assert.Equal(25, clock.Milliseconds); Assert.Equal(0, hardware.OutstandingDma); } [Fact] public void PciDiscoveryUsesTheDeadlineBeforeWalkingEveryBus() { using var hardware = new E1000HardwareFixture { Found = false }; var clock = new TestPlatform(); hardware.PciAccess = () => clock.Wait(1); Assert.Throws(() => new E1000Device(hardware, clock, 5)); Assert.Equal(5, clock.Milliseconds); Assert.Equal(0, hardware.OutstandingDma); } [Fact] public void DeviceInitializationTimeDoesNotRestartTheConnectionBudget() { var state = Wired(); using var hardware = state.Hardware; using var device = state.Device; state.Clock.Wait(30); hardware.CompleteTx = false; Assert.Throws(() => state.Stack.OpenTcpUntil("1.2.3.4", 443, 40, 40)); Assert.Equal(40, state.Clock.Milliseconds); } [Fact] public void OutOfWindowSameTupleAckCannotCompleteAnOutstandingWrite() { var peer = new PacketFixture { AcknowledgeData = false }; var clock = new TestPlatform(); var stack = new Ipv4Network(peer, clock, Ipv4Configuration.QemuUserNat); using Stream stream = stack.OpenTcp("1.2.3.4", 443); stream.WriteTimeout = 40; peer.DataReceived = () => peer.QueueAcknowledgementAt(peer.PeerNext + 70000, 65535); Assert.Throws(() => stream.Write("must wait for valid sequence"u8)); Assert.Equal(40, clock.Milliseconds); } [Fact] public void OutOfWindowZeroWindowAckCannotBlockTheNextWrite() { var peer = new PacketFixture(); var clock = new TestPlatform(); var stack = new Ipv4Network(peer, clock, Ipv4Configuration.QemuUserNat); using Stream stream = stack.OpenTcp("1.2.3.4", 443); stream.ReadTimeout = 5; stream.WriteTimeout = 40; peer.QueueAcknowledgementAt(peer.PeerNext + 70000, 0); Assert.Throws(() => stream.Read(new byte[1])); stream.Write("valid window remains open"u8); Assert.Equal(1, peer.DataSends); Assert.Equal(5, clock.Milliseconds); } [Fact] public void OlderAcceptableSegmentCannotUndoALaterWindowUpdate() { var peer = new PacketFixture(); var clock = new TestPlatform(); var stack = new Ipv4Network(peer, clock, Ipv4Configuration.QemuUserNat); using Stream stream = stack.OpenTcp("1.2.3.4", 443); stream.ReadTimeout = 5; stream.WriteTimeout = 40; peer.QueueAcknowledgementAt(peer.PeerNext + 10, 65535); peer.QueueAcknowledgementAt(peer.PeerNext, 0); Assert.Throws(() => stream.Read(new byte[1])); stream.Write("ordered window update"u8); Assert.Equal(1, peer.DataSends); Assert.Equal(5, clock.Milliseconds); } }