[System] Updated SocketTest.TcpDoubleBind.
authorMarcos Henrich <marcos.henrich@xamarin.com>
Wed, 16 Sep 2015 15:21:29 +0000 (16:21 +0100)
committerMarcos Henrich <marcos.henrich@xamarin.com>
Thu, 17 Sep 2015 11:22:24 +0000 (12:22 +0100)
Multiple threads listening to the same address and port are not possible
before linux 3.9 kernel, where the socket option SO_REUSEPORT was
introduced.

This commit makes TcpDoubleBind sensible to this OS capability.

mcs/class/System/Test/System.Net.Sockets/SocketTest.cs

index 59e3f322dd87722098b2661868ee3cd268f44676..fbc2bff995e010b1e2e97373f5bd7a86db9b7aba 100755 (executable)
@@ -9,8 +9,10 @@
 //
 
 using System;
+using System.Linq;
 using System.Collections;
 using System.Threading;
+using System.Text.RegularExpressions;
 using System.Net;
 using System.Net.Sockets;
 using NUnit.Framework;
@@ -3477,6 +3479,37 @@ namespace MonoTests.System.Net.Sockets
                        s.Close ();
                }
 
+               static bool supportsTcpReuse = false;
+               static bool supportsTcpReuseSet = false;
+
+               static bool SupportsTcpReuse ()
+               {
+                       if (supportsTcpReuseSet)
+                               return supportsTcpReuse;
+
+                       if (Path.DirectorySeparatorChar == '/') {
+                               /*
+                                * On UNIX OS
+                                * Multiple threads listening to the same address and port are not possible
+                                * before linux 3.9 kernel, where the socket option SO_REUSEPORT was introduced.
+                                */
+                               Regex reg = new Regex(@"^#define\s*SO_REUSEPORT");
+                               foreach (string directory in Directory.GetDirectories ("/usr/include")) {
+                                       var f = Directory.GetFiles (directory, "socket.h").SingleOrDefault ();
+                                       if (f != null && File.ReadLines (f).Any (l => reg.Match (l).Success)) {
+                                               supportsTcpReuse = true;
+                                               break;
+                                       }
+                               }
+                       } else {
+                               supportsTcpReuse = true;
+                       }
+
+                       supportsTcpReuseSet = true;
+
+                       return supportsTcpReuse;
+               }
+
                // Test case for bug #31557
                [Test]
                public void TcpDoubleBind ()
@@ -3492,10 +3525,15 @@ namespace MonoTests.System.Net.Sockets
 
                                ss.SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
 
-                               ss.Bind (new IPEndPoint (IPAddress.Any, 12345));
-                               ss.Listen(1);
+                               Exception ex = null;
+                               try {
+                                       ss.Bind (new IPEndPoint (IPAddress.Any, 12345));
+                                       ss.Listen(1);
+                               } catch (SocketException e) {
+                                       ex = e;
+                               }
 
-                               // If we make it this far, we succeeded.
+                               Assert.AreEqual (SupportsTcpReuse (), ex == null);
                        }
                }