Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / class / System.ServiceModel / Test / System.ServiceModel / CallbackBehaviorAttributeTest.cs
1 //
2 // CallbackBehaviorAttributeTest.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2009 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.ObjectModel;
30 using System.IO;
31 using System.Linq;
32 using System.Net.Sockets;
33 using System.Reflection;
34 using System.ServiceModel;
35 using System.ServiceModel.Channels;
36 using System.ServiceModel.Description;
37 using System.ServiceModel.Dispatcher;
38 using System.Transactions;
39 using System.Threading;
40 using NUnit.Framework;
41
42 using MonoTests.Helpers;
43
44 namespace MonoTests.System.ServiceModel
45 {
46         [TestFixture]
47         public class CallbackBehaviorAttributeTest
48         {
49                 [Test]
50                 public void DefaultValues ()
51                 {
52                         var c = new CallbackBehaviorAttribute ();
53                         Assert.IsTrue (c.AutomaticSessionShutdown, "#1");
54                         Assert.AreEqual (ConcurrencyMode.Single, c.ConcurrencyMode, "#2");
55                         Assert.IsFalse (c.IgnoreExtensionDataObject, "#3");
56                         Assert.IsFalse (c.IncludeExceptionDetailInFaults, "#4");
57                         Assert.AreEqual (0x10000, c.MaxItemsInObjectGraph, "#5");
58                         Assert.AreEqual (IsolationLevel.Unspecified, c.TransactionIsolationLevel, "#6");
59                         Assert.IsNull (c.TransactionTimeout, "#7");
60                         Assert.IsTrue (c.UseSynchronizationContext, "#8");
61                         Assert.IsTrue (c.ValidateMustUnderstand, "#9");
62                 }
63
64                 [Test]
65                 public void AddBindingParameters ()
66                 {
67                         IEndpointBehavior eb = new CallbackBehaviorAttribute ();
68                         var cd = ContractDescription.GetContract (typeof (IFoo));
69                         var se = new ServiceEndpoint (cd);
70                         Assert.AreEqual (0, se.Behaviors.Count, "#1");
71                         var pc = new BindingParameterCollection ();
72                         eb.AddBindingParameters (se, pc);
73                         Assert.AreEqual (0, pc.Count, "#2");
74                         Assert.AreEqual (0, se.Behaviors.Count, "#3");
75                 }
76
77                 [Test]
78                 [ExpectedException (typeof (InvalidOperationException))]
79                 public void ApplyDispatchBehavior ()
80                 {
81                         // It cannot be applied to service endpoint dispatcher.
82                         IEndpointBehavior eb = new CallbackBehaviorAttribute () { ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false };
83                         var cd = ContractDescription.GetContract (typeof (IFoo));
84                         var se = new ServiceEndpoint (cd);
85                         var ed = new EndpointDispatcher (new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()), "IFoo", "urn:foo");
86                         eb.ApplyDispatchBehavior (se, ed);
87                 }
88
89                 [Test]
90                 [ExpectedException (typeof (InvalidOperationException))]
91                 public void ApplyClientBehaviorNonDuplex ()
92                 {
93                         // It must be applied to duplex callback runtime
94                         IEndpointBehavior eb = new CallbackBehaviorAttribute () { ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false };
95                         var cd = ContractDescription.GetContract (typeof (IFoo));
96                         var se = new ServiceEndpoint (cd);
97                         var ed = new EndpointDispatcher (new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()), "IFoo", "urn:foo");
98                         var cr = ed.DispatchRuntime.CallbackClientRuntime;
99                         eb.ApplyClientBehavior (se, cr);
100                 }
101
102                 /* There is no way that I can create ClientRuntime instance ...
103                 [Test]
104                 public void ApplyClientBehavior ()
105                 {
106                         IEndpointBehavior eb = new CallbackBehaviorAttribute () { ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false };
107                         var cd = ContractDescription.GetContract (typeof (IDuplexFoo));
108                         var se = new ServiceEndpoint (cd);
109                         var ed = new EndpointDispatcher (new EndpointAddress ("http://localhost:" + NetworkHelpers.FindFreePort ()), "IDuplexFoo", "urn:foo");
110                         var cr = ed.DispatchRuntime.CallbackClientRuntime;
111                         eb.ApplyClientBehavior (se, cr);
112                         Assert.IsFalse (cr.ValidateMustUnderstand, "#2.1");
113                         //Assert.IsFalse (cr.CallbackDispatchRuntime.ValidateMustUnderstand, "#2.2");
114                         Assert.AreEqual (1, se.Behaviors.Count, "#3");
115                 }
116                 */
117
118                 [ServiceContract]
119                 public interface IFoo
120                 {
121                         [OperationContract]
122                         string Join (string s1, string s2);
123                 }
124
125                 [ServiceContract (CallbackContract = typeof (IFoo))]
126                 public interface IDuplexFoo
127                 {
128                         [OperationContract]
129                         void Block (string s);
130                 }
131
132                 #region "bug #567672"
133                 [Test]
134                 [Category ("NotWorking")]
135                 public void CallbackExample1 ()
136                 {
137                         //Start service and use net.tcp binding
138                         ServiceHost eventServiceHost = new ServiceHost (typeof (GreetingsService));
139                         NetTcpBinding tcpBindingpublish = new NetTcpBinding ();
140                         tcpBindingpublish.Security.Mode = SecurityMode.None;
141                         eventServiceHost.AddServiceEndpoint (typeof (IGreetings), tcpBindingpublish, "net.tcp://localhost:8000/GreetingsService");
142                         var cd = eventServiceHost.Description.Endpoints [0].Contract;
143                         Assert.AreEqual (2, cd.Operations.Count, "Operations.Count");
144                         var send = cd.Operations.FirstOrDefault (od => od.Name == "SendMessage");
145                         var show = cd.Operations.FirstOrDefault (od => od.Name == "ShowMessage");
146                         Assert.IsNotNull (send, "OD:SendMessage");
147                         Assert.IsNotNull (show, "OD:ShowMessage");
148                         foreach (var md in send.Messages) {
149                                 if (md.Direction == MessageDirection.Input)
150                                         Assert.AreEqual ("http://tempuri.org/IGreetings/SendMessage", md.Action, "MD:SendMessage");
151                                 else
152                                         Assert.AreEqual ("http://tempuri.org/IGreetings/SendMessageResponse", md.Action, "MD:SendMessage");
153                         }
154                         foreach (var md in show.Messages) {
155                                 if (md.Direction == MessageDirection.Output)
156                                         Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessage", md.Action, "MD:ShowMessage");
157                                 else
158                                         Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessageResponse", md.Action, "MD:ShowMessage");
159                         }
160                         eventServiceHost.Open ();
161
162                         var chd = (ChannelDispatcher) eventServiceHost.ChannelDispatchers [0];
163                         Assert.IsNotNull (chd, "ChannelDispatcher");
164                         Assert.AreEqual (1, chd.Endpoints.Count, "ChannelDispatcher.Endpoints.Count");
165                         var ed = chd.Endpoints [0];
166                         var cr = ed.DispatchRuntime.CallbackClientRuntime;
167                         Assert.IsNotNull (cr, "CR");
168                         Assert.AreEqual (1, cr.Operations.Count, "CR.Operations.Count");
169                         Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessage", cr.Operations [0].Action, "ClientOperation.Action");
170
171                         //Create client proxy
172                         NetTcpBinding clientBinding = new NetTcpBinding ();
173                         clientBinding.Security.Mode = SecurityMode.None;
174                         EndpointAddress ep = new EndpointAddress ("net.tcp://localhost:8000/GreetingsService");
175                         ClientCallback cb = new ClientCallback ();
176                         IGreetings proxy = DuplexChannelFactory<IGreetings>.CreateChannel (new InstanceContext (cb), clientBinding, ep);
177
178                         //Call service
179                         proxy.SendMessage ();
180
181                         //Wait for callback - sort of hack, but better than using wait handle to possibly block tests.
182                         Thread.Sleep (2000);
183
184                         //Cleanup
185                         eventServiceHost.Close ();
186
187                         Assert.IsTrue (CallbackSent, "#1");
188                         Assert.IsTrue (CallbackReceived, "#2");
189                 }
190
191                 [Test]
192                 [Category ("NotWorking")]
193                 public void CallbackExample2 ()
194                 {
195                         //Start service and use net.tcp binding
196                         ServiceHost eventServiceHost = new ServiceHost (typeof (GreetingsService2));
197                         NetTcpBinding tcpBindingpublish = new NetTcpBinding ();
198                         tcpBindingpublish.Security.Mode = SecurityMode.None;
199                         eventServiceHost.AddServiceEndpoint (typeof (IGreetings2), tcpBindingpublish, "net.tcp://localhost:8000/GreetingsService2");
200                         eventServiceHost.Open ();
201
202                         //Create client proxy
203                         NetTcpBinding clientBinding = new NetTcpBinding ();
204                         clientBinding.Security.Mode = SecurityMode.None;
205                         EndpointAddress ep = new EndpointAddress ("net.tcp://localhost:8000/GreetingsService2");
206                         ClientCallback2 cb = new ClientCallback2 ();
207                         IGreetings2 proxy = DuplexChannelFactory<IGreetings2>.CreateChannel (new InstanceContext (cb), clientBinding, ep);
208
209                         //Call service
210                         proxy.SendMessage ();
211
212                         //Wait for callback - sort of hack, but better than using wait handle to possibly block tests.
213                         Thread.Sleep (2000);
214
215                         //Cleanup
216                         eventServiceHost.Close ();
217
218                         Assert.IsTrue (CallbackSent2, "#1");
219                         Assert.IsTrue (CallbackReceived2, "#2");
220                 }
221
222                 public static bool CallbackSent, CallbackReceived;
223
224                 //Service implementation
225                 [ServiceBehavior (ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
226                 public class GreetingsService : IGreetings
227                 {
228                         public void SendMessage ()
229                         {
230                                 //Make a callback
231                                 IGreetingsCallback clientCallback = OperationContext.Current.GetCallbackChannel<IGreetingsCallback> ();
232
233                                 clientCallback.ShowMessage ("Mono and WCF are GREAT!");
234                                 CallbackBehaviorAttributeTest.CallbackSent = true;
235                         }
236                 }
237
238                 // Client callback interface implementation
239                 [CallbackBehavior (ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
240                 public class ClientCallback : IGreetingsCallback
241                 {
242                         public void ShowMessage (string message)
243                         {
244                                 CallbackBehaviorAttributeTest.CallbackReceived = true;
245                         }
246                 }
247
248                 [ServiceContract (CallbackContract = typeof (IGreetingsCallback))]
249                 public interface IGreetings
250                 {
251                         [OperationContract (IsOneWay = true)]
252                         void SendMessage ();
253                 }
254
255                 [ServiceContract]
256                 public interface IGreetingsCallback
257                 {
258                         [OperationContract (IsOneWay = true)]
259                         void ShowMessage (string message);
260                 }
261
262                 public static bool CallbackSent2, CallbackReceived2;
263
264                 //Service implementation
265                 [ServiceBehavior (ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
266                 public class GreetingsService2 : IGreetings2
267                 {
268                         public void SendMessage ()
269                         {
270                                 //Make a callback
271                                 IGreetingsCallback2 clientCallback = OperationContext.Current.GetCallbackChannel<IGreetingsCallback2> ();
272
273                                 clientCallback.ShowMessage ("Mono and WCF are GREAT!");
274                                 CallbackBehaviorAttributeTest.CallbackSent2 = true;
275                         }
276                 }
277
278                 // Client callback interface implementation
279                 [CallbackBehavior (ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
280                 public class ClientCallback2 : IGreetingsCallback2
281                 {
282                         public void ShowMessage (string message)
283                         {
284                                 CallbackBehaviorAttributeTest.CallbackReceived2 = true;
285                         }
286                 }
287
288                 [ServiceContract (CallbackContract = typeof (IGreetingsCallback2))]
289                 public interface IGreetings2
290                 {
291                         [OperationContract (IsOneWay = false)]
292                         void SendMessage ();
293                 }
294
295                 [ServiceContract]
296                 public interface IGreetingsCallback2
297                 {
298                         [OperationContract (IsOneWay = false)]
299                         void ShowMessage (string message);
300                 }
301                 #endregion
302
303                 #region ConcurrencyMode testing
304
305                 ManualResetEvent wait_handle = new ManualResetEvent (false);
306
307                 [Test]
308                 [Category ("NotWorking")]
309                 public void ConcurrencyModeSingleAndCallbackInsideServiceMethod ()
310                 {
311                         var host = new ServiceHost (typeof (TestService));
312                         var binding = new NetTcpBinding ();
313                         binding.Security.Mode = SecurityMode.None;
314                         host.AddServiceEndpoint (typeof (ITestService), binding, new Uri ("net.tcp://localhost:18080"));
315                         host.Description.Behaviors.Find<ServiceDebugBehavior> ().IncludeExceptionDetailInFaults = true;
316                         host.Open ();
317
318                         try {
319                                 var cf = new DuplexChannelFactory<ITestService> (new TestCallback (), binding, new EndpointAddress ("net.tcp://localhost:18080"));
320                                 var ch = cf.CreateChannel ();
321                                 ch.DoWork ("test");
322
323                                 wait_handle.WaitOne (10000);
324                                 Assert.Fail ("should fail");
325                         } catch (FaultException) {
326                                 // expected.
327                         } finally {
328                                 Thread.Sleep (1000);
329                         }
330
331                         host.Close ();
332                 }
333
334                 [ServiceContract (CallbackContract = typeof (ITestCallback))]
335                 public interface ITestService
336                 {
337                         [OperationContract (IsOneWay = false)] // ConcurrencyMode error as long as IsOneWay == false.
338                         void DoWork (string name);
339                 }
340
341                 public interface ITestCallback
342                 {
343                         [OperationContract (IsOneWay = false)]
344                         void Report (string result);
345                 }
346
347                 public class TestService : ITestService
348                 {
349                         public void DoWork (string name)
350                         {
351                                 var cb = OperationContext.Current.GetCallbackChannel<ITestCallback> ();
352                                 cb.Report ("OK");
353                                 Assert.Fail ("callback should have failed");
354                         }
355                 }
356
357                 public class TestCallback : ITestCallback
358                 {
359                         public void Report (string result)
360                         {
361                                 Assert.Fail ("should not reach here");
362                         }
363                 }
364
365                 #endregion
366         }
367 }