1 #region License, Terms and Conditions
2 //
3 // Jayrock - A JSON-RPC implementation for the Microsoft .NET Framework
4 // Written by Atif Aziz (www.raboof.com)
5 // Copyright (c) Atif Aziz. All rights reserved.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 //
12 // This library is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15 // details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with this library; if not, write to the Free Software Foundation, Inc.,
19 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //
21 #endregion
22 
23 namespace Jayrock.Services
24 {
25     #region Imports
26 
27     using System;
28     using System.Reflection;
29     using System.Threading;
30     using NUnit.Framework;
31 
32     #endregion
33 
34     [ TestFixture ]
35     public class TestTypeMethodImpl
36     {
37         [ Test, ExpectedException(typeof(ArgumentNullException)) ]
CannotInitializeWithNullMethod()38         public void CannotInitializeWithNullMethod()
39         {
40             new TypeMethodImpl(null);
41         }
42 
43         [ Test ]
MethodPropertyReflectsInitializedMethod()44         public void MethodPropertyReflectsInitializedMethod()
45         {
46             MethodInfo method = GetMethod("Sub");
47             TypeMethodImpl impl = new TypeMethodImpl(method);
48             Assert.IsNotNull(impl.Method);
49             Assert.AreSame(method, impl.Method);
50         }
51 
52         [ Test ]
InvokeCallsMethod()53         public void InvokeCallsMethod()
54         {
55             MockService service = new MockService();
56             TypeMethodImpl impl = GetImpl("Sub");
57             impl.Invoke(service, null);
58             Assert.AreSame(impl.Method, service.LastCalledMethod);
59         }
60 
61         [ Test ]
InvokeReturnsResult()62         public void InvokeReturnsResult()
63         {
64             MockService service = new MockService();
65             service.NextReturn = new object();
66             Assert.AreSame(service.NextReturn, GetImpl("Function").Invoke(service, null));
67         }
68 
69         [ Test ]
BeginInvokeWithoutCallback()70         public void BeginInvokeWithoutCallback()
71         {
72             MockService service = new MockService();
73             TypeMethodImpl impl = GetImpl("Sub");
74             object state = new object();
75             IAsyncResult ar = impl.BeginInvoke(service, null, null, state);
76             Assert.IsNotNull(ar);
77             Assert.IsTrue(ar.CompletedSynchronously);
78             Assert.IsTrue(ar.IsCompleted);
79             Assert.AreSame(state, ar.AsyncState);
80             Assert.IsNotNull(ar.AsyncWaitHandle);
81             Assert.AreSame(impl.Method, service.LastCalledMethod);
82         }
83 
84         [ Test ]
BeginInvokeWithCallback()85         public void BeginInvokeWithCallback()
86         {
87             MockService service = new MockService();
88             TypeMethodImpl impl = GetImpl("Sub");
89             bool[] called = new bool[1];
90             impl.BeginInvoke(service, null, new AsyncCallback(OnInvoked), called);
91             Assert.IsTrue(called[0]);
92         }
93 
94         [ Test, ExpectedException(typeof(ArgumentNullException)) ]
CannotInvokeWithNullService()95         public void CannotInvokeWithNullService()
96         {
97             GetImpl("Sub").Invoke(null, null);
98         }
99 
100         [ Test, ExpectedException(typeof(ArgumentNullException)) ]
CannotBeginInvokeWithNullService()101         public void CannotBeginInvokeWithNullService()
102         {
103             GetImpl("Sub").BeginInvoke(null, null, null, null);
104         }
105 
106         [ Test, ExpectedException(typeof(InvocationException)) ]
InvokeThrowsInvocationExceptionWhenBadParamCount()107         public void InvokeThrowsInvocationExceptionWhenBadParamCount()
108         {
109             GetImpl("Sub").Invoke(new MockService(), new object[] { 1, 2, 3 });
110         }
111 
112         [ Test, ExpectedException(typeof(InvocationException)) ]
InvokeThrowsInvocationExceptionWhenParamTypeMismatch()113         public void InvokeThrowsInvocationExceptionWhenParamTypeMismatch()
114         {
115             GetImpl("TwoArgSub").Invoke(new MockService(), new object[] { "1", "2" });
116         }
117 
118         [ Test ]
ExceptionInMethodPropagatedAsTargetMethodException()119         public void ExceptionInMethodPropagatedAsTargetMethodException()
120         {
121             MockService service = new MockService();
122             service.NextException = new ApplicationException();
123             TypeMethodImpl impl = GetImpl("Erroneous");
124             try
125             {
126                 impl.Invoke(service, null);
127                 Assert.Fail("Expected " + typeof(TargetMethodException));
128             }
129             catch (TargetMethodException e)
130             {
131                 Assert.IsNotNull(e.InnerException);
132                 Assert.AreSame(service.NextException, e.InnerException);
133             }
134         }
135 
136         [ Test ]
EndInvokePropagatesThrownException()137         public void EndInvokePropagatesThrownException()
138         {
139             MockService service = new MockService();
140             service.NextException = new ApplicationException();
141             TypeMethodImpl impl = GetImpl("Erroneous");
142             IAsyncResult ar = impl.BeginInvoke(service, null, null, null);
143             try
144             {
145                 impl.EndInvoke(service, ar);
146                 Assert.Fail("Expected " + typeof(TargetMethodException));
147             }
148             catch (TargetMethodException e)
149             {
150                 Assert.IsNotNull(e.InnerException);
151                 Assert.AreSame(service.NextException, e.InnerException);
152             }
153         }
154 
155         [ Test, ExpectedException(typeof(ArgumentNullException)) ]
CannotCallEndInvokeWithNullService()156         public void CannotCallEndInvokeWithNullService()
157         {
158             TypeMethodImpl impl = GetImpl("Sub");
159             impl.EndInvoke(null, impl.BeginInvoke(new MockService(), null, null, null));
160         }
161 
162         [ Test, ExpectedException(typeof(ArgumentNullException)) ]
CannotCallEndInvokeWithNullAsyncResult()163         public void CannotCallEndInvokeWithNullAsyncResult()
164         {
165             GetImpl("Sub").EndInvoke(new MockService(), null);
166         }
167 
168         [ Test ]
ImplementationIsNotAsynchronous()169         public void ImplementationIsNotAsynchronous()
170         {
171             Assert.IsFalse(GetImpl("Sub").IsAsynchronous);
172         }
173 
174         [ Test, ExpectedException(typeof(ArgumentException)) ]
CannotCallEndInvokeWithBadAsyncResultType()175         public void CannotCallEndInvokeWithBadAsyncResultType()
176         {
177             GetImpl("Sub").EndInvoke(new MockService(), new DummyAsyncResult());
178         }
179 
180         [ Test ]
InvokingStaticMethodPrependsServiceObjectToArgs()181         public void InvokingStaticMethodPrependsServiceObjectToArgs()
182         {
183             MockService service = new MockService();
184             const int num = 42;
185             const string str = "hello";
186             object result = GetImpl("Static").Invoke(service, new object[] { num, str });
187             Assert.AreEqual(new object[] { service, num, str }, result);
188         }
189 
190         private sealed class DummyAsyncResult : IAsyncResult
191         {
192             public bool IsCompleted { get { throw new NotImplementedException(); } }
193             public WaitHandle AsyncWaitHandle { get { throw new NotImplementedException(); } }
194             public object AsyncState { get { throw new NotImplementedException(); } }
195             public bool CompletedSynchronously { get { throw new NotImplementedException(); } }
196         }
197 
OnInvoked(IAsyncResult ar)198         private static void OnInvoked(IAsyncResult ar)
199         {
200             Assert.IsNotNull(ar);
201             ((bool[]) ar.AsyncState)[0] = true;
202         }
203 
GetImpl(string name)204         private static TypeMethodImpl GetImpl(string name)
205         {
206             return new TypeMethodImpl(typeof(MockService).GetMethod(name));
207         }
208 
GetMethod(string name)209         private static MethodInfo GetMethod(string name)
210         {
211             return typeof(MockService).GetMethod(name);
212         }
213 
214         private sealed class MockService : IService
215         {
216             public MethodBase LastCalledMethod;
217             public object NextReturn;
218             public Exception NextException;
219 
Sub()220             public void Sub()
221             {
222                 LastCalledMethod = MethodBase.GetCurrentMethod();
223             }
224 
TwoArgSub(int a, int b)225             public void TwoArgSub(int a, int b)
226             {
227                 LastCalledMethod = MethodBase.GetCurrentMethod();
228             }
229 
Function()230             public object Function()
231             {
232                 LastCalledMethod = MethodBase.GetCurrentMethod();
233                 return NextReturn;
234             }
235 
Erroneous()236             public void Erroneous()
237             {
238                 throw NextException;
239             }
240 
Static(IService service, int num, string str)241             public static object[] Static(IService service, int num, string str)
242             {
243                 return new object[] { service, num, str };
244             }
245 
GetClass()246             public ServiceClass GetClass()
247             {
248                 throw new NotImplementedException();
249             }
250         }
251     }
252 }
253