summaryrefslogtreecommitdiff
path: root/jurt
diff options
context:
space:
mode:
authorKay Ramme <kr@openoffice.org>2001-02-02 08:01:04 +0000
committerKay Ramme <kr@openoffice.org>2001-02-02 08:01:04 +0000
commit76c7dfe82f3dbb9f409f4090a4a5fdae706516e3 (patch)
tree5fcb024eda13dad19ce473f578b1c6834c2f5a87 /jurt
parentaed6925a5fd6e2ef4bd038b798d698bb093a1419 (diff)
joined changes from: #80673# this enables force synchronous and fixes a small bug urp.java
Diffstat (limited to 'jurt')
-rw-r--r--jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java61
-rw-r--r--jurt/com/sun/star/lib/uno/environments/remote/Job.java15
-rw-r--r--jurt/com/sun/star/lib/uno/protocols/urp/urp.java77
-rw-r--r--jurt/test/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge_Test.java47
-rw-r--r--jurt/test/makefile.mk6
5 files changed, 125 insertions, 81 deletions
diff --git a/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java b/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java
index be50e2021..edda5d7f6 100644
--- a/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java
+++ b/jurt/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge.java
@@ -2,9 +2,9 @@
*
* $RCSfile: java_remote_bridge.java,v $
*
- * $Revision: 1.12 $
+ * $Revision: 1.13 $
*
- * last change: $Author: kr $ $Date: 2001-01-31 10:32:33 $
+ * last change: $Author: kr $ $Date: 2001-02-02 09:01:03 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -130,7 +130,7 @@ import com.sun.star.uno.IQueryInterface;
* The protocol to used is passed by name, the bridge
* then looks for it under <code>com.sun.star.lib.uno.protocols</code>.
* <p>
- * @version $Revision: 1.12 $ $ $Date: 2001-01-31 10:32:33 $
+ * @version $Revision: 1.13 $ $ $Date: 2001-02-02 09:01:03 $
* @author Kay Ramme
* @see com.sun.star.lib.uno.environments.remote.IProtocol
* @since UDK1.0
@@ -200,11 +200,15 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
public class MessageDispatcher extends Thread {
boolean _quit = false;
+ private ThreadID _threadID;
+
MessageDispatcher() {
super("MessageDispatcher");
}
public void run() {
+ _threadID = ThreadPool.getThreadId();
+
if(__MessageDispatcher_run_hook != null) {
try {
__MessageDispatcher_run_hook.invoke(this, "doWork", null);
@@ -225,11 +229,18 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
// Use the protocol to read a job.
IMessage iMessage = _iProtocol.readMessage(_inputStream);
+
+ if(iMessage.getThreadID().equals(_threadID)) {
+ continue;
+ }
+
// Take care of special methods release and acquire
if(iMessage.getOperation() != null && iMessage.getOperation().equals("release")) {
_java_environment.revokeInterface(iMessage.getOid(), new Type(iMessage.getInterface()));
remRefHolder(new Type(iMessage.getInterface()), iMessage.getOid());
+ if(iMessage.mustReply())
+ sendReply(false, iMessage.getThreadID(), null);
}
else if(iMessage.getOperation() != null && iMessage.getOperation().equals("acquire")) {
String oid_o[] = new String[]{iMessage.getOid()};
@@ -300,7 +311,7 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
exception.printStackTrace();
System.err.println(getClass() + " - giving up");
}
- if(DEBUG)
+ if(DEBUG)
exception.printStackTrace();
}
@@ -332,7 +343,7 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
protected Vector _stableListeners;
protected boolean _negotiate;
- protected boolean _forceSynchronouse;
+ protected boolean _forceSynchronous;
/**
* This method is for testing only.
@@ -457,13 +468,13 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
negotiateTouched = true;
}
- else if(left.equals("forcesynchronouse")) {
+ else if(left.equals("forcesynchronous")) {
if(right != null)
- _forceSynchronouse = (Integer.parseInt(right) == 1);
+ _forceSynchronous = (Integer.parseInt(right) == 1);
else
- _forceSynchronouse = true;
+ _forceSynchronous = true;
- if(_forceSynchronouse && !negotiateTouched)
+ if(_forceSynchronous && !negotiateTouched)
_negotiate = true;
}
else
@@ -606,6 +617,7 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
// see if we already have object with zInterface of given oid
Object object = _java_environment.getRegisteredInterface((String)oId, type);
+
if(object != null) {
if(object instanceof DispatcherAdapterBase) {
DispatcherAdapterBase dispatcherAdapterBase = (DispatcherAdapterBase)object;
@@ -613,9 +625,14 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
if(dispatcherAdapterBase.getObject() instanceof DispatcherAdapterBase) {
dispatcherAdapterBase = (DispatcherAdapterBase)dispatcherAdapterBase.getObject();
- if((dispatcherAdapterBase.getObject() instanceof String)) { // is it not my object?
+ if((dispatcherAdapterBase.getObject() instanceof String)) { // is it my proxy?
try {
- sendRequest(oId, type, "release", null, null, null);
+ sendRequest(oId,
+ type,
+ "release",
+ null,
+ new Boolean[]{new Boolean(_forceSynchronous)},
+ new Boolean[]{new Boolean(_forceSynchronous)});
}
catch(Exception exception) {
throw new MappingException(exception.getMessage());
@@ -627,7 +644,7 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
else {
String oid[] = new String[]{(String)oId};
- Object proxy = Proxy.create(this, oid[0], type, false, _forceSynchronouse); // this proxy sends a release, when finalized
+ Object proxy = Proxy.create(this, oid[0], type, false, _forceSynchronous); // this proxy sends a release, when finalized
object = _java_environment.registerInterface(proxy, oid, type);
}
@@ -702,15 +719,10 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
// because there can be active proxies
// _life_count = 0;
- synchronized(_xConnection) {
+ synchronized(_outputStream) {
_iProtocol.ignore_next_closeConnection();
_iProtocol.send_closeConnection(_outputStream);
- try {
- _xConnection.flush();
- }
- catch(com.sun.star.io.IOException ioException) {
- throw new IOException(ioException.toString());
- }
+ _outputStream.flush();
}
}
@@ -838,11 +850,11 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
if(_disposed) throw new RuntimeException("java_remote_bridge(" + this + ").sendReply - is disposed");
- synchronized(_xConnection) {
+ synchronized(_outputStream) {
_iProtocol.writeReply(exception, threadId, result);
_iProtocol.flush(new DataOutputStream(_outputStream));
- _xConnection.flush();
+ _outputStream.flush();
}
}
@@ -866,11 +878,12 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
synchronized(_xConnection) {
_iProtocol.writeRequest((String)object, (TypeDescription)type.getTypeDescription(), operation, ThreadPool.getThreadId(), params, synchron, mustReply);
- if(synchron[0].booleanValue()) // prepare a queue for this thread in the threadpool
+ if(synchron[0].booleanValue() && Thread.currentThread() != _messageDispatcher) // prepare a queue for this thread in the threadpool
ThreadPool.addThread(this);
_iProtocol.flush(new DataOutputStream(_outputStream));
_outputStream.flush();
+
}
}
catch(Exception exception) {
@@ -883,9 +896,9 @@ public class java_remote_bridge implements IBridge, IReceiver, IRequester, XBrid
throw exception;
}
- _xConnection.flush();
+// _xConnection.flush();
- if(synchron[0].booleanValue()) {
+ if(synchron[0].booleanValue() && Thread.currentThread() != _messageDispatcher) { // the message dispatcher must not block
result = ThreadPool.enter();
}
diff --git a/jurt/com/sun/star/lib/uno/environments/remote/Job.java b/jurt/com/sun/star/lib/uno/environments/remote/Job.java
index 855235395..1b010cb98 100644
--- a/jurt/com/sun/star/lib/uno/environments/remote/Job.java
+++ b/jurt/com/sun/star/lib/uno/environments/remote/Job.java
@@ -2,9 +2,9 @@
*
* $RCSfile: Job.java,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: kr $ $Date: 2001-01-16 18:01:27 $
+ * last change: $Author: kr $ $Date: 2001-02-02 09:01:03 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -79,7 +79,7 @@ import com.sun.star.uno.UnoRuntime;
* The Job is an abstraction for tasks which have to be done
* remotely because of a method invocation.
* <p>
- * @version $Revision: 1.3 $ $ $Date: 2001-01-16 18:01:27 $
+ * @version $Revision: 1.4 $ $ $Date: 2001-02-02 09:01:03 $
* @author Kay Ramme
* @see com.sun.star.lib.uno.environments.remote.ThreadID
* @see com.sun.star.lib.uno.environments.remote.IReceiver
@@ -169,7 +169,7 @@ public class Job {
else
xresult = dispatch_MethodCall(params[0]);
- if(_iMessage.isSynchron())
+ if(_iMessage.mustReply())
_iReceiver.sendReply(false, _iMessage.getThreadID(), xresult);
}
}
@@ -193,8 +193,11 @@ public class Job {
if(DEBUG) System.err.println("#### RemoteStub.request - exception:" + theException);
}
- else
- throw (Exception)invocationTargetException.getTargetException();
+ else // wrap it as uno exception
+ theException = new com.sun.star.uno.RuntimeException("java exception: " + theException.toString(), null);
+
+ if(_iMessage.mustReply())
+ _iReceiver.sendReply(true, _iMessage.getThreadID(), theException);
}
return result;
diff --git a/jurt/com/sun/star/lib/uno/protocols/urp/urp.java b/jurt/com/sun/star/lib/uno/protocols/urp/urp.java
index 9150a173f..6b1c32527 100644
--- a/jurt/com/sun/star/lib/uno/protocols/urp/urp.java
+++ b/jurt/com/sun/star/lib/uno/protocols/urp/urp.java
@@ -2,9 +2,9 @@
*
* $RCSfile: urp.java,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: kr $ $Date: 2001-01-16 18:01:32 $
+ * last change: $Author: kr $ $Date: 2001-02-02 09:01:04 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -95,7 +95,7 @@ import com.sun.star.uno.Type;
* from uno. The functionality is reachable through
* the <code>IProtocol</code> interface.
* <p>
- * @version $Revision: 1.3 $ $ $Date: 2001-01-16 18:01:32 $
+ * @version $Revision: 1.4 $ $ $Date: 2001-02-02 09:01:04 $
* @author Kay Ramme
* @see com.sun.star.lib.uno.environments.remote.IProtocol
* @since UDK1.0
@@ -273,9 +273,17 @@ public class urp extends Protocol {
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readShortRequest:" + _in_oid + " " + operation[0] + " " + synchron[0]);
}
- private void readLongRequest(byte header, String operation[], Object param[][], boolean synchron[]) throws Exception {
+ private void readLongRequest(byte header, String operation[], Object param[][], boolean synchron[], boolean mustReply[]) throws Exception {
++ _requestsRecieved;
+ // read the extended flags
+ if((header & MOREFLAGS) != 0) {// is there an extended flags byte?
+ byte exFlags = _unmarshal.readbyte();
+
+ mustReply[0] = (exFlags & MUSTREPLY) != 0;
+ synchron[0] = (exFlags & SYNCHRONOUSE) != 0;
+ }
+
// read the method id
int methodId = 0;
if((header & LONGMETHODID) != 0) // usigned short ?
@@ -286,6 +294,11 @@ public class urp extends Protocol {
if((header & NEWTYPE) != 0)
_in_interface = _unmarshal.readTypeDescription();
+ MethodDescription methodDescription = _in_interface.getMethodDescription(methodId);
+
+ if((header & MOREFLAGS) == 0) // no ex flags, so get info from typeinfo
+ synchron[0] = !methodDescription.isOneway();
+
if((header & NEWOID) != 0) // new oid?
_in_oid = _unmarshal.readOid();
@@ -294,21 +307,6 @@ public class urp extends Protocol {
_ignore_cache = ((header & IGNORECACHE) != 0); // do not use cache for this request?
- MethodDescription methodDescription = _in_interface.getMethodDescription(methodId);
- boolean mustReply;
-
- if((header & MOREFLAGS) != 0) {// is there an extended flags byte?
- byte exFlags = _unmarshal.readbyte();
-
- mustReply = (exFlags & MUSTREPLY) != 0;
- synchron[0] = (exFlags & SYNCHRONOUSE) != 0;
- }
- else {
- // the typeinfo does not differentiate between MUSTREPLY and SYNCHRONOUSE
- synchron[0] = !methodDescription.isOneway();
- mustReply = synchron[0];
- }
-
operation[0] = methodDescription.getName();
param[0] = readParams(methodDescription);
@@ -319,7 +317,7 @@ public class urp extends Protocol {
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readLongRequest:" + _in_oid + " " + operation[0] + " " + synchron[0]);
}
- private Object readMessage(String operation[], Object param[], boolean synchron[], boolean exception[]) throws Exception {
+ private Object readMessage(String operation[], Object param[], boolean synchron[], boolean mustReply[], boolean exception[]) throws Exception {
byte header = _unmarshal.readbyte();
Class signature[];
@@ -328,13 +326,17 @@ public class urp extends Protocol {
if((header & BIG_HEADER) != 0) { // full header?
if((header & REQUEST) != 0) // a request ?
- readLongRequest(header, operation, (Object [][])param, synchron);
+ readLongRequest(header, operation, (Object [][])param, synchron, mustReply);
else // a reply
result = readReply(header, exception);
}
else // only a short request header
readShortRequest(header, operation, (Object[][])param, synchron);
+ if(synchron[0]) // synchron implies MUSTREPLY
+ mustReply[0] = true;
+
+
if(DEBUG) System.err.println("##### " + getClass().getName() + ".readMessage:" + _in_oid + " " + operation[0] + " " + _in_threadId + " " + param[0] + " " + result);
return result;
@@ -390,7 +392,7 @@ public class urp extends Protocol {
boolean hasExFlags = false;
- // if the type of request is provided, test if it differs from declaration
+ // if synchron is provided, test if it differs from declaration
if(synchron[0] != null) {
if(methodDescription.isOneway() == synchron[0].booleanValue()) {
bigHeader = true;
@@ -400,17 +402,14 @@ public class urp extends Protocol {
else
synchron[0] = new Boolean(!methodDescription.isOneway());
-
- // if the type of request is provided, test if it differs from declaration
- if(mustReply[0] != null) {
- if(methodDescription.isOneway() == mustReply[0].booleanValue()) {
- bigHeader = true;
- hasExFlags = true;
- }
+ // if mustReply is provided and if it differs from synchron
+ // then we have to write it
+ if(mustReply[0] != null && (mustReply[0] != synchron[0])) {
+ bigHeader = true;
+ hasExFlags = true;
}
- else
- mustReply[0] = new Boolean(!methodDescription.isOneway());
-
+ else
+ mustReply[0] = synchron[0];
if(bigHeader) { // something has changed, send big header
header |= BIG_HEADER; // big header
@@ -428,7 +427,7 @@ public class urp extends Protocol {
exFlags |= synchron[0].booleanValue() ? SYNCHRONOUSE : 0;
exFlags |= mustReply[0].booleanValue() ? MUSTREPLY : 0;
- _marshal.writebyte(exFlags);
+ _marshal.writebyte(exFlags);
}
// write the method id
@@ -546,6 +545,7 @@ public class urp extends Protocol {
String _operation;
ThreadID _threadId;
boolean _synchron;
+ boolean _mustReply;
boolean _exception;
Object _params[];
@@ -555,6 +555,7 @@ public class urp extends Protocol {
String operation,
ThreadID threadId,
boolean synchron,
+ boolean mustReply,
boolean exception,
Object params[])
{
@@ -564,6 +565,7 @@ public class urp extends Protocol {
_operation = operation;
_threadId = threadId;
_synchron = synchron;
+ _mustReply = mustReply;
_exception = exception;
_params = params;
}
@@ -584,6 +586,10 @@ public class urp extends Protocol {
return _synchron;
}
+ public boolean mustReply() {
+ return _mustReply;
+ }
+
public boolean isException() {
return _exception;
}
@@ -626,9 +632,10 @@ public class urp extends Protocol {
String operation[] = new String[1];
Object params[][] = new Object[1][];
boolean synchron[] = new boolean[1];
+ boolean mustReply[] = new boolean[1];
boolean exception[] = new boolean[1];
- Object result = readMessage(operation, params, synchron, exception);
+ Object result = readMessage(operation, params, synchron, mustReply, exception);
if(operation[0] == null) { // a reply ?
iMessage = new Message(null, // oid
@@ -637,6 +644,7 @@ public class urp extends Protocol {
null, // operation
_in_threadId,
false,
+ false,
exception[0],
params[0]);
}
@@ -647,6 +655,7 @@ public class urp extends Protocol {
operation[0],
_in_threadId,
synchron[0],
+ mustReply[0],
false,
params[0]);
}
diff --git a/jurt/test/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge_Test.java b/jurt/test/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge_Test.java
index bc35484d1..b6c3d6efa 100644
--- a/jurt/test/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge_Test.java
+++ b/jurt/test/com/sun/star/lib/uno/bridges/java_remote/java_remote_bridge_Test.java
@@ -2,9 +2,9 @@
*
* $RCSfile: java_remote_bridge_Test.java,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: kr $ $Date: 2001-01-17 10:13:06 $
+ * last change: $Author: kr $ $Date: 2001-02-02 09:01:04 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -87,7 +87,6 @@ import com.sun.star.lib.uno.environments.java.Proxy;
import com.sun.star.lib.uno.environments.remote.IProtocol;
-
public class java_remote_bridge_Test {
static IEnvironment __java_environment_A;
static IEnvironment __java_environment_B;
@@ -102,23 +101,48 @@ public class java_remote_bridge_Test {
static byte __bytes[] = new byte[] {(byte)255, (byte)0, (byte)128};
- static boolean test_lifecycle(int objects) throws Exception {
+ static class YXInstanceProvider implements XInstanceProvider {
+ Object _object;
+
+ void createNewObject() {
+ _object = new TestInterface_Object(); // create the instance, which is to be mapped from A to B
+ }
+
+ public Object getInstance(String name) throws com.sun.star.container.NoSuchElementException, com.sun.star.uno.RuntimeException {
+// System.err.println("\t\tTest_XInstanceProvider.getInstance:" + name);
+
+ return _object;
+ }
+ }
+
+ static boolean test_lifecycle(int objects, YXInstanceProvider yXInstanceProvider) throws Exception {
System.err.println("\tjava_remote_bridge - testing lifecycle...");
boolean passed = true;
// XInterface theProxy = (XInterface)__java_remote_bridge_B.mapInterfaceFrom("testinstance", XInterface.class); // map the instance back from oid world to Bs real world
XInterface theProxy = (XInterface)Proxy.create(__java_remote_bridge_B, "testinstance", new Type(XInterface.class), true, false);
+
TestInterface theProxy_TestInterfaces[] = new TestInterface[objects];
for(int i = 0; i < objects; ++ i) {
- theProxy_TestInterfaces[i] = (TestInterface)com.sun.star.uno.UnoRuntime.queryInterface(TestInterface.class, theProxy);
+ yXInstanceProvider.createNewObject();
+ // map object
+ theProxy_TestInterfaces[i] = (TestInterface)com.sun.star.uno.UnoRuntime.queryInterface(TestInterface.class, theProxy);
theProxy_TestInterfaces[i].function(); // call the function
+
+ // remap object once
+ TestInterface remappedObject = (TestInterface)com.sun.star.uno.UnoRuntime.queryInterface(TestInterface.class, theProxy);
+ remappedObject.function(); // call the function
+
+ // remap object twice
+ remappedObject = (TestInterface)com.sun.star.uno.UnoRuntime.queryInterface(TestInterface.class, theProxy);
+ remappedObject.function(); // call the function
}
- System.err.println("\t\tobject method called " + TestInterface_Object.__called + " times, should be " + objects + " - passed?" + (TestInterface_Object.__called == objects));
+ System.err.println("\t\tobject method called " + TestInterface_Object.__called + " times, should be " + (objects * 3) + " - passed?" + (TestInterface_Object.__called == (objects * 3)));
System.err.println("\t\tbridge A life count: " + __java_remote_bridge_A.getLifeCount() + " should be " + objects + " - passed?" + (__java_remote_bridge_A.getLifeCount() == objects));
@@ -176,21 +200,16 @@ public class java_remote_bridge_Test {
__java_environment_B = new java_environment(null);
- class yXInstanceProvider implements XInstanceProvider {
- public Object getInstance(String name) throws com.sun.star.container.NoSuchElementException, com.sun.star.uno.RuntimeException {
-// System.err.println("\t\tTest_XInstanceProvider.getInstance:" + name);
- return new TestInterface_Object(); // create the instance, which is to be mapped from A to B
- }
- }
+ YXInstanceProvider yXInstanceProvider = new YXInstanceProvider();
- __xInstanceProvider = new yXInstanceProvider();
+ __xInstanceProvider = yXInstanceProvider;
__java_remote_bridge_A = new java_remote_bridge(__java_environment_A, null, new Object[]{protocol, __xConnection_A, __xInstanceProvider});
__java_remote_bridge_B = new java_remote_bridge(__java_environment_B, null, new Object[]{protocol, __xConnection_B, null});
// __java_remote_bridge_A = new java_remote_bridge(__java_environment_A, null, new Object[]{"iiop", __xConnection_A, __xInstanceProvider});
// __java_remote_bridge_B = new java_remote_bridge(__java_environment_B, null, new Object[]{"iiop", __xConnection_B, null});
- boolean passed = test_lifecycle(100);
+ boolean passed = test_lifecycle(100, yXInstanceProvider);
passed = passed && test_releasing_of_outmapped_objects();
System.err.println("java_remote_bridge_Test - " + protocol + " test passed?" + passed);
diff --git a/jurt/test/makefile.mk b/jurt/test/makefile.mk
index b449e7a73..455c12685 100644
--- a/jurt/test/makefile.mk
+++ b/jurt/test/makefile.mk
@@ -2,9 +2,9 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.3 $
+# $Revision: 1.4 $
#
-# last change: $Author: kr $ $Date: 2001-01-17 09:32:12 $
+# last change: $Author: kr $ $Date: 2001-02-02 09:01:04 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
@@ -77,6 +77,6 @@ test:
cd ./com/sun/star/lib/uno/environments/remote; dmake debug=t product=full
cd ./com/sun/star/lib/uno/protocols; dmake debug=t product=full
cd ./com/sun/star/comp/bridgefactory; dmake debug=t product=full
-
+#
javac DoTests.java
java -classpath $(CLASSPATH):. DoTests