Bug 348710 - Fix array handling bug. Add support for sized strings. Update unit tests to test array parameters. XULRunner only.

This commit is contained in:
pedemont@us.ibm.com 2007-05-02 09:39:19 -07:00
parent e6f06e4e85
commit 1fbdceaa6c
7 changed files with 759 additions and 70 deletions

View File

@ -888,6 +888,67 @@ SetupParams(JNIEnv *env, const jobject aParam, PRUint8 aType, PRBool aIsOut,
break;
}
case nsXPTType::T_PSTRING_SIZE_IS:
case nsXPTType::T_PWSTRING_SIZE_IS:
{
NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
LOG(("Sized string\n"));
jstring data = nsnull;
if (!aIsOut) { // 'in'
data = (jstring) aParam;
} else if (aParam) { // 'inout'
data = (jstring) env->GetObjectArrayElement((jobjectArray) aParam,
aIndex);
}
PRUint32 length = 0;
if (data) {
if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
length = env->GetStringUTFLength(data);
} else {
length = env->GetStringLength(data);
}
if (length > aArraySize) {
rv = NS_ERROR_ILLEGAL_VALUE;
break;
}
}
PRUint32 size_of_char = (aType == nsXPTType::T_PSTRING_SIZE_IS) ?
sizeof(char) : sizeof(jchar);
PRUint32 allocLength = (aArraySize + 1) * size_of_char;
void* buf = nsMemory::Alloc(allocLength);
if (!buf) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
if (data) {
if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
const char* str = env->GetStringUTFChars(data, nsnull);
if (!str) {
nsMemory::Free(buf);
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
memcpy(buf, str, length);
env->ReleaseStringUTFChars(data, str);
} else {
jchar* jchar_str = NS_STATIC_CAST(jchar*, buf);
env->GetStringRegion(data, 0, length, jchar_str);
}
}
aVariant.val.p = buf;
if (aIsOut) { // 'inout'
aVariant.ptr = &aVariant.val;
aVariant.SetPtrIsData();
}
break;
}
default:
NS_WARNING("unexpected parameter type");
return NS_ERROR_UNEXPECTED;
@ -1240,7 +1301,7 @@ FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
// cleanup
// If this is not an out param or if the invokeResult is a failure case,
// then the array elements have not been cleaned up. Do so now.
if (!aParamInfo.IsOut() || NS_FAILED(aInvokeResult)) {
if (!aParamInfo.IsOut() || (NS_FAILED(aInvokeResult) && aVariant.val.p)) {
nsXPTCVariant var;
for (PRUint32 i = 0; i < aArraySize; i++) {
rv = GetNativeArrayElement(aArrayType, aVariant.val.p, i, &var);
@ -1254,6 +1315,48 @@ FinalizeParams(JNIEnv *env, const nsXPTParamInfo &aParamInfo, PRUint8 aType,
break;
}
case nsXPTType::T_PSTRING_SIZE_IS:
case nsXPTType::T_PWSTRING_SIZE_IS:
{
NS_PRECONDITION(!aIsArrayElement, "sized string array not supported");
if ((aParamInfo.IsOut()) && NS_SUCCEEDED(aInvokeResult))
{
// create new string from data
jstring str = nsnull;
if (aVariant.val.p) {
if (aType == nsXPTType::T_PSTRING_SIZE_IS) {
PRUint32 len = (aArraySize + 1) * sizeof(char);
char* buf = (char*) nsMemory::Alloc(len);
if (buf) {
memcpy(buf, aVariant.val.p, len);
buf[aArraySize] = '\0';
str = env->NewStringUTF((const char*) buf);
nsMemory::Free(buf);
}
} else {
str = env->NewString((const jchar*) aVariant.val.p, aArraySize);
}
if (!str) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
}
if (aParamInfo.IsRetval()) {
*aParam = str;
} else if (*aParam) {
// put new string into output array
env->SetObjectArrayElement((jobjectArray) *aParam, aIndex, str);
}
}
// cleanup
if (aVariant.val.p)
nsMemory::Free(aVariant.val.p);
break;
}
default:
NS_WARNING("unexpected parameter type");
return NS_ERROR_UNEXPECTED;
@ -1411,45 +1514,25 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
}
memset(params, 0, paramCount * sizeof(nsXPTCVariant));
PRBool foundDependentParam = PR_FALSE;
for (PRUint8 i = 0; i < paramCount && NS_SUCCEEDED(rv); i++)
{
LOG(("\t Param %d: ", i));
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
params[i].type = paramInfo.GetType();
if (params[i].type.IsDependent() && paramInfo.IsIn()) {
foundDependentParam = PR_TRUE;
continue;
}
if (paramInfo.IsIn()) {
PRUint8 type = params[i].type.TagPart();
// is paramater an array?
PRUint8 arrayType = 0;
PRUint32 arraySize = 0;
if (type == nsXPTType::T_ARRAY) {
// get array type
nsXPTType xpttype;
rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);
if (NS_FAILED(rv))
break;
arrayType = xpttype.TagPart();
// get size of array
PRUint8 argnum;
rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
&argnum);
if (NS_FAILED(rv))
break;
arraySize = params[argnum].val.u32;
}
// get IID for interface params
nsID iid;
if (type == nsXPTType::T_INTERFACE ||
type == nsXPTType::T_INTERFACE_IS ||
type == nsXPTType::T_ARRAY &&
(arrayType == nsXPTType::T_INTERFACE ||
arrayType == nsXPTType::T_INTERFACE_IS))
{
PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
if (type == nsXPTType::T_INTERFACE) {
rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, type,
methodIndex, params, PR_TRUE, iid);
}
@ -1458,8 +1541,8 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
if (aParams && !paramInfo.IsRetval()) {
param = env->GetObjectArrayElement(aParams, i);
}
rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, arrayType,
arraySize, PR_FALSE, 0, params[i]);
rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, 0, 0,
PR_FALSE, 0, params[i]);
}
} else {
LOG(("out/retval\n"));
@ -1467,6 +1550,76 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
params[i].SetPtrIsData();
}
}
// Handle any dependent params by doing a second pass
if (foundDependentParam) {
for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++) {
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
params[j].type = paramInfo.GetType();
if (!params[j].type.IsDependent())
continue;
if (paramInfo.IsIn()) {
PRUint8 type = params[j].type.TagPart();
// is paramater an array or sized string?
PRUint8 arrayType = 0;
PRUint32 arraySize = 0;
PRBool isArray = params[j].type.IsArray();
PRBool isSizedString = isArray ? PR_FALSE :
type == nsXPTType::T_PSTRING_SIZE_IS ||
type == nsXPTType::T_PWSTRING_SIZE_IS;
if (isArray) {
// get array type
nsXPTType xpttype;
rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &xpttype);
if (NS_FAILED(rv))
break;
arrayType = xpttype.TagPart();
// IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
// therefore, treat as a signed 8bit value
if (arrayType == nsXPTType::T_U8)
arrayType = nsXPTType::T_I8;
}
if (isArray || isSizedString) {
// get size of array or string
PRUint8 argnum;
rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
&argnum);
if (NS_FAILED(rv))
break;
arraySize = params[argnum].val.u32;
}
// get IID for interface params
nsID iid;
if (type == nsXPTType::T_INTERFACE_IS ||
type == nsXPTType::T_ARRAY &&
(arrayType == nsXPTType::T_INTERFACE ||
arrayType == nsXPTType::T_INTERFACE_IS))
{
PRUint8 paramType = type == nsXPTType::T_ARRAY ? arrayType : type;
rv = GetIIDForMethodParam(iinfo, methodInfo, paramInfo, paramType,
methodIndex, params, PR_TRUE, iid);
}
if (NS_SUCCEEDED(rv)) {
jobject param = nsnull;
if (aParams && !paramInfo.IsRetval()) {
param = env->GetObjectArrayElement(aParams, j);
}
rv = SetupParams(env, param, type, paramInfo.IsOut(), iid, arrayType,
arraySize, PR_FALSE, 0, params[j]);
}
}
}
}
if (NS_FAILED(rv)) {
ThrowException(env, rv, "SetupParams failed");
return nsnull;
@ -1493,17 +1646,28 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(i);
PRUint8 type = paramInfo.GetType().TagPart();
// is paramater an array?
// is paramater an array or sized string?
PRUint8 arrayType = 0;
PRUint32 arraySize = 0;
if (type == nsXPTType::T_ARRAY) {
PRBool isArray = params[i].type.IsArray();
PRBool isSizedString = isArray ? PR_FALSE :
type == nsXPTType::T_PSTRING_SIZE_IS ||
type == nsXPTType::T_PWSTRING_SIZE_IS;
if (isArray) {
// get array type
nsXPTType array_xpttype;
rv = iinfo->GetTypeForParam(methodIndex, &paramInfo, 1, &array_xpttype);
if (NS_FAILED(rv))
break;
arrayType = array_xpttype.TagPart();
// IDL 'octet' arrays are not 'promoted' to short, but kept as 'byte';
// therefore, treat as a signed 8bit value
if (arrayType == nsXPTType::T_U8)
arrayType = nsXPTType::T_I8;
}
if (isArray || isSizedString) {
// get size of array
PRUint8 argnum;
rv = iinfo->GetSizeIsArgNumberForParam(methodIndex, &paramInfo, 0,
@ -1536,16 +1700,12 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
rv = FinalizeParams(env, paramInfo, type, params[i], iid, PR_FALSE,
arrayType, arraySize, 0, invokeResult, javaElement);
}
if (NS_FAILED(rv)) {
ThrowException(env, rv, "FinalizeParams failed");
return nsnull;
}
// Normally, we would delete any created nsID object in the above loop.
// However, GetIIDForMethodParam may need some of the nsID params when it's
// looking for the IID of an INTERFACE_IS. Therefore, we can't delete it
// until we've gone through the 'Finalize' loop once and created the result.
for (PRUint8 j = 0; j < paramCount && NS_SUCCEEDED(rv); j++)
for (PRUint8 j = 0; j < paramCount; j++)
{
const nsXPTParamInfo &paramInfo = methodInfo->GetParam(j);
const nsXPTType &type = paramInfo.GetType();
@ -1567,6 +1727,10 @@ JAVAPROXY_NATIVE(callXPCOMMethod) (JNIEnv *env, jclass that, jobject aJavaProxy,
message.AppendLiteral("\" returned an error condition");
ThrowException(env, invokeResult, message.get());
}
if (NS_FAILED(rv)) {
ThrowException(env, rv, "FinalizeParams failed");
return nsnull;
}
LOG(("<=== (XPCOM) %s::%s()\n", ifaceName, methodInfo->GetName()));
return result;

View File

@ -49,6 +49,7 @@ DIRS = $(DEPTH)/js/src/xpconnect/tests/idl
XPIDLSRCS = \
nsIJXTestParams.idl \
nsIJXTestArrayParams.idl \
$(NULL)
EXTRA_COMPONENTS = \

View File

@ -37,17 +37,22 @@
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.mozilla.xpcom.Mozilla;
import org.mozilla.xpcom.XPCOMException;
import org.mozilla.interfaces.nsIEcho;
import org.mozilla.interfaces.nsIJXTestArrayParams;
import org.mozilla.interfaces.nsIJXTestParams;
import org.mozilla.interfaces.nsIStackFrame;
import org.mozilla.interfaces.nsISupports;
import org.mozilla.interfaces.nsITestXPCFunctionCallback;
import org.mozilla.interfaces.nsITestXPCSomeUselessThing;
import org.mozilla.interfaces.nsIXPCTestArray;
import org.mozilla.interfaces.nsIXPCTestIn;
import org.mozilla.xpcom.Mozilla;
import org.mozilla.xpcom.XPCOMException;
/**
@ -93,7 +98,10 @@ public class TestParams {
runEchoTests();
runInTests();
} catch (RunTestsException e) {
runArrayTests();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
@ -104,6 +112,7 @@ public class TestParams {
try {
jstest.runTests(new JavaTests());
} catch (XPCOMException e) {
e.printStackTrace();
System.exit(-1);
}
@ -169,17 +178,16 @@ public class TestParams {
}
/**
* @param aCallee
* @param aCallee Object on which to run tests
* @param aTests An array of tests to run. The format looks like this:
* index 0: method name of test to run
* 1: Object array of method arguments
* 2: expected result
* 3: comment to use when logging test result; if
* <code>null</code>, uses method name
* @throws RunTestsException if any of the tests fails
* @throws RuntimeException if any of the tests fails
*/
private static void runTestsArray(Object aCallee, Object[][] aTests)
throws RunTestsException {
private static void runTestsArray(Object aCallee, Object[][] aTests) {
boolean succeeded = true;
for (int i = 0; i < aTests.length; i++) {
Method method = getMethod(aCallee.getClass(), (String) aTests[i][0]);
@ -214,7 +222,64 @@ public class TestParams {
}
if (!succeeded) {
throw new RunTestsException();
throw new RuntimeException("RunTestsArray did not succeed");
}
}
/**
* @param aCallee Object on which to run tests
* @param aTests An array of tests to run. The format looks like this:
* index 0: method name of test to run
* 1: Object array of method arguments
* 2: comparator method that checks result
* 3: comment to use when logging test result; if
* <code>null</code>, uses method name
* @throws RuntimeException if any of the tests fails
*/
private static void runTestsArrayWithComparator(Object aCallee,
Object[][] aTests) {
boolean succeeded = true;
for (int i = 0; i < aTests.length; i++) {
Method method = getMethod(aCallee.getClass(), (String) aTests[i][0]);
String comment = (aTests[i][3] != null) ? (String) aTests[i][3] :
(String) aTests[i][0];
Object result = null;
boolean passed = false;
Exception exp = null;
Object[] args = (Object[]) aTests[i][1];
try {
result = method.invoke(aCallee, args);
} catch (Exception e) {
exp = e;
if (exp instanceof InvocationTargetException) {
exp = (Exception) ((InvocationTargetException) exp).getCause();
}
}
// call comparator method to see if test passed
try {
IResultComparator r = (IResultComparator) aTests[i][2];
passed = r.didPass(args, result, exp);
} catch (Exception e) {
exp = e;
passed = false;
}
logResult(comment, passed);
if (!passed) {
succeeded = false;
if (exp != null) {
System.err.println("*** TEST " + comment + " threw exception:");
exp.printStackTrace();
}
}
}
if (!succeeded) {
throw new RuntimeException("RunTestsArray did not succeed");
}
}
@ -229,10 +294,10 @@ public class TestParams {
}
private static void logResult(String comment, boolean passed) {
System.out.println(comment + "\t\t" + (passed ? "passed" : "FAILED"));
System.out.println((passed ? "passed" : "FAILED") + ": " + comment);
}
private static void runEchoTests() throws RunTestsException {
private static void runEchoTests() {
nsIEcho nativeEcho = (nsIEcho) Mozilla.getInstance()
.getComponentManager()
.createInstanceByContractID("@mozilla.org/javaxpcom/tests/xpc;1",
@ -332,7 +397,7 @@ public class TestParams {
runTestsArray(nativeEcho, tests);
}
private static void runInTests() throws RunTestsException {
private static void runInTests() {
nsIXPCTestIn nativeInTest = (nsIXPCTestIn) Mozilla.getInstance()
.getComponentManager()
.createInstanceByContractID("@mozilla.org/javaxpcom/tests/xpc;1",
@ -387,12 +452,10 @@ public class TestParams {
"echoBoolean w/ " + Boolean.FALSE},
{ "echoBoolean", new Object[] { Boolean.TRUE }, Boolean.TRUE,
"echoBoolean w/ " + Boolean.TRUE },
/* XXX bug 367793
{ "echoOctet", new Object[] { zeroShort }, zeroShort,
"echoOctet w/ zero"},
{ "echoOctet", new Object[] { maxUByte }, maxUByte,
"echoOctet w/ " + maxUByte },
*/
{ "echoLongLong", new Object[] { minLong }, minLong,
"echoLongLong w/ " + minLong },
{ "echoLongLong", new Object[] { maxLong }, maxLong,
@ -486,10 +549,298 @@ public class TestParams {
runTestsArray(nativeInTest, tests);
}
}
class RunTestsException extends Exception {
private static final long serialVersionUID = -2865653674109284035L;
private static void runArrayTests() {
/*** nsIXPCTestArray ***/
nsIXPCTestArray xpcArrayTests = (nsIXPCTestArray) Mozilla.getInstance()
.getComponentManager()
.createInstanceByContractID("@mozilla.org/javaxpcom/tests/xpc;1",
null, nsIXPCTestArray.NS_IXPCTESTARRAY_IID);
boolean succeeded = true;
final int[][] intArray = { { 1, 2, 3, 4, 0, -1, -2, -3, -4 } };
int[][] intArrayCopy = (int[][]) intArray.clone();
Integer multiple = new Integer(2);
final String[][] str = { { "this", "is", "to", "be", "reversed" } };
String[][] strCopy = (String[][]) str.clone();
long[] count = { strCopy[0].length };
String[][] strCopy2 = (String[][]) str.clone();
Object[][] tests = new Object[][] {
{ "multiplyEachItemInIntegerArray",
new Object[] { multiple, new Long(intArrayCopy[0].length), intArrayCopy },
new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int m = ((Integer) args[0]).intValue();
int[][] resultArray = (int[][]) args[2];
for (int i = 0; i < intArray[0].length; i++) {
if (intArray[0][i] * m != resultArray[0][i])
return false;
}
return true;
}
},
null
},
{ "doubleStringArray",
new Object[] { count, strCopy },
new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int inLength = str[0].length;
int outLength = (int) ((long[]) args[0])[0];
if (outLength != inLength * 2)
return false;
String[][] resultArray = (String[][]) args[1];
for (int i = 0; i < inLength; i++) {
String doubled = doubleString(str[0][i]);
if (!doubled.equals(resultArray[0][i*2]) ||
!doubled.equals(resultArray[0][i*2+1]))
return false;
}
return true;
}
private String doubleString(String string) {
StringBuffer buf = new StringBuffer(string.length()*2);
for (int i = 0; i < string.length(); i++) {
buf.append(string.charAt(i));
buf.append(string.charAt(i));
}
return buf.toString();
}
},
null
},
{ "reverseStringArray",
new Object[] { new Long(strCopy2[0].length), strCopy2 },
new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int length = ((Long) args[0]).intValue();
String[][] resultArray = (String[][]) args[1];
for (int i = 0; i < length; i++) {
if (!str[0][i].equals(resultArray[0][length - 1 - i]))
return false;
}
return true;
}
},
null
}
};
runTestsArrayWithComparator(xpcArrayTests, tests);
/*** nsIJXTestArrayParams ***/
nsIJXTestArrayParams arrayTests = (nsIJXTestArrayParams) xpcArrayTests
.queryInterface(nsIJXTestArrayParams.NS_IJXTESTARRAYPARAMS_IID);
System.arraycopy(intArray[0], 0, intArrayCopy[0], 0, intArray[0].length);
int[][] resultArray = new int[1][];
IResultComparator copyIntArrayResultComparator = new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int inLength = ((Long) args[1]).intValue();
int[][] resultArray = (int[][]) args[2];
for (int i = 0; i < inLength; i++) {
if (intArray[0][i] != resultArray[0][i])
return false;
}
return true;
}
};
// for tests that are expected to throw ArrayIndexOutOfBoundsException
IResultComparator arrayIOBExpComparator = new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null) {
if (e instanceof ArrayIndexOutOfBoundsException)
return true;
}
return false;
}
};
String[] returnString = new String[1];
IResultComparator stringComparator = new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
String inString = (String) args[0];
int inLength = ((Long) args[1]).intValue();
String[] outString = (String[]) args[2];
if (outString[0].length() != inLength)
return false;
if (!inString.substring(0, inLength).equals(outString[0]))
return false;
return true;
}
};
IResultComparator returnStringComparator = new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
String inString = (String) args[0];
int inLength = ((Long) args[1]).intValue();
String outString = (String) result;
if (outString.length() != inLength)
return false;
if (!inString.substring(0, inLength).equals(outString))
return false;
return true;
}
};
byte[] testBytes = null;
byte[][] returnBytes = new byte[1][];
try {
testBytes = utf8String.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
tests = new Object[][] {
{ "multiplyEachItemInIntegerArray2",
new Object[] { multiple, intArrayCopy, new Long(intArrayCopy[0].length) },
new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int m = ((Integer) args[0]).intValue();
int[][] resultArray = (int[][]) args[1];
for (int i = 0; i < intArray[0].length; i++) {
if (intArray[0][i] * m != resultArray[0][i])
return false;
}
return true;
}
},
null
},
{ "copyIntArray",
new Object[] { intArray[0], new Long(intArray[0].length), resultArray },
copyIntArrayResultComparator,
null
},
{ "copyIntArray",
new Object[] { intArray[0], new Long(intArray[0].length - 2), resultArray },
copyIntArrayResultComparator,
"copyIntArray w/ smaller count"
},
{ "copyIntArray",
new Object[] { intArray[0], new Long(intArray[0].length + 2), resultArray },
arrayIOBExpComparator,
"copyIntArray w/ larger count"
},
{ "returnIntArray",
new Object[] { intArray[0], new Long(intArray[0].length) },
new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int[] inputArray = (int[]) args[0];
int[] resultArray = (int[]) result;
return Arrays.equals(resultArray, inputArray);
}
},
null
},
{ "returnIntArray",
new Object[] { intArray[0], new Long(intArray[0].length - 2) },
new IResultComparator() {
public boolean didPass(Object[] args, Object result, Exception e) {
if (e != null)
return false;
int[] inputArray = (int[]) args[0];
int inLength = ((Long) args[1]).intValue();
int[] resultArray = (int[]) result;
if (resultArray.length != inLength)
return false;
for (int i = 0; i < inLength; i++) {
if (resultArray[i] != inputArray[i])
return false;
}
return true;
}
},
"returnIntArray w/ smaller count"
},
{ "returnIntArray",
new Object[] { intArray[0], new Long(intArray[0].length + 2) },
arrayIOBExpComparator,
"returnIntArray w/ larger count"
},
{ "copyByteArray",
new Object[] { testBytes, new Long(testBytes.length), returnBytes },
new IResultComparator() {
public boolean didPass(Object[] args, Object result,
Exception e) {
if (e != null)
return false;
byte[] inArray = (byte[]) args[0];
byte[][] outArray = (byte[][]) args[2];
return Arrays.equals(inArray, outArray[0]);
}
},
null
},
{ "returnByteArray",
new Object[] { testBytes, new Long(testBytes.length) },
new IResultComparator() {
public boolean didPass(Object[] args, Object result,
Exception e) {
if (e != null)
return false;
byte[] inArray = (byte[]) args[0];
byte[] outArray = (byte[]) result;
return Arrays.equals(inArray, outArray);
}
},
null
},
{ "copySizedString",
new Object[] { testString, new Long(testString.length()), returnString },
stringComparator,
null
},
{ "returnSizedString",
new Object[] { testString, new Long(testString.length()) },
returnStringComparator,
null
},
{ "copySizedWString",
new Object[] { utf8String, new Long(utf8String.length()), returnString },
stringComparator,
null
},
{ "returnSizedWString",
new Object[] { utf8String, new Long(utf8String.length()) },
returnStringComparator,
null
},
};
runTestsArrayWithComparator(arrayTests, tests);
if (!succeeded) {
throw new RuntimeException("Array tests did not succeed");
}
}
}
class JavaTests implements nsIEcho, nsIXPCTestIn {
@ -646,14 +997,14 @@ class JavaTests implements nsIEcho, nsIXPCTestIn {
throw new XPCOMException(Mozilla.NS_ERROR_NOT_IMPLEMENTED);
}
public void sendInOutManyTypes(byte[] p1, short[] p2, int[] p3, long[] p4,
byte[] p5, int[] p6, long[] p7, double[] p8, float[] p9,
public void sendInOutManyTypes(short[] p1, short[] p2, int[] p3, long[] p4,
short[] p5, int[] p6, long[] p7, double[] p8, float[] p9,
double[] p10, boolean[] p11, char[] p12, char[] p13, String[] p14,
String[] p15, String[] p16) {
throw new XPCOMException(Mozilla.NS_ERROR_NOT_IMPLEMENTED);
}
public void sendManyTypes(byte p1, short p2, int p3, long p4, byte p5,
public void sendManyTypes(short p1, short p2, int p3, long p4, short p5,
int p6, long p7, double p8, float p9, double p10, boolean p11,
char p12, char p13, String p14, String p15, String p16) {
throw new XPCOMException(Mozilla.NS_ERROR_NOT_IMPLEMENTED);
@ -721,7 +1072,7 @@ class JavaTests implements nsIEcho, nsIXPCTestIn {
return ll;
}
public byte echoOctet(byte o) {
public short echoOctet(short o) {
return o;
}
@ -784,4 +1135,35 @@ class JavaTests implements nsIEcho, nsIXPCTestIn {
return wc;
}
public void copyIntArray(int[] srcArray, long count, int[][] dstArray) {
System.arraycopy(srcArray, 0, dstArray[0], 0, (int) count);
}
public void copySizedString(String srcString, long count, String[] dstString) {
dstString[0] = srcString.substring(0, (int) count);
}
public void multiplyEachItemInIntegerArray2(int val, int[][] valueArray,
long count) {
for(int i = 0; i < count; i++) {
valueArray[0][i] *= val;
}
}
public int[] returnIntArray(int[] srcArray, long count) {
int[] array = new int[(int) count];
System.arraycopy(srcArray, 0, array, 0, (int) count);
return array;
}
public String returnSizedString(String srcString, long count) {
return srcString.substring(0, (int) count);
}
}
interface IResultComparator {
boolean didPass(Object[] args, Object result, Exception e);
}

View File

@ -0,0 +1,72 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Java XPCOM Bindings.
*
* The Initial Developer of the Original Code is IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* IBM Corporation. All Rights Reserved.
*
* Contributor(s):
* Javier Pedemonte (jhpedemonte@gmail.com)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
[scriptable, uuid(fb520bac-92cf-4a6b-a2f3-eb63313d7d84)]
interface nsIJXTestArrayParams : nsISupports
{
void multiplyEachItemInIntegerArray2(
in PRInt32 val,
[array, size_is(count)] inout PRInt32 valueArray,
in PRUint32 count);
void copyIntArray([array, size_is(count)] in PRInt32 srcArray,
in PRUint32 count, [array, size_is(count)] out PRInt32 dstArray);
void returnIntArray([array, size_is(count)] in PRInt32 srcArray,
in PRUint32 count,
[retval, array, size_is(count)] out PRInt32 dstArray);
void copyByteArray([array, size_is(count)] in octet srcArray,
in PRUint32 count, [array, size_is(count)] out octet dstArray);
void returnByteArray([array, size_is(count)] in octet srcArray,
in PRUint32 count,
[retval, array, size_is(count)] out octet dstArray);
void copySizedString([size_is(count)] in string srcString,
in PRUint32 count, [size_is(count)] out string dstString);
void returnSizedString([size_is(count)] in string srcString,
in PRUint32 count, [retval, size_is(count)] out string dstString);
void copySizedWString([size_is(count)] in wstring srcString,
in PRUint32 count, [size_is(count)] out wstring dstString);
void returnSizedWString([size_is(count)] in wstring srcString,
in PRUint32 count, [retval, size_is(count)] out wstring dstString);
};

View File

@ -35,7 +35,7 @@
* ***** END LICENSE BLOCK ***** */
function logResult(testname, passed) {
dump(testname + "\t\t" + (passed ? "passed" : "FAILED") + "\n");
dump((passed ? "passed" : "FAILED") + ": " + testname + "\n");
}
function runTestsArray(callee, tests) {
@ -184,10 +184,8 @@ function runInTests(tests) {
[ "EchoChar", charZ, charZ, "EchoChar w/ " + charZ ],
[ "EchoBoolean", true, true, "EchoBoolean w/ " + true ],
[ "EchoBoolean", false, false, "EchoBoolean w/ " + false ],
/* XXX bug 367793
[ "EchoOctet", 0, 0, "EchoOctet w/ " + 0 ],
[ "EchoOctet", maxOctet, maxOctet, "EchoOctet w/ " + maxOctet ],
*/
[ "EchoLongLong", lowLong, lowLong, "EchoLongLong w/ " + lowLong ],
[ "EchoLongLong", highLong, highLong, "EchoLongLong w/ " + highLong ],
[ "EchoUnsignedShort", maxUShort, maxUShort,

View File

@ -41,6 +41,8 @@
const nsISupports = Components.interfaces.nsISupports;
const nsIEcho = Components.interfaces.nsIEcho;
const nsIXPCTestIn = Components.interfaces.nsIXPCTestIn;
const nsIXPCTestArray = Components.interfaces.nsIXPCTestArray;
const nsIJXTestArrayParams = Components.interfaces.nsIJXTestArrayParams;
const CLASS_ID = Components.ID("{9e45a36d-7cf7-4f2a-a415-d0b07e54945b}");
const CLASS_NAME = "XPConnect Tests in Javascript";
@ -64,6 +66,8 @@ XPCTests.prototype = {
QueryInterface: function(aIID) {
if (!aIID.equals(nsIEcho) &&
!aIID.equals(nsIXPCTestIn) &&
!aIID.equals(nsIXPCTestArray) &&
!aIID.equals(nsIJXTestArrayParams) &&
!aIID.equals(nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
@ -187,8 +191,80 @@ XPCTests.prototype = {
return i;
},
EchoVoid: function() {}
EchoVoid: function() {},
// ----------------------------------
// nsIXPCTestArray
// ----------------------------------
MultiplyEachItemInIntegerArray : function(val, len, a) {
for(var i = 0; i < len; i++)
a.value[i] *= val;
},
DoubleStringArray : function(len, a) {
var outArray = new Array();
for(var i = 0; i < len.value; i++) {
var inStr = a.value[i];
var outStr = new String();
for(var k = 0; k < inStr.length; k++) {
outStr += inStr[k];
outStr += inStr[k];
}
outArray.push(outStr);
outArray.push(outStr);
}
len.value *= 2;
a.value = outArray;
},
ReverseStringArray : function(len, a) {
for(var i = 0; i < len/2; i++) {
var temp = a.value[i];
a.value[i] = a.value[len-1-i];
a.value[len-1-i] = temp;
}
},
// ----------------------------------
// nsIJXTestArrayParams
// ----------------------------------
multiplyEachItemInIntegerArray2 : function(val, a, len) {
this.MultiplyEachItemInIntegerArray(val, len, a);
},
copyIntArray: function(srcArray, count, dstArray) {
dstArray.value = srcArray.slice();
},
returnIntArray: function(srcArray, count) {
return srcArray;
},
copyByteArray: function(srcArray, count, dstArray) {
dstArray.value = srcArray.slice();
},
returnByteArray: function(srcArray, count) {
return srcArray;
},
copySizedString: function(srcString, count, dstString) {
dstString.value = srcString.slice();
},
returnSizedString: function(srcString, count) {
return srcString;
},
copySizedWString: function(srcString, count, dstString) {
dstString.value = srcString.slice();
},
returnSizedWString: function(srcString, count) {
return srcString;
}
};
/***********************************************************

View File

@ -469,14 +469,10 @@ xpcom_to_java_type(TreeState *state, IDL_tree param)
break;
case IDLN_TYPE_OCTET:
/* If real type is 'PRUint8', promote to 'short' */
if (IDL_NODE_TYPE(state->tree) == IDLN_IDENT) {
if (strcmp(IDL_IDENT(state->tree).str, "PRUint8") == 0) {
fputs("short", state->file);
break;
}
}
fputs("byte", state->file);
if (param && IDL_tree_property_get(IDL_PARAM_DCL(param).simple_declarator, "array"))
fputs("byte", state->file);
else
fputs("short", state->file);
break;
case IDLN_TYPE_FLOAT: