2 // CallbackBehaviorAttributeTest.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2009 Novell, Inc. http://www.novell.com
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
29 using System.Collections.ObjectModel;
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;
42 namespace MonoTests.System.ServiceModel
45 public class CallbackBehaviorAttributeTest
48 public void DefaultValues ()
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");
63 public void AddBindingParameters ()
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");
76 [ExpectedException (typeof (InvalidOperationException))]
77 public void ApplyDispatchBehavior ()
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);
88 [ExpectedException (typeof (InvalidOperationException))]
89 public void ApplyClientBehaviorNonDuplex ()
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);
100 /* There is no way that I can create ClientRuntime instance ...
102 public void ApplyClientBehavior ()
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");
117 public interface IFoo
120 string Join (string s1, string s2);
123 [ServiceContract (CallbackContract = typeof (IFoo))]
124 public interface IDuplexFoo
127 void Block (string s);
130 #region "bug #567672"
132 public void CallbackExample1 ()
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");
149 Assert.AreEqual ("http://tempuri.org/IGreetings/SendMessageResponse", md.Action, "MD:SendMessage");
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");
155 Assert.AreEqual ("http://tempuri.org/IGreetings/ShowMessageResponse", md.Action, "MD:ShowMessage");
157 eventServiceHost.Open ();
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");
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);
176 proxy.SendMessage ();
178 //Wait for callback - sort of hack, but better than using wait handle to possibly block tests.
182 eventServiceHost.Close ();
184 Assert.IsTrue (CallbackSent, "#1");
185 Assert.IsTrue (CallbackReceived, "#2");
188 public static bool CallbackSent, CallbackReceived;
190 //Service implementation
191 [ServiceBehavior (ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
192 public class GreetingsService : IGreetings
194 public void SendMessage ()
197 IGreetingsCallback clientCallback = OperationContext.Current.GetCallbackChannel<IGreetingsCallback> ();
199 clientCallback.ShowMessage ("Mono and WCF are GREAT!");
200 CallbackBehaviorAttributeTest.CallbackSent = true;
204 // Client callback interface implementation
205 [CallbackBehavior (ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
206 public class ClientCallback : IGreetingsCallback
208 public void ShowMessage (string message)
210 CallbackBehaviorAttributeTest.CallbackReceived = true;
214 [ServiceContract (CallbackContract = typeof (IGreetingsCallback))]
215 public interface IGreetings
217 [OperationContract (IsOneWay = true)]
222 public interface IGreetingsCallback
224 [OperationContract (IsOneWay = true)]
225 void ShowMessage (string message);