using System.Net; using System.Net.Sockets; using System.Text; namespace Nonemm.Keying.Tests; /// The sender is tested against a socket that speaks cwdaemon's side of the /// protocol, so what goes on the wire is what is asserted. public class CwDaemonSenderTests : IDisposable { private readonly UdpClient daemon = new(new IPEndPoint(IPAddress.Loopback, 0)); private int Port => ((IPEndPoint)daemon.Client.LocalEndPoint!).Port; public void Dispose() { daemon.Dispose(); GC.SuppressFinalize(this); } private async Task NextDatagram(Func send) { Task receiving = daemon.ReceiveAsync(); await send(); UdpReceiveResult received = await receiving.WaitAsync(TimeSpan.FromSeconds(5)); return received.Buffer; } [Fact] public async Task TextGoesOutInUpperCaseBehindAReplyRequest() { using CwDaemonSender sender = new("127.0.0.1", Port); await sender.SendAsync("cq test de dl1abc"); // one receive at a time: two at once can take the datagrams in either order UdpReceiveResult request = await daemon.ReceiveAsync().WaitAsync(TimeSpan.FromSeconds(5)); UdpReceiveResult text = await daemon.ReceiveAsync().WaitAsync(TimeSpan.FromSeconds(5)); Assert.Equal("\u001bhnonemm", Encoding.ASCII.GetString(request.Buffer)); Assert.Equal("CQ TEST DE DL1ABC", Encoding.ASCII.GetString(text.Buffer)); } /// cwdaemon answers with `h` and the text of the reply request once the /// message has been played. [Fact] public async Task TheReplySaysTheMessageHasGoneOut() { using CwDaemonSender sender = new("127.0.0.1", Port); TaskCompletionSource finished = new(); sender.Finished += (_, _) => finished.TrySetResult(); Task request = daemon.ReceiveAsync(); await sender.SendAsync("test"); UdpReceiveResult from = await request.WaitAsync(TimeSpan.FromSeconds(5)); await daemon.SendAsync(Encoding.ASCII.GetBytes("hnonemm\r\n"), from.RemoteEndPoint); await finished.Task.WaitAsync(TimeSpan.FromSeconds(5)); } [Fact] public async Task AReplyForSomebodyElseIsPassedOver() { using CwDaemonSender sender = new("127.0.0.1", Port); TaskCompletionSource finished = new(); sender.Finished += (_, _) => finished.TrySetResult(); Task request = daemon.ReceiveAsync(); await sender.SendAsync("test"); UdpReceiveResult from = await request.WaitAsync(TimeSpan.FromSeconds(5)); await daemon.SendAsync(Encoding.ASCII.GetBytes("hsomebodyelse\r\n"), from.RemoteEndPoint); await Assert.ThrowsAsync( () => finished.Task.WaitAsync(TimeSpan.FromMilliseconds(300))); } [Fact] public async Task AbortIsTheEscapeFourCommand() { using CwDaemonSender sender = new("127.0.0.1", Port); byte[] sent = await NextDatagram(() => sender.AbortAsync()); Assert.Equal([0x1B, (byte)'4'], sent); } [Fact] public async Task SpeedIsTheEscapeTwoCommand() { using CwDaemonSender sender = new("127.0.0.1", Port); byte[] sent = await NextDatagram(() => sender.SetSpeedAsync(32)); Assert.Equal([0x1B, (byte)'2', (byte)'3', (byte)'2'], sent); } }