18228 - create a test for Asynchronous RAD Requests and Events.
authorShadrack Kilemba <Shadrack.Kilemba@Oracle.COM>
Wed, 18 May 2011 12:42:36 -0400
changeset 706 9a1e4e1fa997
parent 705 ea1ecdb64a75
child 707 04293498d482
18228 - create a test for Asynchronous RAD Requests and Events. 18229 - create a test for Synchronous RAD requests and Events.
usr/src/apis/test.xml
usr/src/cmd/rad/mod/test/Makefile
usr/src/cmd/rad/mod/test/mod_test.c
usr/src/cmd/rad/mod/test/rad_request.c
usr/src/test/assertions/asynchronous.txt
usr/src/test/assertions/synchronous.txt
usr/src/test/java/src/client/RadRequestAsyncTest.java
usr/src/test/java/src/client/RadRequestBase.java
usr/src/test/java/src/client/RadRequestSyncTest.java
usr/src/test/java/src/client/RadRequestThread.java
usr/src/test/java/src/common/MBeanTestSingle.java
--- a/usr/src/apis/test.xml	Tue May 17 10:07:43 2011 -0400
+++ b/usr/src/apis/test.xml	Wed May 18 12:42:36 2011 -0400
@@ -196,4 +196,18 @@
 		<version major="0" minor="1" stability="private" />
 		<property type="boolean" name="true" access="ro" />
 	</api>
+
+	<api name="RadRequest">
+		<version major="0" minor="1" stability="private"/>
+		<event name="tick" type="integer"/>
+
+		<method name="sleep">
+			<error/>
+			<argument name="milliseconds" type="integer"/>
+		</method>
+
+		<method name="eventsStart"/>
+
+		<method name="eventsStop"/>
+	</api>
 </interface>
--- a/usr/src/cmd/rad/mod/test/Makefile	Tue May 17 10:07:43 2011 -0400
+++ b/usr/src/cmd/rad/mod/test/Makefile	Wed May 18 12:42:36 2011 -0400
@@ -26,7 +26,7 @@
 include ../Makefile.env
 
 MOD_APIS=test
-MOD_OBJS=mod_test.o properties.o addremove.o list.o derived.o
+MOD_OBJS=mod_test.o properties.o addremove.o list.o derived.o rad_request.o
 MOD_LIBNAME=mod_test.so
 MOD_INSTALLDIR=$(RADDIR_MODULE)
 
--- a/usr/src/cmd/rad/mod/test/mod_test.c	Tue May 17 10:07:43 2011 -0400
+++ b/usr/src/cmd/rad/mod/test/mod_test.c	Wed May 18 12:42:36 2011 -0400
@@ -27,6 +27,7 @@
 #include <limits.h>
 #include <string.h>
 #include <rad/adr.h>
+
 #include <rad/rad_modapi.h>
 
 #include "api_test.h"
@@ -234,6 +235,8 @@
 adr_name_t *addremove_template;
 
 extern conerr_t list_populate(void);
+extern rad_container_t rad_container_auth;
+extern rad_container_t rad_container_unauth;
 
 int
 _rad_init(void *handle)
@@ -263,6 +266,21 @@
 	    1, "type", "addremove"),
 	    &api_AddRemove_svr);
 
+	adr_name_t *rr_name = adr_name_vcreate("org.opensolaris.os.rad.test",
+	    1, "type", "radRequest");
+	rad_instance_t *inst = instance_create(adr_name_hold(rr_name),
+	    &api_RadRequest_svr, NULL, NULL);
+	rad_instance_t *uinst = instance_create(adr_name_hold(rr_name),
+	    &api_RadRequest_svr, NULL, NULL);
+
+	conerr_t err = ce_nomem;
+	if (inst == NULL || uinst == NULL ||
+	    (err = cont_insert(&rad_container_auth, inst, INST_ID_PICK)) !=
+	    ce_ok ||
+	    (err = cont_insert(&rad_container_unauth, uinst, INST_ID_PICK))
+	    != ce_ok)
+		rad_log(RL_WARN, "Unable to install test objects : %d", err);
+
 	(void) list_populate();
 
 	return (0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/rad/mod/test/rad_request.c	Wed May 18 12:42:36 2011 -0400
@@ -0,0 +1,104 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <unistd.h>
+#include "api_test.h"
+
+#define	INTERVAL 300000
+
+pthread_mutex_t events_lock = PTHREAD_MUTEX_INITIALIZER;
+static boolean_t go = B_FALSE;
+static boolean_t started = B_FALSE;
+
+static boolean_t
+should_go()
+{
+	rad_mutex_enter(&events_lock);
+	boolean_t result = go;
+	rad_mutex_exit(&events_lock);
+
+	return (result);
+}
+
+static void
+generate_events(void *args)
+{
+	rad_instance_t *inst = (rad_instance_t *)args;
+	long seq = 0;
+	while (should_go()) {
+		data_t *result = data_new_integer(seq);
+
+		instance_notify(inst, "tick", seq++, result);
+		(void) usleep(INTERVAL);
+	}
+
+	rad_mutex_enter(&events_lock);
+	started = B_FALSE;
+	rad_mutex_exit(&events_lock);
+
+	instance_rele(inst);
+}
+
+conerr_t
+api_RadRequest_invoke_sleep(rad_instance_t *inst, adr_method_t *meth,
+    data_t **rtnval, data_t **args, int count, data_t **err)
+{
+	int milliseconds = data_to_integer(args[0]);
+	if (milliseconds <= 0)
+		return (ce_object);
+
+	(void) usleep(milliseconds * 1000);
+	return (ce_ok);
+}
+
+conerr_t
+api_RadRequest_invoke_eventsStart(rad_instance_t *inst, adr_method_t *meth,
+    data_t **rtnval, data_t **args, int count, data_t **error)
+{
+	rad_mutex_enter(&events_lock);
+	if (!started) {
+		instance_hold(inst);
+
+		if (rad_thread_create_async(generate_events, inst) != rm_ok)
+			rad_log(RL_FATAL, "unable to create events thread.");
+
+		go = B_TRUE;
+		started = B_TRUE;
+	}
+	rad_mutex_exit(&events_lock);
+	return (ce_ok);
+}
+
+conerr_t
+api_RadRequest_invoke_eventsStop(rad_instance_t *inst, adr_method_t *meth,
+    data_t **rtnval, data_t **args, int count, data_t **error)
+{
+	rad_mutex_enter(&events_lock);
+	if (started) {
+		go = B_FALSE;
+	}
+	rad_mutex_exit(&events_lock);
+	return (ce_ok);
+}
--- a/usr/src/test/assertions/asynchronous.txt	Tue May 17 10:07:43 2011 -0400
+++ b/usr/src/test/assertions/asynchronous.txt	Wed May 18 12:42:36 2011 -0400
@@ -40,4 +40,5 @@
 
   Assertion: asyncStress
   Description: Stresses multiple simultaneous requests of differing
-    durations.
+    durations. All requests should be handled and in a reasonable
+    amount of time.
--- a/usr/src/test/assertions/synchronous.txt	Tue May 17 10:07:43 2011 -0400
+++ b/usr/src/test/assertions/synchronous.txt	Wed May 18 12:42:36 2011 -0400
@@ -35,5 +35,5 @@
   Description: Requests made while a long-running request is being
     processed are properly queued and handled.
 
-  Assertion: syncEvents
+  Assertion: syncEventWhileSlow
   Description: Events are delivered during long-running request.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/java/src/client/RadRequestAsyncTest.java	Wed May 18 12:42:36 2011 -0400
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package client;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opensolaris.os.rad.test.RadRequestMXBean;
+import testutil.Desc;
+
+import static org.junit.Assert.*;
+
+public class RadRequestAsyncTest extends RadRequestBase {
+
+    @Before
+    public void setUp() throws Exception {
+	// allow anonymous connections i.e. -t tcp:noauth,port=...
+	setUp("noauth,");
+    }
+
+    @Test(timeout = SLOW + PAUSE + TO_PADDING)
+    @Desc("Fast requests made while a long-running request is being " +
+	  "return before the long-running request returns.")
+    public void asyncFastWhileSlow() throws Exception {
+	RadRequestThread tslow = new RadRequestThread(mbean_, SLOW);
+	RadRequestThread tfast = new RadRequestThread(mbean_, FAST);
+
+	tslow.start();
+	Thread.sleep(PAUSE);
+	tfast.start();
+
+	tslow.join();
+	tfast.join();
+
+	// test normal completion of both requests.
+	assertTrue(tslow.isNormalCompletion() && tfast.isNormalCompletion());
+
+	// are the requests taking as long as they should.
+	assertTrue((tslow.getExecutionTime() >= SLOW) &&
+	    (tslow.getExecutionTime() <= SLOW + EPSILON));
+	assertTrue((tfast.getExecutionTime() >= FAST) &&
+	    (tfast.getExecutionTime() <= FAST + EPSILON));
+
+	// tfast should return approximately SLOW - (FAST + PAUSE) give or take
+	// EPSILON earlier than tslow.
+	long diff =
+	    tslow.getEndTime().getTime() - tfast.getEndTime().getTime();
+	assertTrue((diff > SLOW - (FAST + PAUSE) - EPSILON) &&
+		   (diff < SLOW - (FAST + PAUSE) + EPSILON));
+    }
+
+    @Test(timeout = SLOW + TO_PADDING)
+    @Desc("Events are delivered during long-running request.")
+    public void asyncEventWhileSlow() throws Exception {
+	runEventsTest();
+    }
+
+    @Test(timeout = (SLOW + TO_PADDING) * 2)
+    @Desc("Stresses multiple requests of differing durations to see if they " +
+	  "are all handled.")
+    public void asyncStressHandled() throws Exception {
+	RadRequestThread [] thread = asyncStress(MAX_THREADS * 2);
+
+	for (RadRequestThread t : thread) {
+	    if (t.getExecutionTime() < t.getDuration())
+		fail("The request was not handled successfully.");
+	}
+    }
+
+    @Test(timeout = SLOW + TO_PADDING)
+    @Desc("Stresses multiple requests of differing durations to see if they " +
+	  "are handled in a timely manner.")
+    public void asyncStressLatency() throws Exception {
+	RadRequestThread [] thread = asyncStress(MAX_THREADS);
+
+	for (RadRequestThread t : thread) {
+	    assertTrue((t.getExecutionTime() >= t.getDuration()) &&
+		(t.getExecutionTime() <= (t.getDuration() + EPSILON)));
+	}
+    }
+
+    /**
+     * simultaneously submit the requested number of requests to the server.
+     * @param - number of requests to submit
+     */
+    private RadRequestThread [] asyncStress(int reqs) throws Exception {
+	RadRequestThread [] thread = new RadRequestThread[reqs];
+
+	for (int i = 0; i < reqs; i++) {
+	    int duration = FAST + (int) (Math.random() * (SLOW - FAST));
+
+	    thread[i] = new RadRequestThread(mbean_, duration);
+	}
+
+	for (Thread t : thread) {
+	    t.start();
+	}
+
+	for (Thread t : thread) {
+	    t.join();
+	}
+
+	return thread;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/java/src/client/RadRequestBase.java	Wed May 18 12:42:36 2011 -0400
@@ -0,0 +1,171 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package client;
+
+import common.MBeanTestSingle;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.opensolaris.os.adr.Stability;
+import org.opensolaris.os.rad.api.pam.AuthenticatorMXBean;
+import org.opensolaris.os.rad.jmx.RadJMX;
+import org.opensolaris.os.rad.jmx.RadNotification;
+import org.opensolaris.os.rad.test.RadRequestMXBean;
+import testutil.Desc;
+
+import static org.junit.Assert.*;
+
+public abstract class RadRequestBase
+    extends MBeanTestSingle<RadRequestMXBean>
+    implements NotificationListener, NotificationFilter {
+
+    // durations in milliseconds
+    public static final int FAST = 300;
+    public static final int SLOW = 1500;
+    public static final int PAUSE = 200;
+    public static final int EPSILON = 50;
+    public static final int INTERVAL = 300;
+    public static final int TO_PADDING = 1000;
+
+    public static final int MAX_THREADS = 10;
+
+    private List<Date> eventList_ = new ArrayList<Date>();
+    private int TCP_PORT = 13579;
+    private final String URL = "service:jmx:rad://localhost:" + TCP_PORT;
+    private final String name = "org.opensolaris.os.rad.test:type=radRequest";
+    private ObjectName objName_;
+
+    protected JMXConnector connector_;
+    protected MBeanServerConnection mbsc_;
+    protected RadRequestMXBean mbean_;
+
+    private boolean isRadReady() throws Exception {
+	AuthenticatorMXBean authenticator = RadJMX.newMXBeanProxy(getMBSC(),
+	    strToON("org.opensolaris.os.rad:type=authentication"),
+	    AuthenticatorMXBean.class, Stability.PRIVATE);
+
+	if ((authenticator != null) &&
+	    (authenticator.getconnectionTimeout() > 0)) {
+	    return true;
+	}
+
+	return false;
+    }
+
+    protected void setUp(String noauth) throws Exception {
+	super.setUpSingle(name, RadRequestMXBean.class,
+	    new String [] {"-t", "tcp:" + noauth + "port=" + TCP_PORT +
+	    ",localonly=false"},
+	    "/usr/lib/rad/module/mod_test.so",
+	    "/usr/lib/rad/transport/mod_xport_socket.so");
+
+	assertTrue(isRadReady());
+
+	objName_ = strToON(name);
+
+	// now make the tcp connection we'll need for the tests.
+	connector_ = JMXConnectorFactory.connect(new JMXServiceURL(URL));
+	mbsc_ = connector_.getMBeanServerConnection();
+	mbean_ = RadJMX.newMXBeanProxy(mbsc_, objName_, RadRequestMXBean.class,
+	    Stability.PRIVATE);
+    }
+
+    @After
+    @Override
+    public void tearDown() throws IOException {
+	connector_.close();
+	super.tearDown();
+    }
+
+    /**
+     * implement <code>javax.management.NotificationListener.</code>
+     */
+    @Override
+    public void handleNotification(Notification notification, Object obj) {
+	if ((notification instanceof RadNotification) &&
+	    notification.getType().equals("tick")) {
+
+	    eventList_.add(new Date());
+	}
+    }
+
+    /**
+     * implement <code>javax.management.NotificationFilter.<code>
+     */
+    @Override
+    public boolean isNotificationEnabled(Notification notification) {
+	return notification.getType().equals("tick");
+    }
+
+    protected void runEventsTest() throws Exception {
+	RadRequestThread thread = new RadRequestThread(mbean_, SLOW);
+
+	mbean_.eventsStart();
+	mbsc_.addNotificationListener(objName_, this, this, null);
+	thread.start();
+	thread.join();
+	mbsc_.removeNotificationListener(objName_, this, this, null);
+	mbean_.eventsStop();
+
+	Date startTime = thread.getStartTime();
+	Date endTime = thread.getEndTime();
+
+	// the request completed normally
+	assertTrue(thread.isNormalCompletion());
+
+	// we received roughly ((endTime - startTime) / INTERVAL)
+	// events. At the very least we should get 1 less event than expected.
+	int expected = (int)
+	    (endTime.getTime() - startTime.getTime()) / INTERVAL;
+	int received = eventList_.size();
+	assertTrue((received == expected) || (received == (expected - 1)));
+
+	// check that the interval between the events is roughly
+	// INTERVAL +/- a small margin.
+	for (int i = 0, j = 1; j < eventList_.size(); i++, j++) {
+	    long delta =
+		eventList_.get(j).getTime() - eventList_.get(i).getTime();
+
+	    // INTERVAL - EPSILON >= delta <= INTERVAL + EPSILON
+	    boolean withinRange = (delta >= INTERVAL - EPSILON) &&
+		(delta <= INTERVAL + EPSILON);
+
+	    assertTrue(withinRange);
+	}
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/java/src/client/RadRequestSyncTest.java	Wed May 18 12:42:36 2011 -0400
@@ -0,0 +1,73 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package client;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opensolaris.os.rad.test.RadRequestMXBean;
+import testutil.Desc;
+
+import static org.junit.Assert.*;
+
+public class RadRequestSyncTest extends RadRequestBase {
+
+    @Before
+    public void setUp() throws Exception {
+	// do not allow anonymous connections -t tcp:port=...
+	setUp("");
+    }
+
+    @Test(timeout = SLOW + PAUSE + FAST + TO_PADDING)
+    @Desc("Requests made while a long-running request is being processed " +
+	  "are properly queued and handled.")
+    public void syncSlowBlocksFast() throws Exception {
+	RadRequestThread tslow = new RadRequestThread(mbean_, SLOW);
+	RadRequestThread tfast = new RadRequestThread(mbean_, FAST);
+
+	tslow.start();
+	Thread.sleep(PAUSE);
+	tfast.start();
+
+	tslow.join();
+	tfast.join();
+
+	// both requests completed.
+	assertTrue(tslow.isNormalCompletion() && tfast.isNormalCompletion());
+
+	// tslow finishes before tfast.
+	assertTrue(tslow.getEndTime().before(tfast.getEndTime()));
+
+	// tfast finishes atleast FAST after tslow finishes.
+	assertTrue((tslow.getEndTime().getTime() + FAST) <=
+            tfast.getEndTime().getTime());
+    }
+
+    @Test(timeout = SLOW + TO_PADDING)
+    @Desc("Events are delivered during a long-running request.")
+    public void syncEventWhileSlow() throws Exception {
+	runEventsTest();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/test/java/src/client/RadRequestThread.java	Wed May 18 12:42:36 2011 -0400
@@ -0,0 +1,78 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ */
+
+package client;
+
+import java.util.Date;
+import org.opensolaris.os.rad.ObjectException;
+import org.opensolaris.os.rad.test.RadRequestMXBean;
+
+public class RadRequestThread extends Thread {
+    private RadRequestMXBean mbean_;
+
+    private int duration_;
+    private Date startTime_;
+    private Date endTime_;
+
+    public RadRequestThread(RadRequestMXBean bean, int duration) {
+	mbean_ = bean;
+	duration_ = duration;
+    }
+
+    @Override
+    public void run() {
+	startTime_ = new Date();
+	try {
+	    mbean_.sleep(duration_);
+	    endTime_ = new Date();
+	} catch (Exception e) {
+	    e.printStackTrace();
+	}
+    }
+
+    public int getDuration() {
+	return duration_;
+    }
+
+    public Date getStartTime() {
+	return startTime_;
+    }
+
+    public Date getEndTime() {
+	return endTime_;
+    }
+
+    /* These two methods should be called after a successful join */
+    public boolean isNormalCompletion() {
+	return (endTime_ != null);
+    }
+
+    public long getExecutionTime() throws Exception {
+	if (!isNormalCompletion())
+	    throw new Exception("The request was not handled successfuly.");
+
+	return (endTime_.getTime() - startTime_.getTime());
+    }
+}
\ No newline at end of file
--- a/usr/src/test/java/src/common/MBeanTestSingle.java	Tue May 17 10:07:43 2011 -0400
+++ b/usr/src/test/java/src/common/MBeanTestSingle.java	Wed May 18 12:42:36 2011 -0400
@@ -33,8 +33,12 @@
 
     protected void setUpSingle(String name, Class<T> type, String... modules)
 	throws Exception {
+	setUpSingle(name, type, null,  modules);
+    }
 
-	super.setUpCommon(modules);
+    protected void setUpSingle(String name, Class<T> type, String auxargs[],
+        String... modules) throws Exception {
+	super.setUpCommon(auxargs, modules);
 	bean_ = RadJMX.newMXBeanProxy(getMBSC(), strToON(name), type,
 	    Stability.PRIVATE);
     }