2 // Author: Atsushi Enomoto <atsushi@ximian.com>
4 // Copyright (C) 2010 Novell, Inc (http://www.novell.com)
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 using System.Collections.Generic;
27 using System.Collections.ObjectModel;
29 using System.Net.Sockets;
30 using System.ServiceModel;
31 using System.ServiceModel.Channels;
32 using System.ServiceModel.Description;
33 using System.ServiceModel.Discovery;
34 using System.ServiceModel.Dispatcher;
35 using System.Threading;
36 using NUnit.Framework;
38 namespace MonoTests.System.ServiceModel.Discovery
41 public class IntegratedDiscoveryTest
43 void AssertTcpPortOpen (int port)
46 var l = new TcpListener (port);
49 } catch (Exception ex) {
50 Assert.Fail (String.Format ("TCP port {0} is not freed", port));
55 public void UseCase1 ()
57 RunCodeUnderDiscoveryHost1 (new Uri ("http://localhost:37564"), new Uri ("http://localhost:4949"), new Uri ("http://localhost:4989"), UseCase1Core);
58 AssertTcpPortOpen (4949);
59 AssertTcpPortOpen (4989);
60 AssertTcpPortOpen (37564);
63 void UseCase1Core (Uri serviceUri, AnnouncementEndpoint aEndpoint, DiscoveryEndpoint dEndpoint)
65 // actual service, announcing to 4989
66 var host = new ServiceHost (typeof (TestService));
67 var sdb = new ServiceDiscoveryBehavior ();
68 sdb.AnnouncementEndpoints.Add (aEndpoint);
69 host.Description.Behaviors.Add (sdb);
70 host.AddServiceEndpoint (typeof (ITestService), new BasicHttpBinding (), serviceUri);
72 // It does not start announcement very soon, so wait for a while.
75 // actual client, with DiscoveryClientBindingElement
76 var be = new DiscoveryClientBindingElement () { DiscoveryEndpointProvider = new SimpleDiscoveryEndpointProvider (dEndpoint) };
77 var clientBinding = new CustomBinding (new BasicHttpBinding ());
78 clientBinding.Elements.Insert (0, be);
79 var cf = new ChannelFactory<ITestService> (clientBinding, DiscoveryClientBindingElement.DiscoveryEndpointAddress);
80 var ch = cf.CreateChannel ();
81 Assert.AreEqual ("TEST", ch.Echo ("TEST"), "#1");
88 void RunCodeUnderDiscoveryHost1 (Uri serviceUri, Uri dHostUri, Uri aHostUri, Action<Uri,AnnouncementEndpoint,DiscoveryEndpoint> action)
90 // announcement service
91 var abinding = new CustomBinding (new HttpTransportBindingElement ());
92 var aAddress = new EndpointAddress (aHostUri);
93 var aEndpoint = new AnnouncementEndpoint (abinding, aAddress);
96 var dbinding = new CustomBinding (new HttpTransportBindingElement ());
97 var dAddress = new EndpointAddress (dHostUri);
98 var dEndpoint = new DiscoveryEndpoint (dbinding, dAddress);
99 // Without this, .NET rejects the host as if it had no service.
100 dEndpoint.IsSystemEndpoint = false;
102 // it internally hosts an AnnouncementService
103 using (var inst = new AnnouncementBoundDiscoveryService (aEndpoint)) {
104 var host = new ServiceHost (inst);
105 host.AddServiceEndpoint (dEndpoint);
108 action (serviceUri, aEndpoint, dEndpoint);
115 [Test] // Announcement: UDP, Discovery: HTTP
116 public void UseCase2 ()
118 RunCodeUnderDiscoveryHost2 (new Uri ("http://localhost:37564"), new Uri ("http://localhost:4949"), UseCase2Core);
119 AssertTcpPortOpen (4949);
120 AssertTcpPortOpen (37564);
123 void UseCase2Core (Uri serviceUri, AnnouncementEndpoint aEndpoint, DiscoveryEndpoint dEndpoint)
125 // actual service, announcing to UDP
126 var host = new ServiceHost (typeof (TestService));
127 var sdb = new ServiceDiscoveryBehavior ();
128 sdb.AnnouncementEndpoints.Add (aEndpoint);
129 host.Description.Behaviors.Add (sdb);
130 host.AddServiceEndpoint (typeof (ITestService), new BasicHttpBinding (), serviceUri);
132 // It does not start announcement very soon, so wait for a while.
135 // actual client, with DiscoveryClientBindingElement
136 var be = new DiscoveryClientBindingElement () { DiscoveryEndpointProvider = new SimpleDiscoveryEndpointProvider (dEndpoint) };
137 var clientBinding = new CustomBinding (new BasicHttpBinding ());
138 clientBinding.Elements.Insert (0, be);
139 var cf = new ChannelFactory<ITestService> (clientBinding, DiscoveryClientBindingElement.DiscoveryEndpointAddress);
140 var ch = cf.CreateChannel ();
141 Assert.AreEqual ("TEST", ch.Echo ("TEST"), "#1");
147 void RunCodeUnderDiscoveryHost2 (Uri serviceUri, Uri dHostUri, Action<Uri,AnnouncementEndpoint,DiscoveryEndpoint> action)
149 // announcement service
150 var aEndpoint = new UdpAnnouncementEndpoint (new Uri ("soap.udp://239.255.255.250:3802/"));
153 var dbinding = new CustomBinding (new HttpTransportBindingElement ());
154 var dAddress = new EndpointAddress (dHostUri);
155 var dEndpoint = new DiscoveryEndpoint (dbinding, dAddress);
156 // Without this, .NET rejects the host as if it had no service.
157 dEndpoint.IsSystemEndpoint = false;
159 // it internally hosts an AnnouncementService
160 using (var inst = new AnnouncementBoundDiscoveryService (aEndpoint)) {
161 var host = new ServiceHost (inst);
162 host.AddServiceEndpoint (dEndpoint);
165 action (serviceUri, aEndpoint, dEndpoint);
173 public void UseCase3 ()
175 RunCodeUnderDiscoveryHost3 (new Uri ("http://localhost:37564"), new Uri ("http://localhost:4989"), UseCase3Core);
176 AssertTcpPortOpen (4989);
177 AssertTcpPortOpen (37564);
180 void UseCase3Core (Uri serviceUri, AnnouncementEndpoint aEndpoint, DiscoveryEndpoint dEndpoint)
182 // actual service, announcing to 4989
183 var host = new ServiceHost (typeof (TestService));
184 var sdb = new ServiceDiscoveryBehavior ();
185 sdb.AnnouncementEndpoints.Add (aEndpoint);
186 host.Description.Behaviors.Add (sdb);
187 host.AddServiceEndpoint (typeof (ITestService), new BasicHttpBinding (), serviceUri);
189 // It does not start announcement very soon, so wait for a while.
192 // actual client, with DiscoveryClientBindingElement
193 var be = new DiscoveryClientBindingElement () { DiscoveryEndpointProvider = new SimpleDiscoveryEndpointProvider (dEndpoint) };
194 var clientBinding = new CustomBinding (new BasicHttpBinding ());
195 clientBinding.Elements.Insert (0, be);
196 var cf = new ChannelFactory<ITestService> (clientBinding, DiscoveryClientBindingElement.DiscoveryEndpointAddress);
197 var ch = cf.CreateChannel ();
198 Assert.AreEqual ("TEST", ch.Echo ("TEST"), "#1");
205 void RunCodeUnderDiscoveryHost3 (Uri serviceUri, Uri aHostUri, Action<Uri,AnnouncementEndpoint,DiscoveryEndpoint> action)
207 // announcement service
208 var abinding = new CustomBinding (new HttpTransportBindingElement ());
209 var aAddress = new EndpointAddress (aHostUri);
210 var aEndpoint = new AnnouncementEndpoint (abinding, aAddress);
213 var dEndpoint = new UdpDiscoveryEndpoint (DiscoveryVersion.WSDiscovery11, new Uri ("soap.udp://239.255.255.250:3802/"));
214 // Without this, .NET rejects the host as if it had no service.
215 dEndpoint.IsSystemEndpoint = false;
217 // it internally hosts an AnnouncementService
218 using (var inst = new AnnouncementBoundDiscoveryService (aEndpoint)) {
219 var host = new ServiceHost (inst);
220 host.AddServiceEndpoint (dEndpoint);
223 action (serviceUri, aEndpoint, dEndpoint);
230 class SimpleDiscoveryEndpointProvider : DiscoveryEndpointProvider
232 public SimpleDiscoveryEndpointProvider (DiscoveryEndpoint endpoint)
234 this.endpoint = endpoint;
237 DiscoveryEndpoint endpoint;
239 public override DiscoveryEndpoint GetDiscoveryEndpoint ()