Update tests network helper to be reliable in multi-threaded tests
authorMarek Safar <marek.safar@gmail.com>
Fri, 15 Sep 2017 09:10:31 +0000 (11:10 +0200)
committerMarek Safar <marek.safar@gmail.com>
Mon, 18 Sep 2017 17:10:00 +0000 (19:10 +0200)
mcs/class/test-helpers/NetworkHelpers.cs

index 9d5eb1140816690a5d1ab6c03e97b8a94935da32..262b8d33232459be06ddde9a7b9e8f9bfbd7befc 100644 (file)
@@ -1,12 +1,14 @@
 using System;
 using System.Net;
 using System.Net.Sockets;
+using System.Collections.Generic;
 
 namespace MonoTests.Helpers {
 
        public static class NetworkHelpers
        {
                static Random rndPort = new Random ();
+               static HashSet<int> portsTable = new HashSet<int> ();
 
                public static int FindFreePort ()
                {
@@ -15,17 +17,32 @@ namespace MonoTests.Helpers {
 
                public static IPEndPoint LocalEphemeralEndPoint ()
                {
-                       while (true) {
-                               var ep = new IPEndPoint (IPAddress.Loopback, rndPort.Next (10000, 60000));
-
-                               try {
-                                       using (var socket = new Socket (ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) {
-                                               socket.Bind (ep);
-                                               socket.Close ();
-                                       }
-                                       return ep;
-                               } catch (SocketException) { }
+                       int counter = 0;
+
+                       while (counter < 1000) {
+                               var testingPort = rndPort.Next (10000, 60000);
+
+                               var ep = new IPEndPoint (IPAddress.Loopback, testingPort);
+
+                               lock (portsTable) {
+                                       if (portsTable.Contains (testingPort))
+                                               continue;
+
+                                       ++counter;
+
+                                       try {
+                                               using (var socket = new Socket (ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) {
+                                                       socket.Bind (ep);
+                                                       socket.Close ();
+                                               }
+
+                                               portsTable.Add (testingPort);
+                                               return ep;
+                                       } catch (SocketException) { }
+                               }
                        }
+
+                       throw new ApplicationException ($"Could not find available local port after {counter} retries");
                }
        }
 }