PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/tests/Microsoft.AspNet.SignalR.Tests/Server/Connections/PersistentConnectionFacts.cs

https://github.com/mip1983/SignalR
C# | 482 lines | 362 code | 108 blank | 12 comment | 12 complexity | 9fc2cfd9da1e15d82983d2b8159cc946 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Newtonsoft.Json.Linq;
  8. using Microsoft.AspNet.SignalR.Hosting.Memory;
  9. using Xunit;
  10. namespace Microsoft.AspNet.SignalR.Tests
  11. {
  12. public class PersistentConnectionFacts
  13. {
  14. public class OnConnectedAsync : IDisposable
  15. {
  16. [Fact]
  17. public void ConnectionsWithTheSameConnectionIdSSECloseGracefully()
  18. {
  19. var host = new MemoryHost();
  20. host.MapConnection<MyConnection>("/echo");
  21. var tasks = new List<Task>();
  22. for (int i = 0; i < 1000; i++)
  23. {
  24. tasks.Add(ProcessRequest(host, "serverSentEvents", "1"));
  25. }
  26. ProcessRequest(host, "serverSentEvents", "1");
  27. Task.WaitAll(tasks.ToArray());
  28. Assert.True(tasks.All(t => !t.IsFaulted));
  29. }
  30. [Fact]
  31. public void ConnectionsWithTheSameConnectionIdLongPollingCloseGracefully()
  32. {
  33. var host = new MemoryHost();
  34. host.MapConnection<MyConnection>("/echo");
  35. var tasks = new List<Task>();
  36. for (int i = 0; i < 1000; i++)
  37. {
  38. tasks.Add(ProcessRequest(host, "longPolling", "1"));
  39. }
  40. ProcessRequest(host, "longPolling", "1");
  41. Task.WaitAll(tasks.ToArray());
  42. Assert.True(tasks.All(t => !t.IsFaulted));
  43. }
  44. private static Task ProcessRequest(MemoryHost host, string transport, string connectionId)
  45. {
  46. return host.ProcessRequest("http://foo/echo/connect?transport=" + transport + "&connectionId=" + connectionId, request => { }, null);
  47. }
  48. [Fact]
  49. public void GroupsAreNotReadOnConnectedAsync()
  50. {
  51. var host = new MemoryHost();
  52. host.MapConnection<MyConnection>("/echo");
  53. var connection = new Client.Connection("http://foo/echo");
  54. connection.Groups = new List<string> { typeof(MyConnection).FullName + ".test" };
  55. connection.Received += data =>
  56. {
  57. Assert.False(true, "Unexpectedly received data");
  58. };
  59. connection.Start(host).Wait();
  60. Thread.Sleep(TimeSpan.FromSeconds(5));
  61. connection.Stop();
  62. }
  63. [Fact]
  64. public void GroupsAreNotReadOnConnectedAsyncLongPolling()
  65. {
  66. var host = new MemoryHost();
  67. host.MapConnection<MyConnection>("/echo");
  68. var connection = new Client.Connection("http://foo/echo");
  69. connection.Groups = new List<string> { typeof(MyConnection).FullName + ".test" };
  70. connection.Received += data =>
  71. {
  72. Assert.False(true, "Unexpectedly received data");
  73. };
  74. var transport = new Client.Transports.LongPollingTransport(host);
  75. connection.Start(transport).Wait();
  76. Thread.Sleep(TimeSpan.FromSeconds(5));
  77. connection.Stop();
  78. }
  79. [Fact]
  80. public void SendRaisesOnReceivedFromAllEvents()
  81. {
  82. var host = new MemoryHost();
  83. host.MapConnection<MySendingConnection>("/multisend");
  84. var connection = new Client.Connection("http://foo/multisend");
  85. var results = new List<string>();
  86. connection.Received += data =>
  87. {
  88. results.Add(data);
  89. };
  90. connection.Start(host).Wait();
  91. connection.Send("").Wait();
  92. Thread.Sleep(TimeSpan.FromSeconds(5));
  93. connection.Stop();
  94. Debug.WriteLine(String.Join(", ", results));
  95. Assert.Equal(4, results.Count);
  96. Assert.Equal("OnConnectedAsync1", results[0]);
  97. Assert.Equal("OnConnectedAsync2", results[1]);
  98. Assert.Equal("OnReceivedAsync1", results[2]);
  99. Assert.Equal("OnReceivedAsync2", results[3]);
  100. }
  101. [Fact]
  102. public void SendCanBeCalledAfterStateChangedEvent()
  103. {
  104. var host = new MemoryHost();
  105. host.MapConnection<MySendingConnection>("/multisend");
  106. var connection = new Client.Connection("http://foo/multisend");
  107. var results = new List<string>();
  108. connection.Received += data =>
  109. {
  110. results.Add(data);
  111. };
  112. connection.StateChanged += stateChange =>
  113. {
  114. if (stateChange.NewState == Client.ConnectionState.Connected)
  115. {
  116. connection.Send("").Wait();
  117. }
  118. };
  119. connection.Start(host).Wait();
  120. Thread.Sleep(TimeSpan.FromSeconds(5));
  121. connection.Stop();
  122. Debug.WriteLine(String.Join(", ", results));
  123. Assert.Equal(4, results.Count);
  124. }
  125. public void Dispose()
  126. {
  127. GC.Collect();
  128. GC.WaitForPendingFinalizers();
  129. }
  130. }
  131. public class OnReconnectedAsync : IDisposable
  132. {
  133. [Fact]
  134. public void ReconnectFiresAfterHostShutDown()
  135. {
  136. var host = new MemoryHost();
  137. var conn = new MyReconnect();
  138. host.DependencyResolver.Register(typeof(MyReconnect), () => conn);
  139. host.MapConnection<MyReconnect>("/endpoint");
  140. var connection = new Client.Connection("http://foo/endpoint");
  141. connection.Start(host).Wait();
  142. host.Dispose();
  143. Thread.Sleep(TimeSpan.FromSeconds(5));
  144. Assert.Equal(Client.ConnectionState.Reconnecting, connection.State);
  145. connection.Stop();
  146. }
  147. [Fact]
  148. public void ReconnectFiresAfterTimeOutSSE()
  149. {
  150. var host = new MemoryHost();
  151. var conn = new MyReconnect();
  152. host.Configuration.KeepAlive = null;
  153. host.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(5);
  154. host.Configuration.HeartBeatInterval = TimeSpan.FromSeconds(5);
  155. host.DependencyResolver.Register(typeof(MyReconnect), () => conn);
  156. host.MapConnection<MyReconnect>("/endpoint");
  157. var connection = new Client.Connection("http://foo/endpoint");
  158. connection.Start(new Client.Transports.ServerSentEventsTransport(host)).Wait();
  159. Thread.Sleep(TimeSpan.FromSeconds(15));
  160. connection.Stop();
  161. Assert.InRange(conn.Reconnects, 1, 4);
  162. }
  163. [Fact]
  164. public void ReconnectFiresAfterTimeOutLongPolling()
  165. {
  166. var host = new MemoryHost();
  167. var conn = new MyReconnect();
  168. host.Configuration.KeepAlive = null;
  169. host.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(5);
  170. host.Configuration.HeartBeatInterval = TimeSpan.FromSeconds(5);
  171. host.DependencyResolver.Register(typeof(MyReconnect), () => conn);
  172. host.MapConnection<MyReconnect>("/endpoint");
  173. var connection = new Client.Connection("http://foo/endpoint");
  174. connection.Start(new Client.Transports.LongPollingTransport(host)).Wait();
  175. Thread.Sleep(TimeSpan.FromSeconds(15));
  176. connection.Stop();
  177. Assert.InRange(conn.Reconnects, 1, 4);
  178. }
  179. public void Dispose()
  180. {
  181. GC.Collect();
  182. GC.WaitForPendingFinalizers();
  183. }
  184. }
  185. public class GroupTest : IDisposable
  186. {
  187. [Fact]
  188. public void GroupsReceiveMessages()
  189. {
  190. var host = new MemoryHost();
  191. host.MapConnection<MyGroupConnection>("/groups");
  192. var connection = new Client.Connection("http://foo/groups");
  193. var list = new List<string>();
  194. connection.Received += data =>
  195. {
  196. list.Add(data);
  197. };
  198. connection.Start(host).Wait();
  199. // Join the group
  200. connection.Send(new { type = 1, group = "test" }).Wait();
  201. // Sent a message
  202. connection.Send(new { type = 3, group = "test", message = "hello to group test" }).Wait();
  203. // Leave the group
  204. connection.Send(new { type = 2, group = "test" }).Wait();
  205. // Send a message
  206. connection.Send(new { type = 3, group = "test", message = "goodbye to group test" }).Wait();
  207. Thread.Sleep(TimeSpan.FromSeconds(5));
  208. connection.Stop();
  209. Assert.Equal(1, list.Count);
  210. Assert.Equal("hello to group test", list[0]);
  211. }
  212. [Fact]
  213. public void GroupsDontRejoinByDefault()
  214. {
  215. var host = new MemoryHost();
  216. host.Configuration.KeepAlive = null;
  217. host.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(2);
  218. host.Configuration.HeartBeatInterval = TimeSpan.FromSeconds(2);
  219. host.MapConnection<MyGroupConnection>("/groups");
  220. var connection = new Client.Connection("http://foo/groups");
  221. var list = new List<string>();
  222. connection.Received += data =>
  223. {
  224. list.Add(data);
  225. };
  226. connection.Start(host).Wait();
  227. // Join the group
  228. connection.Send(new { type = 1, group = "test" }).Wait();
  229. // Sent a message
  230. connection.Send(new { type = 3, group = "test", message = "hello to group test" }).Wait();
  231. // Force Reconnect
  232. Thread.Sleep(TimeSpan.FromSeconds(5));
  233. // Send a message
  234. connection.Send(new { type = 3, group = "test", message = "goodbye to group test" }).Wait();
  235. Thread.Sleep(TimeSpan.FromSeconds(5));
  236. connection.Stop();
  237. Assert.Equal(1, list.Count);
  238. Assert.Equal("hello to group test", list[0]);
  239. }
  240. [Fact]
  241. public void GroupsRejoinedWhenOnRejoiningGroupsOverridden()
  242. {
  243. var host = new MemoryHost();
  244. host.Configuration.KeepAlive = null;
  245. host.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(2);
  246. host.Configuration.HeartBeatInterval = TimeSpan.FromSeconds(2);
  247. host.MapConnection<MyRejoinGroupConnection>("/groups");
  248. var connection = new Client.Connection("http://foo/groups");
  249. var list = new List<string>();
  250. connection.Received += data =>
  251. {
  252. list.Add(data);
  253. };
  254. connection.Start(host).Wait();
  255. // Join the group
  256. connection.Send(new { type = 1, group = "test" }).Wait();
  257. // Sent a message
  258. connection.Send(new { type = 3, group = "test", message = "hello to group test" }).Wait();
  259. // Force Reconnect
  260. Thread.Sleep(TimeSpan.FromSeconds(5));
  261. // Send a message
  262. connection.Send(new { type = 3, group = "test", message = "goodbye to group test" }).Wait();
  263. Thread.Sleep(TimeSpan.FromSeconds(5));
  264. connection.Stop();
  265. Assert.Equal(2, list.Count);
  266. Assert.Equal("hello to group test", list[0]);
  267. Assert.Equal("goodbye to group test", list[1]);
  268. }
  269. public void Dispose()
  270. {
  271. GC.Collect();
  272. GC.WaitForPendingFinalizers();
  273. }
  274. }
  275. public class SendFacts : IDisposable
  276. {
  277. [Fact]
  278. public void SendToAllButCaller()
  279. {
  280. var host = new MemoryHost();
  281. host.MapConnection<FilteredConnection>("/filter");
  282. var connection1 = new Client.Connection("http://foo/filter");
  283. var connection2 = new Client.Connection("http://foo/filter");
  284. var wh1 = new ManualResetEventSlim(initialState: false);
  285. var wh2 = new ManualResetEventSlim(initialState: false);
  286. connection1.Received += data => wh1.Set();
  287. connection2.Received += data => wh2.Set();
  288. connection1.Start(host).Wait();
  289. connection2.Start(host).Wait();
  290. connection1.Send("test").Wait();
  291. Assert.False(wh1.WaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  292. Assert.True(wh2.WaitHandle.WaitOne(TimeSpan.FromSeconds(5)));
  293. connection1.Stop();
  294. connection2.Stop();
  295. }
  296. public void Dispose()
  297. {
  298. GC.Collect();
  299. GC.WaitForPendingFinalizers();
  300. }
  301. }
  302. }
  303. public class FilteredConnection : PersistentConnection
  304. {
  305. protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
  306. {
  307. return Connection.Broadcast(data, connectionId);
  308. }
  309. }
  310. public class MyGroupConnection : PersistentConnection
  311. {
  312. protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
  313. {
  314. JObject operation = JObject.Parse(data);
  315. int type = operation.Value<int>("type");
  316. string group = operation.Value<string>("group");
  317. if (type == 1)
  318. {
  319. return Groups.Add(connectionId, group);
  320. }
  321. else if (type == 2)
  322. {
  323. return Groups.Remove(connectionId, group);
  324. }
  325. else if (type == 3)
  326. {
  327. return Groups.Send(group, operation.Value<string>("message"));
  328. }
  329. return base.OnReceivedAsync(request, connectionId, data);
  330. }
  331. }
  332. public class MyRejoinGroupConnection : MyGroupConnection
  333. {
  334. protected override IEnumerable<string> OnRejoiningGroups(IRequest request, IEnumerable<string> groups, string connectionId)
  335. {
  336. return groups;
  337. }
  338. }
  339. public class MyReconnect : PersistentConnection
  340. {
  341. public int Reconnects { get; set; }
  342. protected override Task OnConnectedAsync(IRequest request, string connectionId)
  343. {
  344. return null;
  345. }
  346. protected override Task OnReconnectedAsync(IRequest request, string connectionId)
  347. {
  348. Reconnects++;
  349. return base.OnReconnectedAsync(request, connectionId);
  350. }
  351. }
  352. public class MySendingConnection : PersistentConnection
  353. {
  354. protected override Task OnConnectedAsync(IRequest request, string connectionId)
  355. {
  356. Connection.Send(connectionId, "OnConnectedAsync1");
  357. Connection.Send(connectionId, "OnConnectedAsync2");
  358. return base.OnConnectedAsync(request, connectionId);
  359. }
  360. protected override Task OnReceivedAsync(IRequest request, string connectionId, string data)
  361. {
  362. Connection.Send(connectionId, "OnReceivedAsync1");
  363. Connection.Send(connectionId, "OnReceivedAsync2");
  364. return base.OnReceivedAsync(request, connectionId, data);
  365. }
  366. }
  367. public class MyConnection : PersistentConnection
  368. {
  369. protected override Task OnConnectedAsync(IRequest request, string connectionId)
  370. {
  371. return Groups.Send("test", "hey");
  372. }
  373. }
  374. }