1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2004-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: InvokeTestCase.java,v 1.4 2005/05/03 13:46:01 tanderson Exp $
44 */
45 package org.exolab.jms.net.invoke;
46
47 import java.util.Arrays;
48 import java.util.Map;
49 import java.util.Properties;
50 import java.util.HashMap;
51 import java.io.IOException;
52
53 import org.apache.commons.logging.Log;
54 import org.apache.commons.logging.LogFactory;
55 import junit.framework.TestCase;
56
57 import org.exolab.jms.net.EchoServer;
58 import org.exolab.jms.net.EchoService;
59 import org.exolab.jms.net.EchoServiceImpl;
60 import org.exolab.jms.net.jvm.JVM;
61 import org.exolab.jms.net.orb.ORB;
62 import org.exolab.jms.net.orb.ORBFactory;
63 import org.exolab.jms.net.proxy.Proxy;
64 import org.exolab.jms.net.registry.Registry;
65 import org.exolab.jms.net.util.SSLUtil;
66
67
68 /***
69 * Tests remote method invocation.
70 *
71 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
72 * @version $Revision: 1.4 $ $Date: 2005/05/03 13:46:01 $
73 */
74 public abstract class InvokeTestCase extends TestCase {
75
76 /***
77 * The export URI.
78 */
79 private final String _uri;
80
81 /***
82 * The route URI.
83 */
84 private final String _routeURI;
85
86 /***
87 * Determines if the echo service will be run in the same JVM.
88 */
89 private final boolean _embeddedService;
90
91 /***
92 * Connection properties used when establishing a connection to the remote
93 * ORB. May be <code>null</code>
94 */
95 private final Map _connectionProps;
96
97 /***
98 * Connection properties used when constructing the local ORB. May
99 * be <code>null</code>
100 */
101 private final Map _acceptorProps;
102
103 /***
104 * The ORB.
105 */
106 private ORB _orb;
107
108 /***
109 * Tracks errors during {@link #testConcurrency}.
110 */
111 private Throwable _failure;
112
113 /***
114 * The JVM for running the echo service when <code>_embeddedService ==
115 * false</clode>.
116 */
117 private JVM _jvm;
118
119 /***
120 * The logger.
121 */
122 private static final Log _log = LogFactory.getLog(InvokeTestCase.class);
123
124 /***
125 * Echo service name.
126 */
127 private static final String ECHO_SERVICE = "echo";
128
129
130 /***
131 * Construct an instance of this class for a specific test case.
132 *
133 * @param name the name of test case
134 * @param uri the export URI
135 * @param embeddedService determines if the service will be run in the
136 * current JVM
137 */
138 public InvokeTestCase(String name, String uri, boolean embeddedService) {
139 this(name, uri, embeddedService, null);
140 }
141
142 /***
143 * Construct an instance of this class for a specific test case.
144 *
145 * @param name the name of test case
146 * @param uri the export URI
147 * @param embeddedService determines if the service will be run in the
148 * current JVM
149 * @param properties connection properties. May be <code>null</code>
150 */
151 public InvokeTestCase(String name, String uri, boolean embeddedService,
152 Map properties) {
153 this(name, uri, null, embeddedService, properties);
154 }
155
156 /***
157 * Construct an instance of this class for a specific test case.
158 *
159 * @param name the name of test case
160 * @param uri the export URI
161 * @param routeURI the route URI
162 * @param embeddedService determines if the service will be run in the
163 * current JVM
164 */
165 public InvokeTestCase(String name, String uri, String routeURI,
166 boolean embeddedService) {
167 this(name, uri, routeURI, embeddedService, null);
168 }
169
170 /***
171 * Construct an instance of this class for a specific test case.
172 *
173 * @param name the name of test case
174 * @param uri the export URI
175 * @param routeURI the route URI
176 * @param embeddedService determines if the service will be run in the
177 * current JVM
178 * @param properties connection properties. May be <code>null</code>
179 */
180 public InvokeTestCase(String name, String uri, String routeURI,
181 boolean embeddedService, Map properties) {
182 this(name, uri, routeURI, embeddedService, properties, properties);
183 }
184
185 /***
186 * Construct an instance of this class for a specific test case.
187 *
188 * @param name the name of test case
189 * @param uri the export URI
190 * @param routeURI the route URI
191 * @param embeddedService determines if the service will be run in the
192 * current JVM
193 * @param connectionProps connection properties. May be <code>null</code>
194 * @param acceptorProps acceptor properites. May be <code>null</code>
195 */
196 public InvokeTestCase(String name, String uri, String routeURI,
197 boolean embeddedService,
198 Map connectionProps, Map acceptorProps) {
199 super(name);
200 _uri = uri;
201 _routeURI = routeURI;
202 _embeddedService = embeddedService;
203 _connectionProps = connectionProps;
204 _acceptorProps = acceptorProps;
205 }
206
207 /***
208 * Tests remote method invocation for primitives.
209 *
210 * @throws Exception for any error
211 */
212 public void testPrimitives() throws Exception {
213 Registry registry = _orb.getRegistry(getConnectionProperties());
214 EchoService echo = (EchoService) registry.lookup(ECHO_SERVICE);
215
216 assertEquals(true, echo.echoBoolean(true));
217 assertEquals(false, echo.echoBoolean(false));
218
219 assertEquals(Byte.MIN_VALUE, echo.echoByte(Byte.MIN_VALUE));
220 assertEquals(Byte.MAX_VALUE, echo.echoByte(Byte.MAX_VALUE));
221
222 assertEquals(Character.MIN_VALUE, echo.echoChar(Character.MIN_VALUE));
223 assertEquals(Character.MAX_VALUE, echo.echoChar(Character.MAX_VALUE));
224
225 assertEquals(Short.MIN_VALUE, echo.echoShort(Short.MIN_VALUE));
226 assertEquals(Short.MAX_VALUE, echo.echoShort(Short.MAX_VALUE));
227
228 assertEquals(Integer.MIN_VALUE, echo.echoInt(Integer.MIN_VALUE));
229 assertEquals(Integer.MAX_VALUE, echo.echoInt(Integer.MAX_VALUE));
230
231 assertEquals(Long.MIN_VALUE, echo.echoLong(Long.MIN_VALUE));
232 assertEquals(Long.MAX_VALUE, echo.echoLong(Long.MAX_VALUE));
233
234 assertEquals(Float.MIN_VALUE, echo.echoFloat(Float.MIN_VALUE), 0.0f);
235 assertEquals(Float.MAX_VALUE, echo.echoFloat(Float.MAX_VALUE), 0.0f);
236
237 assertEquals(Double.MIN_VALUE, echo.echoDouble(Double.MIN_VALUE), 0.0);
238 assertEquals(Double.MAX_VALUE, echo.echoDouble(Double.MAX_VALUE), 0.0);
239 }
240
241 /***
242 * Tests remote method invocation for primitive arrays.
243 *
244 * @throws Exception for any error
245 */
246 public void testPrimitiveArrays() throws Exception {
247 final int size = 4096;
248
249 Registry registry = _orb.getRegistry(getConnectionProperties());
250 EchoService echo = (EchoService) registry.lookup(ECHO_SERVICE);
251
252
253 byte[] bytes = new byte[size];
254 for (int i = 0; i < bytes.length; ++i) {
255 bytes[i] = (byte) i;
256 }
257 byte[] bytesResult = (byte[]) echo.echoObject(bytes);
258 assertTrue(Arrays.equals(bytes, bytesResult));
259
260
261 int[] ints = new int[size];
262 for (int i = 0; i < ints.length; ++i) {
263 ints[i] = (int) i;
264 }
265 int[] intsResult = (int[]) echo.echoObject(ints);
266 assertTrue(Arrays.equals(ints, intsResult));
267
268
269 float[] floats = new float[size];
270 for (int i = 0; i < floats.length; ++i) {
271 floats[i] = i;
272 }
273 float[] floatsResult = (float[]) echo.echoObject(floats);
274 assertTrue(Arrays.equals(floats, floatsResult));
275 }
276
277 /***
278 * Verifies invocations can be made concurrently.
279 *
280 * @throws Exception for any error
281 */
282 public void testConcurrency() throws Exception {
283 Thread[] threads = new Thread[10];
284
285 Registry registry = _orb.getRegistry(getConnectionProperties());
286 EchoService echo = (EchoService) registry.lookup(ECHO_SERVICE);
287
288 for (int i = 0; i < threads.length; ++i) {
289 threads[i] = new Thread(new IntInvoker(echo, i, 1000));
290 }
291
292 for (int i = 0; i < threads.length; ++i) {
293 threads[i].start();
294 }
295
296 for (int i = 0; i < threads.length; ++i) {
297 try {
298 threads[i].join();
299 } catch (InterruptedException ignore) {
300 }
301 }
302 if (_failure != null) {
303 if (_failure instanceof Error) {
304 throw (Error) _failure;
305 } else if (_failure instanceof Exception) {
306 throw (Exception) _failure;
307 } else {
308 throw new Exception("testConcurrency failed: "
309 + _failure.getMessage());
310 }
311 }
312 }
313
314 /***
315 * Returns connection properties for establishing a connection to the remote
316 * ORB.
317 *
318 * @return the connection properties, or <code>null</code> if the default
319 * connection properties should be used
320 * @throws IOException if a store cannot be found
321 */
322 protected Map getConnectionProperties() throws IOException {
323 Map properties = new HashMap();
324 properties.put(ORB.PROVIDER_URI, getServerURI());
325 if (_connectionProps != null) {
326 properties.putAll(_connectionProps);
327 }
328 return properties;
329 }
330
331 /***
332 * Returns the acceptor properties to use when accepting connections.
333 *
334 * @return the acceptor properties, or <code>null</code> if the default
335 * connection properties should be used
336 * @throws Exception for any error
337 */
338 protected Map getAcceptorProperties() throws Exception {
339 Map properties = new HashMap();
340 properties.put(ORB.PROVIDER_URI, _uri);
341 if (_acceptorProps != null) {
342 properties.putAll(_acceptorProps);
343 }
344 return properties;
345 }
346
347 /***
348 * Helper to return the server URI.
349 *
350 * @return the server URI
351 */
352 protected String getServerURI() {
353 return (_routeURI != null) ? _routeURI : _uri;
354 }
355
356 /***
357 * Sets up the test case.
358 *
359 * @throws Exception for any error
360 */
361 protected void setUp() throws Exception {
362 _log.debug("setUp() [test=" + getName() + ", uri=" + _uri + "]");
363 _orb = ORBFactory.createORB(getAcceptorProperties());
364 if (_routeURI != null) {
365 _orb.addRoute(_uri, _routeURI);
366 }
367
368 if (_embeddedService) {
369 Registry serverRegistry = _orb.getRegistry();
370
371 Proxy proxy = _orb.exportObject(new EchoServiceImpl());
372 serverRegistry.bind(ECHO_SERVICE, proxy);
373 } else {
374 Properties props = new Properties();
375 final String key = "log4j.configuration";
376 String log4j = System.getProperty(key);
377 if (log4j != null) {
378 props.setProperty("log4j.configuration", key);
379 }
380 _jvm = new JVM(EchoServer.class.getName(), null, props,
381 getServerURI());
382 _jvm.start();
383
384 Thread.sleep(2000);
385 }
386 }
387
388 /***
389 * Cleans up the test case
390 *
391 * @throws Exception for any error
392 */
393 protected void tearDown() throws Exception {
394 _log.debug("tearDown() [test=" + getName() + ", uri=" + _uri + "]");
395 _orb.shutdown();
396 if (!_embeddedService && _jvm != null) {
397 _jvm.stop();
398 _jvm.waitFor();
399 }
400
401
402 SSLUtil.clearProperties();
403 }
404
405 /***
406 * Helper classed used in concurrency tests.
407 */
408 private class IntInvoker implements Runnable {
409
410 /***
411 * The echo service.
412 */
413 private final EchoService _echo;
414
415 /***
416 * The value to invoke the service with.
417 */
418 private final int _value;
419
420 /***
421 * No. of invocations to perform.
422 */
423 private final int _count;
424
425
426 /***
427 * Construct a new <code>IntInvoker</code>.
428 *
429 * @param echo the echo service
430 * @param value the value to invoke the echo service with
431 * @param count the no. of invocations to perform
432 */
433 public IntInvoker(EchoService echo, int value, int count) {
434 _echo = echo;
435 _value = value;
436 _count = count;
437 }
438
439 /***
440 * Run the invoker.
441 */
442 public void run() {
443 try {
444 for (int i = 0; i < _count; ++i) {
445 assertEquals(_value, _echo.echoInt(_value));
446 }
447 } catch (Throwable exception) {
448 _failure = exception;
449 }
450 }
451 }
452 }