/* Copyright (c) 2007 Wayne Meissner, All Rights Reserved
* Copyright (c) 2007-2013 Timothy Wall, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import junit.framework.TestCase;
public class PointerTest extends TestCase {
private static final String UNICODE = "[\u0444]";
public void testGetNativeLong() {
Memory m = new Memory(8);
if (NativeLong.SIZE == 4) {
final int MAGIC = 0xABEDCF23;
m.setInt(0, MAGIC);
NativeLong l = m.getNativeLong(0);
assertEquals("Native long mismatch", MAGIC, l.intValue());
} else {
final long MAGIC = 0x1234567887654321L;
m.setLong(0, MAGIC);
NativeLong l = m.getNativeLong(0);
assertEquals("Native long mismatch", MAGIC, l.longValue());
}
}
public void testSetNativeLong() {
Memory m = new Memory(8);
if (NativeLong.SIZE == 4) {
final int MAGIC = 0xABEDCF23;
m.setNativeLong(0, new NativeLong(MAGIC));
assertEquals("Native long mismatch", MAGIC, m.getInt(0));
} else {
final long MAGIC = 0x1234567887654321L;
m.setNativeLong(0, new NativeLong(MAGIC));
assertEquals("Native long mismatch", MAGIC, m.getLong(0));
}
}
public void testGetSetStringWithDefaultEncoding() throws Exception {
final String ENCODING = Native.DEFAULT_ENCODING;
String VALUE = getName();
int size = VALUE.getBytes(ENCODING).length+1;
Memory m = new Memory(size);
m.setString(0, VALUE);
assertEquals("Wrong decoded value", VALUE, m.getString(0));
}
public void testGetSetStringWithCustomEncoding() throws Exception {
final String ENCODING = "utf8";
String VALUE = getName() + UNICODE;
int size = VALUE.getBytes(ENCODING).length+1;
Memory m = new Memory(size);
m.setString(0, VALUE, ENCODING);
assertEquals("Wrong decoded value", VALUE, m.getString(0, ENCODING));
}
public static class TestPointerType extends PointerType {
public TestPointerType() { }
public TestPointerType(Pointer p) { super(p); }
}
public void testSetNativeMapped() {
Pointer p = new Memory(Pointer.SIZE);
TestPointerType tp = new TestPointerType(p);
p.setValue(0, tp, tp.getClass());
assertEquals("Wrong value written", p, p.getPointer(0));
}
public void testGetNativeMapped() {
Pointer p = new Memory(Pointer.SIZE);
p.setPointer(0, null);
Object o = p.getValue(0, TestPointerType.class, null);
assertNull("Wrong empty value: " + o, o);
p.setPointer(0, p);
TestPointerType tp = new TestPointerType(p);
assertEquals("Wrong value", tp, p.getValue(0, TestPointerType.class, null));
}
public void testGetStringArray() {
Pointer p = new Memory(Pointer.SIZE*3);
final String VALUE1 = getName() + UNICODE;
final String VALUE2 = getName() + "2" + UNICODE;
final String ENCODING = "utf8";
p.setPointer(0, new NativeString(VALUE1, ENCODING).getPointer());
p.setPointer(Pointer.SIZE, new NativeString(VALUE2, ENCODING).getPointer());
p.setPointer(Pointer.SIZE*2, null);
assertEquals("Wrong null-terminated String array",
Arrays.asList(new String[] { VALUE1, VALUE2 }),
Arrays.asList(p.getStringArray(0, ENCODING)));
assertEquals("Wrong length-specified String array (1)",
Arrays.asList(new String[] { VALUE1 }),
Arrays.asList(p.getStringArray(0, 1, ENCODING)));
assertEquals("Wrong length-specified String array (2)",
Arrays.asList(new String[] { VALUE1, VALUE2 }),
Arrays.asList(p.getStringArray(0, 2, ENCODING)));
}
public void testGetWideStringArray() {
Pointer p = new Memory(Pointer.SIZE*3);
final String VALUE1 = getName() + UNICODE;
final String VALUE2 = getName() + "2" + UNICODE;
p.setPointer(0, new NativeString(VALUE1, true).getPointer());
p.setPointer(Pointer.SIZE, new NativeString(VALUE2, true).getPointer());
p.setPointer(Pointer.SIZE*2, null);
assertEquals("Wrong null-terminated String array",
Arrays.asList(new String[] { VALUE1, VALUE2 }),
Arrays.asList(p.getWideStringArray(0)));
assertEquals("Wrong length-specified String array (1)",
Arrays.asList(new String[] { VALUE1 }),
Arrays.asList(p.getWideStringArray(0, 1)));
assertEquals("Wrong length-specified String array (2)",
Arrays.asList(new String[] { VALUE1, VALUE2 }),
Arrays.asList(p.getWideStringArray(0, 2)));
}
public void testReadPointerArray() {
Pointer mem = new Memory(Pointer.SIZE * 2);
Pointer[] p = new Pointer[2];
String VALUE1 = getName();
p[0] = new NativeString(VALUE1).getPointer();
p[1] = new Memory(1024);
Pointer[] orig = new Pointer[p.length];
System.arraycopy(p, 0, orig, 0, p.length);
mem.write(0, p, 0, p.length);
mem.read(0, p, 0, p.length);
assertSame("Pointer object not preserved[0]", orig[0], p[0]);
assertSame("Pointer object not preserved[1]", orig[1], p[1]);
mem.setPointer(0, null);
mem.setPointer(Pointer.SIZE, new Memory(1024));
mem.read(0, p, 0, p.length);
assertNull("Pointer element not updated[0]", p[0]);
assertNotSame("Pointer element not updated[1]", orig[1], p[1]);
}
public void testCreateConstantPointer() {
Pointer p = Pointer.createConstant(0xFFFFFFFF);
assertEquals("Wrong peer value", p.peer, 0xFFFFFFFF);
p = Pointer.createConstant(-1);
assertEquals("Wrong peer value", p.peer, -1);
}
public void testReadStringArrayNULLElement() {
Memory m = new Memory(Pointer.SIZE);
m.clear();
String[] arr = m.getStringArray(0, 1);
assertEquals("Wrong array size", 1, arr.length);
assertNull("Array element should be null", arr[0]);
}
private Object defaultArg(Class<?> type) {
if (type == boolean.class || type == Boolean.class) return Boolean.FALSE;
if (type == byte.class || type == Byte.class) return Byte.valueOf((byte)0);
if (type == char.class || type == Character.class) return Character.valueOf((char)0);
if (type == short.class || type == Short.class) return Short.valueOf((short)0);
if (type == int.class || type == Integer.class) return Integer.valueOf(0);
if (type == long.class || type == Long.class) return Long.valueOf(0L);
if (type == float.class || type == Float.class) return Float.valueOf(0);
if (type == double.class || type == Double.class) return Double.valueOf(0);
if (type == NativeLong.class) return new NativeLong(0);
return null;
}
public void testOpaquePointer() throws Exception {
Pointer p = Pointer.createConstant(0);
Class<?> cls = p.getClass();
Method[] methods = cls.getMethods();
for (int i=0;i < methods.length;i++) {
Method m = methods[i];
Class<?>[] argTypes = m.getParameterTypes();
try {
Object[] args = new Object[argTypes.length];
for (int arg=0;arg < args.length;arg++) {
args[arg] = defaultArg(argTypes[arg]);
}
if ("hashCode".equals(m.getName())
|| "equals".equals(m.getName())
|| m.getDeclaringClass() == Object.class
|| (m.getModifiers() & Modifier.STATIC) != 0) {
continue;
}
Object result = m.invoke(p, args);
if ("toString".equals(m.getName())) {
assertTrue("toString() should indicate const-ness", ((String)result).indexOf("const") != -1);
continue;
}
fail("Method '" + m.getName() + "(" + Arrays.asList(argTypes) + ")' should throw UnsupportedOperationException");
}
catch(InvocationTargetException e) {
assertEquals("Wrong exception type thrown by '" + m.getName() + "(" + Arrays.asList(argTypes) + ")", UnsupportedOperationException.class, e.getTargetException().getClass());
}
catch(IllegalArgumentException e) {
fail("Need to fix test of method '" + m.getName() + "(" + Arrays.asList(argTypes) + ")'");
}
}
}
public static void main(String[] args) {
junit.textui.TestRunner.run(PointerTest.class);
}
}