public async Task Connect_Address_Credentials_Succeeds_When_TcpConnection_Succeeds(IPEndPoint endpoint, string username, string password) { var c = new Mock <IMessageConnection>(); var factory = new Mock <IConnectionFactory>(); factory.Setup(m => m.GetServerConnection( It.IsAny <IPEndPoint>(), It.IsAny <EventHandler>(), It.IsAny <EventHandler <ConnectionDisconnectedEventArgs> >(), It.IsAny <EventHandler <MessageReadEventArgs> >(), It.IsAny <ConnectionOptions>(), It.IsAny <ITcpClient>())) .Returns(c.Object); var key = new WaitKey(MessageCode.Server.Login); var waiter = new Mock <IWaiter>(); waiter.Setup(m => m.Wait <LoginResponse>(key, It.IsAny <int?>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(new LoginResponse(succeeded: true, string.Empty))); using (var s = new SoulseekClient(connectionFactory: factory.Object, waiter: waiter.Object)) { var ex = await Record.ExceptionAsync(async() => await s.ConnectAsync(endpoint.Address.ToString(), endpoint.Port, username, password)); Assert.Null(ex); } waiter.Verify(m => m.Wait <LoginResponse>(key, It.IsAny <int?>(), It.IsAny <CancellationToken>()), Times.Once); }
public async Task LeaveRoomAsync_Uses_Given_CancellationToken(string roomName) { var cancellationToken = new CancellationToken(); var conn = new Mock <IMessageConnection>(); conn.Setup(m => m.State) .Returns(ConnectionState.Connected); var key = new WaitKey(MessageCode.Server.LeaveRoom, roomName); var waiter = new Mock <IWaiter>(); waiter.Setup(m => m.Wait(It.Is <WaitKey>(k => k.Equals(key)), It.IsAny <int?>(), It.IsAny <CancellationToken?>())) .Returns(Task.CompletedTask); using (var s = new SoulseekClient(serverConnection: conn.Object, waiter: waiter.Object)) { s.SetProperty("State", SoulseekClientStates.Connected | SoulseekClientStates.LoggedIn); var ex = await Record.ExceptionAsync(() => s.LeaveRoomAsync(roomName, cancellationToken)); Assert.Null(ex); } conn.Verify(m => m.WriteAsync(It.IsAny <byte[]>(), cancellationToken), Times.Once); }
public void Wait_Dictionary_And_Queue_Are_Collected_After_Last_Wait_Is_Dequeued() { using (var waiter = new Waiter()) { var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); var locks = waiter.GetProperty <ConcurrentDictionary <WaitKey, ReaderWriterLockSlim> >("Locks"); int CountWaits(WaitKey k) { waits.TryGetValue(k, out var queue); return(queue?.Count ?? 0); } var key = new WaitKey("foo"); waiter.Wait(key); waiter.Wait(key); Assert.Equal(2, CountWaits(key)); Assert.True(waits.TryGetValue(key, out _)); Assert.True(locks.TryGetValue(key, out _)); waiter.Complete(key); Assert.Equal(1, CountWaits(key)); Assert.True(waits.TryGetValue(key, out _)); Assert.True(locks.TryGetValue(key, out _)); waiter.Complete(key); Assert.Equal(0, CountWaits(key)); Assert.False(waits.TryGetValue(key, out _)); Assert.False(locks.TryGetValue(key, out _)); } }
public void Wait_Throws_And_Is_Dequeued_When_Cancelled() { using (var tcs = new CancellationTokenSource()) { tcs.CancelAfter(100); var key = new WaitKey(MessageCode.ServerLogin); using (var waiter = new Waiter(0)) { Task <object> task = waiter.Wait <object>(key, 999999, tcs.Token); object result = null; var ex = Record.Exception(() => result = task.Result); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.NotNull(ex); Assert.IsType <OperationCanceledException>(ex.InnerException); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Empty(queue); } } }
static void Main(string[] args) { MyClass t = new MyClass(); NonStatic myNonStatic = new NonStatic(t.Y); myNonStatic(); myNonStatic = MyClass.X; myNonStatic(); MyWrite myDelegate = new MyWrite(WriteLine); MyReadLine read = ReadLine; string str = read(); MyWrite write = WriteLine; write("myDelegate == WriteLine()"); write(str); write = Write; write("myDelegate == Write()"); write("a"); write("a"); write("a"); write("a"); WaitKey wait = ReadKey; wait(); }
public async Task JoinRoomAsync_Returns_Expected_Response_On_Success(string roomName) { var conn = new Mock <IMessageConnection>(); conn.Setup(m => m.State) .Returns(ConnectionState.Connected); var expectedResponse = new RoomData(roomName, 0, Enumerable.Empty <UserData>(), false, null, null, null); var key = new WaitKey(MessageCode.Server.JoinRoom, roomName); var waiter = new Mock <IWaiter>(); waiter.Setup(m => m.Wait <RoomData>(It.Is <WaitKey>(k => k.Equals(key)), It.IsAny <int?>(), It.IsAny <CancellationToken?>())) .Returns(Task.FromResult(expectedResponse)); using (var s = new SoulseekClient(serverConnection: conn.Object, waiter: waiter.Object)) { s.SetProperty("State", SoulseekClientStates.Connected | SoulseekClientStates.LoggedIn); RoomData response; response = await s.JoinRoomAsync(roomName); Assert.Equal(expectedResponse, response); } }
public void Wait_Throws_And_Is_Dequeued_When_Cancelled() { using (var tcs = new CancellationTokenSource()) { tcs.CancelAfter(100); var key = new WaitKey(MessageCode.Server.Login); using (var waiter = new Waiter(0)) { Task <object> task = waiter.Wait <object>(key, 999999, tcs.Token); object result = null; // stick another wait in the same queue to prevent the disposal logic from removing // the dictionary record before we can inspect it waiter.Wait <object>(key, 999999, CancellationToken.None); var ex = Record.Exception(() => result = task.Result); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.NotNull(ex); Assert.IsType <OperationCanceledException>(ex.InnerException); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Single(queue); // should contain only the dummy wait } } }
public async Task GetRoomListAsync_Uses_Given_CancellationToken(IReadOnlyCollection <RoomInfo> rooms, CancellationToken cancellationToken) { var conn = new Mock <IMessageConnection>(); conn.Setup(m => m.State) .Returns(ConnectionState.Connected); var key = new WaitKey(MessageCode.Server.RoomList); var waiter = new Mock <IWaiter>(); waiter.Setup(m => m.Wait <IReadOnlyCollection <RoomInfo> >(It.Is <WaitKey>(k => k.Equals(key)), It.IsAny <int?>(), It.IsAny <CancellationToken?>())) .Returns(Task.FromResult(rooms)); using (var s = new SoulseekClient(serverConnection: conn.Object, waiter: waiter.Object)) { s.SetProperty("State", SoulseekClientStates.Connected | SoulseekClientStates.LoggedIn); IReadOnlyCollection <RoomInfo> response; response = await s.GetRoomListAsync(cancellationToken); Assert.Equal(rooms, response); } conn.Verify(m => m.WriteAsync(It.IsAny <IOutgoingMessage>(), cancellationToken), Times.Once); }
internal void Non_Generic_Wait_Invocation_Creates_Valid_Wait(MessageCode.Server code, string token, int?timeout) { var key = new WaitKey(code, token); using (var waiter = new Waiter()) { Task task = waiter.Wait(key, timeout); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.IsType <Task <object> >(task); Assert.NotNull(task); Assert.Equal(TaskStatus.WaitingForActivation, task.Status); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Single(queue); Assert.NotEqual(new DateTime(), wait.DateTime); if (timeout != null) { Assert.Equal(timeout, wait.TimeoutAfter); } } }
public void Wait_For_Subsequent_MessageCode_Enqueues_Wait() { using (var waiter = new Waiter()) { var task1 = waiter.Wait <object>(new WaitKey(MessageCode.Server.Login)); var task2 = waiter.Wait <object>(new WaitKey(MessageCode.Server.Login)); var key = new WaitKey(MessageCode.Server.Login); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); Assert.IsType <Task <object> >(task1); Assert.NotNull(task1); Assert.Equal(TaskStatus.WaitingForActivation, task1.Status); Assert.IsType <Task <object> >(task2); Assert.NotNull(task2); Assert.Equal(TaskStatus.WaitingForActivation, task2.Status); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Equal(2, queue.Count); } }
public void Completes_Solicited_Distributed_Connection_On_Distributed_PierceFirewall(IPAddress ip, string username, int token) { var(handler, mocks) = GetFixture(ip); var message = new PierceFirewall(token); var messageBytes = message.ToByteArray().AsSpan().Slice(4).ToArray(); mocks.Connection.Setup(m => m.ReadAsync(4, It.IsAny <CancellationToken?>())) .Returns(Task.FromResult(BitConverter.GetBytes(messageBytes.Length))); mocks.Connection.Setup(m => m.ReadAsync(messageBytes.Length, It.IsAny <CancellationToken?>())) .Returns(Task.FromResult(messageBytes)); var dict = new ConcurrentDictionary <int, string>(); dict.TryAdd(token, username); mocks.DistributedConnectionManager.Setup(m => m.PendingSolicitations) .Returns(dict); handler.HandleConnection(null, mocks.Connection.Object); var expectedKey = new WaitKey(Constants.WaitKey.SolicitedDistributedConnection, username, token); mocks.Waiter.Verify(m => m.Complete(expectedKey, mocks.Connection.Object), Times.Once); }
public void Sets_BranchRoot_On_Message_From_Parent(string parent, IPAddress ip, int port, string root) { var(handler, mocks) = GetFixture(); var conn = new Mock <IMessageConnection>(); conn.Setup(m => m.Context).Returns(null); conn.Setup(m => m.IPAddress).Returns(ip); conn.Setup(m => m.Port).Returns(port); conn.Setup(m => m.Username).Returns(parent); conn.Setup(m => m.Key).Returns(new ConnectionKey(ip, port)); var key = new WaitKey(Constants.WaitKey.BranchRootMessage, conn.Object.Context, conn.Object.Key); mocks.DistributedConnectionManager.Setup(m => m.Parent).Returns((parent, ip, port)); var message = new MessageBuilder() .WriteCode(MessageCode.Distributed.BranchRoot) .WriteString(root) .Build(); handler.HandleMessage(conn.Object, message); mocks.Waiter.Verify(m => m.Complete <string>(key, root), Times.Once); mocks.DistributedConnectionManager.Verify(m => m.SetBranchRoot(root), Times.Once); }
public void Wait_Throws_And_Is_Dequeued_When_Timing_out() { var key = new WaitKey(MessageCode.Server.Login); using (var waiter = new Waiter(0)) { Task <object> task = waiter.Wait <object>(key); object result = null; // stick another wait in the same queue to prevent the disposal logic from removing // the dictionary record before we can inspect it waiter.Wait <object>(key, timeout: 99999); var ex = Record.Exception(() => result = task.Result); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.NotNull(ex); Assert.IsType <TimeoutException>(ex.InnerException); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Single(queue); } }
public void Expiration_Ignores_Non_Timed_Out_Waits() { var key = new WaitKey(MessageCode.Server.Login); using (var waiter = new Waiter(0)) { Task <object> task = waiter.Wait <object>(key); waiter.Wait <object>(key, 30); object result = null; var ex = Record.Exception(() => result = task.Result); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.NotNull(ex); Assert.IsType <TimeoutException>(ex.InnerException); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Single(queue); } }
public async Task DownloadInternalAsync_Throws_DownloadException_On_PeerTransferRequest_Cancellation(string username, IPAddress ip, int port, string filename, int token, int size) { var options = new SoulseekClientOptions(messageTimeout: 5); var response = new PeerTransferResponse(token, false, size, string.Empty); var responseWaitKey = new WaitKey(MessageCode.PeerTransferResponse, username, token); var waiter = new Mock <IWaiter>(); waiter.Setup(m => m.Wait <PeerTransferResponse>(It.Is <WaitKey>(w => w.Equals(responseWaitKey)), null, It.IsAny <CancellationToken>())) .Returns(Task.FromResult(response)); waiter.Setup(m => m.WaitIndefinitely <PeerTransferRequest>(It.IsAny <WaitKey>(), It.IsAny <CancellationToken>())) .Returns(Task.FromException <PeerTransferRequest>(new OperationCanceledException())); waiter.Setup(m => m.Wait <GetPeerAddressResponse>(It.IsAny <WaitKey>(), null, It.IsAny <CancellationToken>())) .Returns(Task.FromResult(new GetPeerAddressResponse(username, ip, port))); var conn = new Mock <IMessageConnection>(); var connFactory = new Mock <IMessageConnectionFactory>(); connFactory.Setup(m => m.GetMessageConnection(It.IsAny <MessageConnectionType>(), It.IsAny <string>(), It.IsAny <IPAddress>(), It.IsAny <int>(), It.IsAny <ConnectionOptions>())) .Returns(conn.Object); var s = new SoulseekClient("127.0.0.1", 1, options, messageWaiter: waiter.Object, messageConnectionFactory: connFactory.Object); s.SetProperty("State", SoulseekClientStates.Connected | SoulseekClientStates.LoggedIn); var ex = await Record.ExceptionAsync(async() => await s.InvokeMethod <Task <byte[]> >("DownloadInternalAsync", username, filename, token, null)); Assert.NotNull(ex); Assert.IsType <DownloadException>(ex); Assert.IsType <OperationCanceledException>(ex.InnerException); }
public void TokenParts_Returns_Empty_Given_Null_Parts() { WaitKey k = new WaitKey(); Assert.NotNull(k.TokenParts); Assert.Empty(k.TokenParts); }
public void GetHashCode_Differs_Given_Different_Key() { var k1 = new WaitKey(1, "test", 5m); var k2 = new WaitKey(2, "foo", 2.5m); Assert.NotEqual(k1.GetHashCode(), k2.GetHashCode()); }
public void Non_Generic_WaitIndefinitely_Invocation_Creates_Wait_With_Max_Timeout() { var key = new WaitKey(MessageCode.Server.Login); using (var waiter = new Waiter()) { Task task = waiter.WaitIndefinitely(key); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.IsType <Task <object> >(task); Assert.NotNull(task); Assert.Equal(TaskStatus.WaitingForActivation, task.Status); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Single(queue); Assert.NotEqual(new DateTime(), wait.DateTime); Assert.Equal(int.MaxValue, wait.TimeoutAfter); } }
public void GetHashCode_Matches_Given_Identical_Key() { var k1 = new WaitKey(1, "test", 5m); var k2 = new WaitKey(1, "test", 5m); Assert.Equal(k1.GetHashCode(), k2.GetHashCode()); }
public void Wait_Throws_And_Is_Dequeued_When_Thrown() { var key = new WaitKey(MessageCode.Server.Login); using (var waiter = new Waiter(0)) { Task <object> task = waiter.Wait <object>(key, 999999); object result = null; waiter.Throw(key, new InvalidOperationException("error")); var ex = Record.Exception(() => result = task.Result); var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); waits.TryGetValue(key, out var queue); queue.TryPeek(out var wait); Assert.NotNull(ex); Assert.IsType <InvalidOperationException>(ex.InnerException); Assert.Equal("error", ex.InnerException.Message); Assert.NotEmpty(waits); Assert.Single(waits); Assert.NotNull(queue); Assert.Empty(queue); } }
public void Wait_Dictionary_And_Queue_Are_Collected_After_Last_Wait_Is_Dequeued() { using (var tcs = new CancellationTokenSource()) { tcs.CancelAfter(100); var key = new WaitKey(MessageCode.Server.Login); using (var waiter = new Waiter(0)) { Task <object> task = waiter.Wait <object>(key, 999999, tcs.Token); object result = null; var ex = Record.Exception(() => result = task.Result); waiter.InvokeMethod("MonitorWaits", null, null); // force clean up. normally this is on a timer. var waits = waiter.GetProperty <ConcurrentDictionary <WaitKey, ConcurrentQueue <PendingWait> > >("Waits"); var exists = waits.TryGetValue(key, out var record); Assert.NotNull(ex); Assert.IsType <OperationCanceledException>(ex.InnerException); Assert.Empty(waits); Assert.False(exists); } } }
public void DoubleEqualOperator_Returns_True_When_Equal() { var k1 = new WaitKey("foo", 2); var k2 = new WaitKey("foo", 2); Assert.True(k1 == k2); Assert.True(k2 == k1); }
public void TokenParts_Returns_Parts() { WaitKey k = new WaitKey(1, 2); Assert.Equal(2, k.TokenParts.Length); Assert.Contains(1, k.TokenParts); Assert.Contains(2, k.TokenParts); }
public void Instantiates_With_Null_Parts() { WaitKey k = null; var ex = Record.Exception(() => k = new WaitKey()); Assert.Null(ex); Assert.NotNull(k); }
public void Equals_Handles_Boxed_Instances() { var k1 = new WaitKey("foo", 2); var k2 = new WaitKey("foo", 2); Assert.True(k1.Equals((object)k2)); Assert.True(k2.Equals((object)k1)); }
public void Equals_Returns_False_When_Different_Type() { var k1 = new WaitKey("foo", 2); var k2 = "bar"; Assert.False(k1.Equals(k2)); Assert.False(k2.Equals(k1)); }
public void Equals_Returns_False_When_Not_Equal() { var k1 = new WaitKey("foo", 2); var k2 = new WaitKey("bar", 3); Assert.False(k1.Equals(k2)); Assert.False(k2.Equals(k1)); }
public void Equals_Returns_True_When_Equal() { var k1 = new WaitKey("foo", 2); var k2 = new WaitKey("foo", 2); Assert.True(k1.Equals(k2)); Assert.True(k2.Equals(k1)); }
public void NotEqualOperator_Returns_False_When_Not_Equal() { var k1 = new WaitKey("foo", 2); var k2 = new WaitKey("bar", 3); Assert.True(k1 != k2); Assert.True(k2 != k1); }
public async Task DownloadInternalAsync_Raises_Expected_Final_Event_On_Cancellation(string username, IPAddress ip, int port, string filename, int token, int size) { var options = new SoulseekClientOptions(messageTimeout: 5); var response = new PeerTransferResponse(token, false, size, string.Empty); var responseWaitKey = new WaitKey(MessageCode.PeerTransferResponse, username, token); var request = new PeerTransferRequest(TransferDirection.Download, token, filename, size); var transferConn = new Mock <IConnection>(); transferConn.Setup(m => m.WriteAsync(It.IsAny <byte[]>(), It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask); var waiter = new Mock <IWaiter>(); waiter.Setup(m => m.Wait <PeerTransferResponse>(It.Is <WaitKey>(w => w.Equals(responseWaitKey)), null, It.IsAny <CancellationToken>())) .Returns(Task.FromResult(response)); waiter.Setup(m => m.WaitIndefinitely <PeerTransferRequest>(It.IsAny <WaitKey>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(request)); waiter.Setup(m => m.Wait(It.IsAny <WaitKey>(), null, It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask); waiter.Setup(m => m.WaitIndefinitely <byte[]>(It.IsAny <WaitKey>(), It.IsAny <CancellationToken>())) .Returns(Task.FromException <byte[]>(new OperationCanceledException())); waiter.Setup(m => m.Wait <IConnection>(It.IsAny <WaitKey>(), null, It.IsAny <CancellationToken>())) .Returns(Task.FromResult(transferConn.Object)); waiter.Setup(m => m.Wait <GetPeerAddressResponse>(It.IsAny <WaitKey>(), null, It.IsAny <CancellationToken>())) .Returns(Task.FromResult(new GetPeerAddressResponse(username, ip, port))); var conn = new Mock <IMessageConnection>(); var connFactory = new Mock <IMessageConnectionFactory>(); connFactory.Setup(m => m.GetMessageConnection(It.IsAny <MessageConnectionType>(), It.IsAny <string>(), It.IsAny <IPAddress>(), It.IsAny <int>(), It.IsAny <ConnectionOptions>())) .Returns(conn.Object); var s = new SoulseekClient("127.0.0.1", 1, options, messageWaiter: waiter.Object, messageConnectionFactory: connFactory.Object); s.SetProperty("State", SoulseekClientStates.Connected | SoulseekClientStates.LoggedIn); var events = new List <DownloadStateChangedEventArgs>(); s.DownloadStateChanged += (sender, e) => { events.Add(e); }; var ex = await Record.ExceptionAsync(async() => await s.InvokeMethod <Task <byte[]> >("DownloadInternalAsync", username, filename, token, null)); Assert.NotNull(ex); Assert.IsType <DownloadException>(ex); Assert.IsType <OperationCanceledException>(ex.InnerException); Assert.Equal(DownloadStates.Cancelled, events[events.Count - 1].PreviousState); Assert.Equal(DownloadStates.Completed | DownloadStates.Cancelled, events[events.Count - 1].State); }