/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
import com.sun.jna.ReturnTypesTest.TestLibrary.SimpleStructure;
import com.sun.jna.ReturnTypesTest.TestLibrary.TestStructure;
import com.sun.jna.ReturnTypesTest.TestLibrary.TestSmallStructure;
/** Exercise a range of native methods.
*
* @author twall@users.sf.net
*/
public class ReturnTypesTest extends TestCase {
private static final double DOUBLE_MAGIC = -118.625d;
private static final float FLOAT_MAGIC = -118.625f;
public static interface TestLibrary extends Library {
public static class SimpleStructure extends Structure {
public double value;
}
public static class TestSmallStructure extends Structure {
public static class ByValue extends TestSmallStructure implements Structure.ByValue { }
public byte c1;
public byte c2;
public short s;
}
public static class TestStructure extends Structure {
public static class ByValue extends TestStructure implements Structure.ByValue { }
public byte c;
public short s;
public int i;
public long j;
public SimpleStructure inner;
}
class CheckFieldAlignment extends Structure {
public int int32Field = 1;
public long int64Field = 2;
public float floatField = 3f;
public double doubleField = 4d;
}
class TestObject { }
Object returnObjectArgument(Object s);
TestObject returnObjectArgument(TestObject s);
boolean returnFalse();
boolean returnTrue();
int returnInt32Zero();
int returnInt32Magic();
long returnInt64Zero();
long returnInt64Magic();
NativeLong returnLongZero();
NativeLong returnLongMagic();
float returnFloatZero();
float returnFloatMagic();
double returnDoubleZero();
double returnDoubleMagic();
String returnStringMagic();
WString returnWStringMagic();
SimpleStructure returnStaticTestStructure();
SimpleStructure returnNullTestStructure();
TestSmallStructure.ByValue returnSmallStructureByValue();
TestStructure.ByValue returnStructureByValue();
Pointer[] returnPointerArgument(Pointer[] arg);
String[] returnPointerArgument(String[] arg);
WString[] returnPointerArgument(WString[] arg);
}
TestLibrary lib;
protected void setUp() {
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class);
}
protected void tearDown() {
lib = null;
}
public void testReturnObject() throws Exception {
Map options = new HashMap() { {
put(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE);
}};
lib = (TestLibrary)Native.loadLibrary("testlib", TestLibrary.class, options);
assertNull("null value not returned", lib.returnObjectArgument(null));
final Object VALUE = new Object() {
public String toString() {
return getName();
}
};
assertEquals("Wrong object returned", VALUE, lib.returnObjectArgument(VALUE));
}
public void testReturnObjectUnsupported() throws Exception {
try {
lib.returnObjectArgument(new TestLibrary.TestObject());
fail("Java Object return is not supported, should throw IllegalArgumentException");
}
catch(IllegalArgumentException e) {
assertTrue("Exception should include return object type: " + e,
e.getMessage().indexOf(TestLibrary.TestObject.class.getName()) != -1);
}
catch(Throwable e) {
fail("Method declared with Java Object return should throw IllegalArgumentException, not " + e);
}
}
public void testInvokeBoolean() {
assertFalse("Expect false", lib.returnFalse());
assertTrue("Expect true", lib.returnTrue());
}
public void testInvokeInt() {
assertEquals("Expect 32-bit zero", 0, lib.returnInt32Zero());
assertEquals("Expect 32-bit magic",
"12345678",
Integer.toHexString(lib.returnInt32Magic()));
}
public void testInvokeLong() {
assertEquals("Expect 64-bit zero", 0L, lib.returnInt64Zero());
assertEquals("Expect 64-bit magic",
"123456789abcdef0",
Long.toHexString(lib.returnInt64Magic()));
}
public void testInvokeNativeLong() {
if (NativeLong.SIZE == 4) {
assertEquals("Expect 32-bit zero", new NativeLong(0), lib.returnLongZero());
assertEquals("Expect 32-bit magic",
"12345678",
Integer.toHexString(lib.returnLongMagic().intValue()));
} else {
assertEquals("Expect 64-bit zero", new NativeLong(0L),
lib.returnLongZero());
assertEquals("Expect 64-bit magic",
"123456789abcdef0",
Long.toHexString(lib.returnLongMagic().longValue()));
}
}
public interface NativeMappedLibrary extends Library {
Custom returnInt32Argument(int arg);
}
public static class Custom implements NativeMapped {
private int value;
public Custom() { }
public Custom(int value) {
this.value = value;
}
public Object fromNative(Object nativeValue, FromNativeContext context) {
return new Custom(((Integer)nativeValue).intValue());
}
public Class nativeType() {
return Integer.class;
}
public Object toNative() {
return new Integer(value);
}
public boolean equals(Object o) {
return o instanceof Custom && ((Custom)o).value == value;
}
}
protected NativeMappedLibrary loadNativeMappedLibrary() {
return (NativeMappedLibrary)
Native.loadLibrary("testlib", NativeMappedLibrary.class);
}
public void testInvokeNativeMapped() {
NativeMappedLibrary lib = loadNativeMappedLibrary();
final int MAGIC = 0x12345678;
final Custom EXPECTED = new Custom(MAGIC);
assertEquals("Argument not mapped", EXPECTED, lib.returnInt32Argument(MAGIC));
}
public void testInvokeFloat() {
assertEquals("Expect float zero", 0f, lib.returnFloatZero(), 0d);
assertEquals("Expect float magic",
FLOAT_MAGIC, lib.returnFloatMagic(), 0d);
}
public void testInvokeDouble() {
assertEquals("Expect double zero", 0d, lib.returnDoubleZero(), 0d);
assertEquals("Expect double magic",
DOUBLE_MAGIC, lib.returnDoubleMagic(), 0d);
}
static final String MAGIC = "magic";
public void testInvokeString() {
assertEquals("Expect String magic", MAGIC, lib.returnStringMagic());
}
public void testInvokeWString() {
WString s = lib.returnWStringMagic();
assertEquals("Wrong length", MAGIC.length(), s.toString().length());
assertEquals("Expect WString magic", new WString(MAGIC), s);
}
public void testInvokeStructure() {
SimpleStructure s = lib.returnStaticTestStructure();
assertEquals("Expect test structure magic", DOUBLE_MAGIC, s.value, 0d);
}
public void testInvokeNullStructure() {
SimpleStructure s = lib.returnNullTestStructure();
assertNull("Expect null structure return", s);
}
public void testReturnSmallStructureByValue() {
TestSmallStructure s = lib.returnSmallStructureByValue();
assertNotNull("Returned structure must not be null", s);
assertEquals("Wrong char field value (1)", 1, s.c1);
assertEquals("Wrong char field value (2)", 2, s.c2);
assertEquals("Wrong short field value", 3, s.s);
}
public void testReturnStructureByValue() {
TestStructure s = lib.returnStructureByValue();
assertNotNull("Returned structure must not be null", s);
assertEquals("Wrong char field value", 1, s.c);
assertEquals("Wrong short field value", 2, s.s);
assertEquals("Wrong int field value", 3, s.i);
assertEquals("Wrong long field value", 4, s.j);
assertNotNull("Structure not initialized", s.inner);
assertEquals("Wrong inner structure value", 5, s.inner.value, 0);
}
public void testReturnPointerArray() {
Pointer value = new Memory(10);
Pointer[] input = {
value, null,
};
Pointer[] result = lib.returnPointerArgument(input);
assertEquals("Wrong array length", input.length-1, result.length);
assertEquals("Wrong array element value", value, result[0]);
}
public void testReturnStringArray() {
String value = getName();
String[] input = {
value, null,
};
String[] result = lib.returnPointerArgument(input);
assertEquals("Wrong array length", input.length-1, result.length);
assertEquals("Wrong array element value", value, result[0]);
}
public void testReturnWStringArray() {
WString value = new WString(getName());
WString[] input = {
value, null,
};
WString[] result = lib.returnPointerArgument(input);
assertEquals("Wrong array length", input.length-1, result.length);
assertEquals("Wrong array element value", value, result[0]);
}
public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(ReturnTypesTest.class);
}
}