1 //
2 // DispatchRuntimeTest.cs
3 //
4 // Author:
5 //	Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2006 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 #if !MOBILE && !XAMMAC_4_5
29 using System;
30 using System.Collections.Generic;
31 using System.Runtime.Serialization;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.ServiceModel.Description;
35 using System.ServiceModel.Dispatcher;
36 using System.ServiceModel.Security;
37 using System.Xml;
38 using NUnit.Framework;
39 using System.Collections.ObjectModel;
40 using SMMessage = System.ServiceModel.Channels.Message;
41 using System.Threading;
42 
43 using MonoTests.Helpers;
44 
45 namespace MonoTests.System.ServiceModel.Dispatcher
46 {
47 	[TestFixture]
48 	public class DispatchRuntimeTest
49 	{
50 		[Test]
TestConstructor()51 		public void TestConstructor ()
52 		{
53 			// This test is rather to just detect implementation
54 			// differences than digging in-depth meanings, so feel
55 			// free to change if MS implementation does not make
56 			// sense.
57 			DispatchRuntime r = new EndpointDispatcher (
58 				new EndpointAddress ("http://localhost:30158"), "IFoo", "urn:foo").DispatchRuntime;
59 			Assert.AreEqual (AuditLogLocation.Default,
60 					 r.SecurityAuditLogLocation, "#1");
61 
62 			Assert.IsTrue (r.AutomaticInputSessionShutdown, "#2");
63 			Assert.IsNotNull (r.CallbackClientRuntime, "#3");
64 			Assert.IsNull (r.ExternalAuthorizationPolicies, "#4");
65 			Assert.IsFalse (r.IgnoreTransactionMessageProperty, "#5");
66 			Assert.IsFalse (r.ImpersonateCallerForAllOperations, "#6");
67 			Assert.AreEqual (0, r.InputSessionShutdownHandlers.Count, "#7");
68 			Assert.AreEqual (0, r.InstanceContextInitializers.Count, "#8");
69 			//Assert.AreEqual (0, r.InstanceContextLifetimes.Count, "#9");
70 			Assert.IsNull (r.InstanceProvider, "#10");
71 			Assert.IsNull (r.InstanceContextProvider, "#10-2");
72 			Assert.AreEqual (AuditLevel.None,
73 					 r.MessageAuthenticationAuditLevel, "#11");
74 			Assert.AreEqual (0, r.MessageInspectors.Count, "#12");
75 			Assert.AreEqual (0, r.Operations.Count, "#13");
76 			Assert.IsNull (r.OperationSelector, "#14");
77 			// This is silly, but anyways there will be similar
78 			// functionality that just represents unix "Groups".
79 			Assert.AreEqual (PrincipalPermissionMode.UseWindowsGroups,
80 					 r.PrincipalPermissionMode, "#15");
81 			Assert.IsFalse (r.ReleaseServiceInstanceOnTransactionComplete, "#16");
82 			Assert.IsNull (r.RoleProvider, "#17");
83 			Assert.AreEqual (AuditLevel.None, r.ServiceAuthorizationAuditLevel, "#18");
84 			Assert.IsNull (r.ServiceAuthorizationManager, "#19");
85 			Assert.IsTrue (r.SuppressAuditFailure, "#20");
86 			Assert.IsNull (r.SynchronizationContext, "#21");
87 			Assert.IsFalse (r.TransactionAutoCompleteOnSessionClose, "#22");
88 			Assert.IsNull (r.Type, "#23");
89 			Assert.IsNotNull (r.UnhandledDispatchOperation, "#24");
90 			DispatchOperation udo = r.UnhandledDispatchOperation;
91 			Assert.AreEqual ("*", udo.Name, "#24-2");
92 			Assert.AreEqual ("*", udo.Action, "#24-3");
93 			Assert.AreEqual ("*", udo.ReplyAction, "#24-4");
94 			Assert.IsFalse (udo.IsOneWay, "#24-5");
95 		}
96 
97 		[Test]
TestInstanceBehavior1()98 		public void TestInstanceBehavior1 ()
99 		{
100 
101 			Result res = new Result ();
102 			MessageInspectBehavior b = new MessageInspectBehavior ();
103 			b.instanceCtxInitializer = new MyInstanceContextInitializer (res);
104 			b.instanceCtxProvider = new MyInstanceContextProvider (null, res);
105 			//b.instanceProvider = new MyInstanceProvider (null, res);
106 			b.msgInspect = new MyMessageInspector (res);
107 			string expected = "GetExistingInstanceContext , InitializeInstanceContext , OperationContext , InstanceContext = Opening , Initialize , OperationContext , InstanceContext = Opening , AfterReceiveRequest , OperationContext , InstanceContext = Opened , BeforeSendReply , OperationContext , InstanceContext = Opened , IsIdle , OperationContext , InstanceContext = Opened , NotifyIdle , OperationContext , InstanceContext = Opened , ";
108 			TestInstanceBehavior (b, expected, res, 1);
109 			Assert.IsTrue (res.Done, "done");
110 		}
111 
112 		[Test]
TestInstanceBehavior2()113 		public void TestInstanceBehavior2 ()
114 		{
115 			Result res = new Result ();
116 			MessageInspectBehavior b = new MessageInspectBehavior ();
117 			b.instanceCtxInitializer = new MyInstanceContextInitializer (res);
118 			b.instanceCtxProvider = new MyInstanceContextProvider (null, res);
119 			b.instanceProvider = new MyInstanceProvider (new AllActions (res), res);
120 			b.msgInspect = new MyMessageInspector (res);
121 			string expected = "GetExistingInstanceContext , InitializeInstanceContext , OperationContext , InstanceContext = Opening , Initialize , OperationContext , InstanceContext = Opening , AfterReceiveRequest , OperationContext , InstanceContext = Opened , GetInstance1 , OperationContext , InstanceContext = Opened , BeforeSendReply , OperationContext , InstanceContext = Opened , ReleaseInstance , OperationContext , InstanceContext = Opened , IsIdle , OperationContext , InstanceContext = Opened , NotifyIdle , OperationContext , InstanceContext = Opened , ";
122 			TestInstanceBehavior (b, expected, res, 1);
123 			Assert.IsTrue (res.Done, "done");
124 		}
125 
126 		[Test]
TestInstanceBehavior3()127 		public void TestInstanceBehavior3 ()
128 		{
129 			Result res = new Result ();
130 			MessageInspectBehavior b = new MessageInspectBehavior ();
131 			b.instanceCtxInitializer = new MyInstanceContextInitializer (res);
132 
133 			InstanceContext c = new InstanceContext (new AllActions (res));
134 
135 			b.instanceCtxProvider = new MyInstanceContextProvider (c, res);
136 			b.instanceProvider = new MyInstanceProvider (new AllActions (res), res);
137 			b.msgInspect = new MyMessageInspector (res);
138 			string expected = "GetExistingInstanceContext , InitializeInstanceContext , OperationContext , InstanceContext = Opening , Initialize , OperationContext , InstanceContext = Opening , AfterReceiveRequest , OperationContext , InstanceContext = Opened , BeforeSendReply , OperationContext , InstanceContext = Opened , ";
139 			TestInstanceBehavior (b, expected, res, 1);					Assert.IsTrue (res.Done, "done");
140 		}
141 
142 		[Test]
TestInstanceBehavior4()143 		public void TestInstanceBehavior4 ()
144 		{
145 			Result res = new Result ();
146 			MessageInspectBehavior b = new MessageInspectBehavior ();
147 			b.instanceCtxInitializer = new MyInstanceContextInitializer (res);
148 
149 			b.instanceCtxProvider = new MyInstanceContextProvider (null, res);
150 			b.instanceProvider = new MyInstanceProvider (new AllActions (res), res);
151 			b.msgInspect = new MyMessageInspector (res);
152 			string expected = "GetExistingInstanceContext , InitializeInstanceContext , OperationContext , InstanceContext = Opening , Initialize , OperationContext , InstanceContext = Opening , AfterReceiveRequest , OperationContext , InstanceContext = Opened , GetInstance1 , OperationContext , InstanceContext = Opened , BeforeSendReply , OperationContext , InstanceContext = Opened , ReleaseInstance , OperationContext , InstanceContext = Opened , IsIdle , OperationContext , InstanceContext = Opened , NotifyIdle , OperationContext , InstanceContext = Opened , GetExistingInstanceContext , InitializeInstanceContext , OperationContext , InstanceContext = Opening , Initialize , OperationContext , InstanceContext = Opening , AfterReceiveRequest , OperationContext , InstanceContext = Opened , GetInstance1 , OperationContext , InstanceContext = Opened , BeforeSendReply , OperationContext , InstanceContext = Opened , ReleaseInstance , OperationContext , InstanceContext = Opened , IsIdle , OperationContext , InstanceContext = Opened , NotifyIdle , OperationContext , InstanceContext = Opened , ";
153 			TestInstanceBehavior (b, expected, res, 2);					Assert.IsTrue (res.Done, "done");
154 		}
155 
TestInstanceBehavior(MessageInspectBehavior b, string expected, Result actual, int invocations)156 		void TestInstanceBehavior (MessageInspectBehavior b, string expected, Result actual, int invocations)
157 		{
158 			var port = NetworkHelpers.FindFreePort ();
159 			ServiceHost h = new ServiceHost (typeof (AllActions), new Uri ("http://localhost:" + port));
160 			try {
161 				h.AddServiceEndpoint (typeof (IAllActions).FullName, new BasicHttpBinding (), "AllActions");
162 				h.Description.Behaviors.Add (b);
163 				ServiceDebugBehavior db = h.Description.Behaviors.Find<ServiceDebugBehavior> ();
164 				db.IncludeExceptionDetailInFaults = true;
165 				h.Open ();
166 				foreach (ChannelDispatcher cd in h.ChannelDispatchers) {
167 					foreach (var ed in cd.Endpoints) {
168 						if (ed.ContractName == "IHttpGetHelpPageAndMetadataContract")
169 							continue;
170 						Assert.AreEqual (typeof (AllActions), ed.DispatchRuntime.Type, "Type property: " + ed.ContractName);
171 					}
172 				}
173 				AllActionsProxy p = new AllActionsProxy (new BasicHttpBinding () { SendTimeout = TimeSpan.FromSeconds (5), ReceiveTimeout = TimeSpan.FromSeconds (5) }, new EndpointAddress ("http://localhost:" + port + "/AllActions"));
174 
175 				for (int i = 0; i < invocations; ++i)
176 					p.Get (10);
177 				p.Close ();
178 
179 				//let ther server finish his work
180 				Thread.Sleep (100);
181 				Assert.AreEqual (expected, actual.string_res);
182 				actual.Done = true;
183 			}
184 			finally {
185 				h.Close ();
186 			}
187 		}
188 	}
189 
190 
191 #region helpers
192 
193 	#region message inspectors
194 
195 	public class MessageInspectBehavior : IServiceBehavior
196 	{
197 		public MyMessageInspector msgInspect;
198 		public MyInstanceContextProvider instanceCtxProvider;
199 		public MyInstanceProvider instanceProvider;
200 		public MyInstanceContextInitializer instanceCtxInitializer;
201 
AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)202 		public void AddBindingParameters (ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) {
203 
204 		}
205 
ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)206 		public void ApplyDispatchBehavior (ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
207 			ChannelDispatcher d = serviceHostBase.ChannelDispatchers [0] as ChannelDispatcher;
208 			d.Endpoints [0].DispatchRuntime.MessageInspectors.Add (msgInspect);
209 			d.Endpoints [0].DispatchRuntime.InstanceContextProvider = instanceCtxProvider;
210 			d.Endpoints [0].DispatchRuntime.InstanceProvider = instanceProvider;
211 			d.Endpoints [0].DispatchRuntime.InstanceContextInitializers.Add (instanceCtxInitializer);
212 		}
213 
Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)214 		public void Validate (ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
215 
216 		}
217 	}
218 
219 	public class MyMessageInspector : IDispatchMessageInspector
220 	{
221 		Result res;
222 
MyMessageInspector(Result result)223 		public MyMessageInspector (Result result) {
224 			res = result;
225 		}
226 		#region IDispatchMessageInspector Members
227 
AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)228 		public object AfterReceiveRequest (ref Message request, IClientChannel channel, InstanceContext instanceContext) {
229 			res.string_res += "AfterReceiveRequest , ";
230 			res.AddCurrentOperationContextInfo ();
231 			return null;
232 		}
233 
BeforeSendReply(ref Message reply, object correlationState)234 		public void BeforeSendReply (ref Message reply, object correlationState) {
235 			res.string_res += "BeforeSendReply , ";
236 			res.AddCurrentOperationContextInfo ();
237 		}
238 
239 		#endregion
240 	}
241 
242 	#endregion
243 
244 	#region InstanceProvider
245 
246 	public class MyInstanceProvider : IInstanceProvider
247 	{
248 		object instance;
249 		Result res;
250 
MyInstanceProvider(object obj, Result result)251 		public MyInstanceProvider (object obj, Result result) {
252 			instance = obj;
253 			res = result;
254 		}
255 
256 		#region IInstanceProvider Members
257 
GetInstance(InstanceContext instanceContext, Message message)258 		public object GetInstance (InstanceContext instanceContext, Message message) {
259 			res.string_res += "GetInstance1 , ";
260 			res.AddCurrentOperationContextInfo ();
261 			return instance;
262 		}
263 
GetInstance(InstanceContext instanceContext)264 		public object GetInstance (InstanceContext instanceContext) {
265 			res.string_res += "GetInstance2 , ";
266 			res.AddCurrentOperationContextInfo ();
267 			return instance;
268 		}
269 
ReleaseInstance(InstanceContext instanceContext, object instance)270 		public void ReleaseInstance (InstanceContext instanceContext, object instance) {
271 			res.string_res += "ReleaseInstance , ";
272 			res.AddCurrentOperationContextInfo ();
273 		}
274 
275 		#endregion
276 	}
277 
278 	#endregion
279 
280 	#region InstanceContextProvider
281 
282 	public class MyInstanceContextProvider : IInstanceContextProvider
283 	{
284 
285 		InstanceContext existing;
286 		Result res;
287 
MyInstanceContextProvider(InstanceContext exist, Result result)288 		public MyInstanceContextProvider (InstanceContext exist, Result result) {
289 			existing = exist;
290 			res = result;
291 		}
292 
293 		#region IInstanceContextProvider Members
294 
GetExistingInstanceContext(Message message, IContextChannel channel)295 		public InstanceContext GetExistingInstanceContext (Message message, IContextChannel channel) {
296 			res.string_res += "GetExistingInstanceContext , ";
297 			res.AddCurrentOperationContextInfo ();
298 			return existing;
299 		}
300 
InitializeInstanceContext(InstanceContext instanceContext, Message message, IContextChannel channel)301 		public void InitializeInstanceContext (InstanceContext instanceContext, Message message, IContextChannel channel) {
302 			res.string_res += "InitializeInstanceContext , ";
303 			res.AddCurrentOperationContextInfo ();
304 		}
305 
IsIdle(InstanceContext instanceContext)306 		public bool IsIdle (InstanceContext instanceContext) {
307 			res.string_res += "IsIdle , ";
308 			res.AddCurrentOperationContextInfo ();
309 			return false;
310 		}
311 
NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext)312 		public void NotifyIdle (InstanceContextIdleCallback callback, InstanceContext instanceContext) {
313 			res.string_res += "NotifyIdle , ";
314 			res.AddCurrentOperationContextInfo ();
315 		}
316 
317 		#endregion
318 	}
319 
320 	#endregion
321 
322 	#region InstanceContextInitializer
323 
324 	public class MyInstanceContextInitializer : IInstanceContextInitializer
325 	{
326 		Result res;
327 
MyInstanceContextInitializer(Result result)328 		public MyInstanceContextInitializer (Result result) {
329 			res = result;
330 		}
331 
Initialize(InstanceContext instanceContext, Message message)332 		public void Initialize (InstanceContext instanceContext, Message message) {
333 			res.string_res += "Initialize , ";
334 			res.AddCurrentOperationContextInfo ();
335 		}
336 	}
337 
338 	#endregion
339 
340 	#region Helpers
341 
342 	public class Result
343 	{
344 		public bool Done;
345 		public string string_res = "";
346 
AddCurrentOperationContextInfo()347 		public void AddCurrentOperationContextInfo()
348 		{
349 			if (OperationContext.Current != null) {
350 				string_res += "OperationContext , ";
351 				if (OperationContext.Current.InstanceContext != null) {
352 					string_res += ("InstanceContext = " + OperationContext.Current.InstanceContext.State + " , ");
353 					//if (OperationContext.Current.InstanceContext != null)
354 					//    string_res += ("Instance = " + OperationContext.Current.InstanceContext.GetServiceInstance () + " , ");
355 				}
356 			}
357 		}
358 	}
359 
360 	class AllActions : IAllActions, IDisposable
361 	{
362 		Result res;
363 
AllActions()364 		public AllActions () { }
365 
AllActions(Result result)366 		public AllActions (Result result) {
367 			res = result;
368 		}
369 
370 		[OperationBehavior (ReleaseInstanceMode = ReleaseInstanceMode.BeforeAndAfterCall)]
Get(int i)371 		public int Get(int i)
372 		{
373 			return i;
374 		}
375 
Dispose()376 		public void Dispose () {
377 			if (res != null)
378 				res.string_res += "Disposed , ";
379 		}
380 	}
381 
382 	[ServiceContract (Namespace = "http://MonoTests.System.ServiceModel.Dispatcher")]
383 	public interface IAllActions
384 	{
385 		[OperationContract]
Get(int i)386 		int Get(int i);
387 	}
388 
389 	#endregion
390 
391 	#region ClientProxy
392 
393 	public class AllActionsProxy : ClientBase<IAllActions>, IAllActions
394 	{
AllActionsProxy(Binding binding, EndpointAddress remoteAddress)395 		public AllActionsProxy (Binding binding, EndpointAddress remoteAddress) :
396 			base (binding, remoteAddress)
397 		{
398 		}
399 
Get(int i)400 		public int Get (int i) {
401 			return base.Channel.Get (i);
402 		}
403 	}
404 
405 	#endregion
406 #endregion
407 
408 }
409 #endif
410