[tests] Avoid "Address already in use"
[mono.git] / mcs / class / System.ServiceModel / Test / System.ServiceModel / ServiceHostTest.cs
index d98e86302e9bc2deac24f932b3594a587ad45c0a..a120402ff7cc6bbcdcaadc235ad311843ca49752 100644 (file)
@@ -34,6 +34,8 @@ using System.ServiceModel.Description;
 using System.ServiceModel.Dispatcher;
 using NUnit.Framework;
 
+using MonoTests.Helpers;
+
 namespace MonoTests.System.ServiceModel
 {
        [TestFixture]
@@ -130,7 +132,6 @@ namespace MonoTests.System.ServiceModel
 
                [Test]
                [ExpectedException (typeof (InvalidOperationException))]
-               [Category ("NotWorking")]
                public void AddServiceEndpoint2 ()
                {
                        ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
@@ -143,7 +144,6 @@ namespace MonoTests.System.ServiceModel
 
                [Test]
                [ExpectedException (typeof (InvalidOperationException))]
-               [Category ("NotWorking")]
                public void AddServiceEndpoint2_2 ()
                {
                        ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
@@ -157,12 +157,11 @@ namespace MonoTests.System.ServiceModel
 
                [Test]
                [ExpectedException (typeof (InvalidOperationException))]
-               [Category ("NotWorking")] // If I blindly reject things like this, it will block Service[Debug|Metadata]Behavior functionality.
                public void AddServiceEndpoint2_3 ()
                {
-                       ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
-                       host.Description.Endpoints.Add (new ServiceEndpoint (ContractDescription.GetContract (typeof (Foo)), new BasicHttpBinding (), new EndpointAddress ("http://localhost/echo")));
-                       host.Description.Endpoints.Add (new ServiceEndpoint (ContractDescription.GetContract (typeof (IMetadataExchange)), new BasicHttpBinding (), new EndpointAddress ("http://localhost/echo")));
+                       ServiceHost host = new ServiceHost (typeof (HogeFuga), new Uri ("http://localhost/echo"));
+                       host.Description.Endpoints.Add (new ServiceEndpoint (ContractDescription.GetContract (typeof (IHoge)), new BasicHttpBinding (), new EndpointAddress ("http://localhost/echo")));
+                       host.Description.Endpoints.Add (new ServiceEndpoint (ContractDescription.GetContract (typeof (IFuga)), new BasicHttpBinding (), new EndpointAddress ("http://localhost/echo")));
 
                        // Different contracts unlike previous two cases.
                        // If two or more endpoints are bound to the same listen
@@ -172,9 +171,31 @@ namespace MonoTests.System.ServiceModel
                        host.Close (); // should not reach here. It is to make sure to close unexpectedly opened host.
                }
 
+               [Test]
+               public void AddServiceEndpoint2_4 ()
+               {
+                       var ep = "http://" + NetworkHelpers.LocalEphemeralEndPoint().ToString();
+                       ServiceHost host = new ServiceHost (typeof (HogeFuga), new Uri (ep));
+                       var binding = new BasicHttpBinding ();
+                       host.AddServiceEndpoint (typeof (IHoge), binding, new Uri (ep));
+                       host.AddServiceEndpoint (typeof (IFuga), binding, new Uri (ep));
+
+                       // Use the same binding, results in one ChannelDispatcher (actually two, for metadata/debug behavior).
+                       host.Open ();
+                       try {
+                               Assert.AreEqual (2, host.ChannelDispatchers.Count, "#1");
+                               foreach (ChannelDispatcher cd in host.ChannelDispatchers) {
+                                       if (cd.BindingName != binding.Name)
+                                               continue; // mex
+                                       Assert.AreEqual (2, cd.Endpoints.Count, "#2");
+                               }
+                       } finally {
+                               host.Close ();
+                       }
+               }
+
                [Test]
                [ExpectedException (typeof (InvalidOperationException))]
-               [Category ("NotWorking")]
                public void AddServiceEndpoint3 ()
                {
                        ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
@@ -185,6 +206,26 @@ namespace MonoTests.System.ServiceModel
                        host.Close (); // should not reach here. It is to make sure to close unexpectedly opened host.
                }
 
+               [Test]
+               public void Open ()
+               {
+                       ServiceHost host = new ServiceHost (typeof (ZeroOperationsImpl));
+                       host.AddServiceEndpoint (typeof (IHaveZeroOperarationsContract), new BasicHttpBinding (), "http://localhost/echo");
+
+                       try {
+                               host.Open ();
+                               Assert.Fail ("InvalidOperationException expected");
+                       } 
+                       catch (InvalidOperationException e) {
+                               //"ContractDescription 'IHaveZeroOperarationsContract' has zero operations; a contract must have at least one operation."
+                               StringAssert.Contains ("IHaveZeroOperarationsContract", e.Message);
+                       }
+                       finally {
+                               if (host.State == CommunicationState.Opened)
+                                       host.Close (); // It is to make sure to close unexpectedly opened host if the test fail.
+                       }
+               }
+
                [Test]
                public void AddServiceEndpoint4 ()
                {
@@ -210,6 +251,21 @@ namespace MonoTests.System.ServiceModel
                        host.AddServiceEndpoint ("ISuchTypeDoesNotExist", new BasicHttpBinding (), "rel");
                }
 
+               [Test]
+               public void AddServiceEndpoint7 ()
+               {
+                       ServiceHost host = new ServiceHost (typeof (Foo), new Uri ("http://localhost/echo"));
+                       var a = host.AddServiceEndpoint (typeof (Foo), new BasicHttpBinding (), "a");
+                       Console.WriteLine (a.Address);
+                       Assert.AreEqual ("http", a.Address.Uri.Scheme, "#1");
+                       Assert.AreEqual ("http://localhost/echo/a", a.Address.Uri.AbsoluteUri, "#2");
+
+                       var b = host.AddServiceEndpoint (typeof (Foo), new BasicHttpBinding (), "/b");
+                       Console.WriteLine (b.Address);
+                       Assert.AreEqual ("http", b.Address.Uri.Scheme, "#3");
+                       Assert.AreEqual ("http://localhost/echo/b", b.Address.Uri.AbsoluteUri, "#4");
+               }
+               
                [Test]
                [ExpectedException (typeof (InvalidOperationException))]
                public void AddServiceEndpointMexWithNoImpl ()
@@ -243,13 +299,14 @@ namespace MonoTests.System.ServiceModel
                [Test]
                public void InstanceWithNonSingletonMode ()
                {
+                       var ep = NetworkHelpers.LocalEphemeralEndPoint().ToString();
                        ServiceHost host = new ServiceHost (
                                new NonSingletonService ());
                        Assert.IsNotNull (host.Description.Behaviors.Find<ServiceBehaviorAttribute> ().GetWellKnownSingleton (), "premise1");
                        host.AddServiceEndpoint (
                                typeof (NonSingletonService),
                                new BasicHttpBinding (),
-                               new Uri ("http://localhost:37564/s1"));
+                               new Uri ("http://" + ep + "/s1"));
 
                        // in case Open() didn't fail, we need to close the host.
                        // And even if Close() caused the expected exception,
@@ -270,13 +327,14 @@ namespace MonoTests.System.ServiceModel
                [Test]
                public void InstanceWithSingletonMode ()
                {
+            var ep = NetworkHelpers.LocalEphemeralEndPoint().ToString();
                        SingletonService instance = new SingletonService ();
                        ServiceHost host = new ServiceHost (instance);
                        Assert.IsNotNull (host.Description.Behaviors.Find<ServiceBehaviorAttribute> ().GetWellKnownSingleton (), "#1");
                        host.AddServiceEndpoint (
                                typeof (SingletonService),
                                new BasicHttpBinding (),
-                               new Uri ("http://localhost:37564/s2"));
+                               new Uri ("http://" + ep + "/s2"));
 
                        // in case Open() didn't fail, we need to close the host.
                        // And even if Close() caused the expected exception,
@@ -313,6 +371,40 @@ namespace MonoTests.System.ServiceModel
                        [OperationContract]
                        string Echo (string source);
                }
+               
+               [ServiceContract]
+               interface IHoge
+               {
+                       [OperationContract]
+                       void DoX ();
+               }
+
+               [ServiceContract]
+               interface IFuga
+               {
+                       [OperationContract]
+                       void DoY ();
+               }
+
+               [ServiceContract]
+               interface IHaveZeroOperarationsContract
+               {
+                       string Echo (string source);
+               }
+
+               class ZeroOperationsImpl : IHaveZeroOperarationsContract
+               {
+                       public string Echo(string source)
+                       {
+                               return null;
+                       }
+               }
+
+               class HogeFuga : IHoge, IFuga
+               {
+                       public void DoX () {}
+                       public void DoY () {}
+               }
 
                class Baz : IBaz
                {