2455698998feacb6f4e06bf73e48f3f8334a212c
[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 namespace MonoTests.System.ServiceModel
43 {
44         [TestFixture]
45         public class CallbackBehaviorAttributeTest
46         {
47                 [Test]
48                 public void DefaultValues ()
49                 {
50                         var c = new CallbackBehaviorAttribute ();
51                         Assert.IsTrue (c.AutomaticSessionShutdown, "#1");
52                         Assert.AreEqual (ConcurrencyMode.Single, c.ConcurrencyMode, "#2");
53                         Assert.IsFalse (c.IgnoreExtensionDataObject, "#3");
54                         Assert.IsFalse (c.IncludeExceptionDetailInFaults, "#4");
55                         Assert.AreEqual (0x10000, c.MaxItemsInObjectGraph, "#5");
56                         Assert.AreEqual (IsolationLevel.Unspecified, c.TransactionIsolationLevel, "#6");
57                         Assert.IsNull (c.TransactionTimeout, "#7");
58                         Assert.IsTrue (c.UseSynchronizationContext, "#8");
59                         Assert.IsTrue (c.ValidateMustUnderstand, "#9");
60                 }
61
62                 [Test]
63                 public void AddBindingParameters ()
64                 {
65                         IEndpointBehavior eb = new CallbackBehaviorAttribute ();
66                         var cd = ContractDescription.GetContract (typeof (IFoo));
67                         var se = new ServiceEndpoint (cd);
68                         Assert.AreEqual (0, se.Behaviors.Count, "#1");
69                         var pc = new BindingParameterCollection ();
70                         eb.AddBindingParameters (se, pc);
71                         Assert.AreEqual (0, pc.Count, "#2");
72                         Assert.AreEqual (0, se.Behaviors.Count, "#3");
73                 }
74
75                 [Test]
76                 [ExpectedException (typeof (InvalidOperationException))]
77                 public void ApplyDispatchBehavior ()
78                 {
79                         // It cannot be applied to service endpoint dispatcher.
80                         IEndpointBehavior eb = new CallbackBehaviorAttribute () { ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false };
81                         var cd = ContractDescription.GetContract (typeof (IFoo));
82                         var se = new ServiceEndpoint (cd);
83                         var ed = new EndpointDispatcher (new EndpointAddress ("http://localhost:37564"), "IFoo", "urn:foo");
84                         eb.ApplyDispatchBehavior (se, ed);
85                 }
86
87                 [Test]
88                 [ExpectedException (typeof (InvalidOperationException))]
89                 public void ApplyClientBehaviorNonDuplex ()
90                 {
91                         // It must be applied to duplex callback runtime
92                         IEndpointBehavior eb = new CallbackBehaviorAttribute () { ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false };
93                         var cd = ContractDescription.GetContract (typeof (IFoo));
94                         var se = new ServiceEndpoint (cd);
95                         var ed = new EndpointDispatcher (new EndpointAddress ("http://localhost:37564"), "IFoo", "urn:foo");
96                         var cr = ed.DispatchRuntime.CallbackClientRuntime;
97                         eb.ApplyClientBehavior (se, cr);
98                 }
99
100                 /* There is no way that I can create ClientRuntime instance ...
101                 [Test]
102                 public void ApplyClientBehavior ()
103                 {
104                         IEndpointBehavior eb = new CallbackBehaviorAttribute () { ConcurrencyMode = ConcurrencyMode.Multiple, ValidateMustUnderstand = false };
105                         var cd = ContractDescription.GetContract (typeof (IDuplexFoo));
106                         var se = new ServiceEndpoint (cd);
107                         var ed = new EndpointDispatcher (new EndpointAddress ("http://localhost:37564"), "IDuplexFoo", "urn:foo");
108                         var cr = ed.DispatchRuntime.CallbackClientRuntime;
109                         eb.ApplyClientBehavior (se, cr);
110                         Assert.IsFalse (cr.ValidateMustUnderstand, "#2.1");
111                         //Assert.IsFalse (cr.CallbackDispatchRuntime.ValidateMustUnderstand, "#2.2");
112                         Assert.AreEqual (1, se.Behaviors.Count, "#3");
113                 }
114                 */
115
116                 [ServiceContract]
117                 public interface IFoo
118                 {
119                         [OperationContract]
120                         string Join (string s1, string s2);
121                 }
122
123                 [ServiceContract (CallbackContract = typeof (IFoo))]
124                 public interface IDuplexFoo
125                 {
126                         [OperationContract]
127                         void Block (string s);
128                 }
129
130                 #region "bug #567672"
131                 [Test]
132                 public void CallbackExample1 ()
133                 {
134                         //Start service and use net.tcp binding
135                         ServiceHost eventServiceHost = new ServiceHost (typeof (GreetingsService));
136                         NetTcpBinding tcpBindingpublish = new NetTcpBinding ();
137                         tcpBindingpublish.Security.Mode = SecurityMode.None;
138                         eventServiceHost.AddServiceEndpoint (typeof (IGreetings), tcpBindingpublish, "net.tcp://localhost:8000/GreetingsService");
139                         var cd = eventServiceHost.Description.Endpoints [0].Contract;
140                         Assert.AreEqual (2, cd.Operations.Count, "Operations.Count");
141                         var send = cd.Operations.FirstOrDefault (od => od.Name == "SendMessage");
142                         var show = cd.Operations.FirstOrDefault (od => od.Name == "ShowMessage");
143                         Assert.IsNotNull (send, "OD:SendMessage");
144                         Assert.IsNotNull (show, "OD:ShowMessage");
145                         foreach (var md in send.Messages) {
146                                 if (md.Direction == MessageDirection.Input)
147                                         Assert.AreEqual ("http://tempuri.org/IGreetings/SendMessage", md.Action, "MD:SendMessage");
148                                 else
149                                         Assert.AreEqual ("http://tempuri.org/IGreetings/SendMessageResponse", md.Action, "MD:SendMessage");
150                         }
151                         foreach (var md in show.Messages) {
152                                 if (md.Direction == MessageDirection.Output)
153                                         Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessage", md.Action, "MD:ShowMessage");
154                                 else
155                                         Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessageResponse", md.Action, "MD:ShowMessage");
156                         }
157                         eventServiceHost.Open ();
158
159                         var chd = (ChannelDispatcher) eventServiceHost.ChannelDispatchers [0];
160                         Assert.IsNotNull (chd, "ChannelDispatcher");
161                         Assert.AreEqual (1, chd.Endpoints.Count, "ChannelDispatcher.Endpoints.Count");
162                         var ed = chd.Endpoints [0];
163                         var cr = ed.DispatchRuntime.CallbackClientRuntime;
164                         Assert.IsNotNull (cr, "CR");
165                         Assert.AreEqual (1, cr.Operations.Count, "CR.Operations.Count");
166                         Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessage", cr.Operations [0].Action, "ClientOperation.Action");
167
168                         //Create client proxy
169                         NetTcpBinding clientBinding = new NetTcpBinding ();
170                         clientBinding.Security.Mode = SecurityMode.None;
171                         EndpointAddress ep = new EndpointAddress ("net.tcp://localhost:8000/GreetingsService");
172                         ClientCallback cb = new ClientCallback ();
173                         IGreetings proxy = DuplexChannelFactory<IGreetings>.CreateChannel (new InstanceContext (cb), clientBinding, ep);
174
175                         //Call service
176                         proxy.SendMessage ();
177
178                         //Wait for callback - sort of hack, but better than using wait handle to possibly block tests.
179                         Thread.Sleep (1000);
180
181                         //Cleanup
182                         eventServiceHost.Close ();
183
184                         Assert.IsTrue (CallbackSent, "#1");
185                         Assert.IsTrue (CallbackReceived, "#2");
186                 }
187
188                 public static bool CallbackSent, CallbackReceived;
189
190                 //Service implementation
191                 [ServiceBehavior (ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
192                 public class GreetingsService : IGreetings
193                 {
194                         public void SendMessage ()
195                         {
196                                 //Make a callback
197                                 IGreetingsCallback clientCallback = OperationContext.Current.GetCallbackChannel<IGreetingsCallback> ();
198
199                                 clientCallback.ShowMessage ("Mono and WCF are GREAT!");
200                                 CallbackBehaviorAttributeTest.CallbackSent = true;
201                         }
202                 }
203
204                 // Client callback interface implementation
205                 [CallbackBehavior (ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
206                 public class ClientCallback : IGreetingsCallback
207                 {
208                         public void ShowMessage (string message)
209                         {
210                                 CallbackBehaviorAttributeTest.CallbackReceived = true;
211                         }
212                 }
213
214                 [ServiceContract (CallbackContract = typeof (IGreetingsCallback))]
215                 public interface IGreetings
216                 {
217                         [OperationContract (IsOneWay = true)]
218                         void SendMessage ();
219                 }
220
221                 [ServiceContract]
222                 public interface IGreetingsCallback
223                 {
224                         [OperationContract (IsOneWay = true)]
225                         void ShowMessage (string message);
226                 }
227                 #endregion
228         }
229 }