/* Copyright (c) 2007 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.util.List;
import junit.framework.TestCase;
//@SuppressWarnings("unused")
public class UnionTest extends TestCase {
public static class TestStructure extends Structure {
public static final List<String> FIELDS = createFieldsOrder("value");
public String value;
@Override
protected List<String> getFieldOrder() {
return FIELDS;
}
}
public static class BigTestStructure extends Structure {
public static final List<String> FIELDS = createFieldsOrder("field1", "field2");
public long field1;
public long field2;
@Override
protected List<String> getFieldOrder() {
return FIELDS;
}
}
public static class IntStructure extends Structure {
public static final List<String> FIELDS = createFieldsOrder("value");
public int value;
@Override
protected List<String> getFieldOrder() {
return FIELDS;
}
}
public static class SubIntStructure extends IntStructure {}
public static interface Func1 extends Callback {
public void callback();
}
public static class SizedUnion extends Union {
public byte byteField;
public short shortField;
public int intField;
public long longField;
public TestStructure structField;
public BigTestStructure structField2;
public String string;
public WString wstring;
public Pointer pointer;
}
public static class StructUnion extends Union {
public int intField;
public TestStructure testStruct;
public IntStructure intStruct;
public Func1 func1;
}
public void testCalculateSize() {
Union u = new SizedUnion();
assertEquals("Wrong union size: " + u, 16, u.size());
assertEquals("Union should be size of largest field",
new BigTestStructure().size(), u.size());
}
public void testFieldOffsets() {
StructUnion u = new StructUnion();
assertEquals("Wrong union size: " + u, Pointer.SIZE, u.size());
u.setType(u.testStruct.getClass());
u.write();
assertEquals("Wrong struct member base address",
u.getPointer(), u.testStruct.getPointer());
u.setType(u.intStruct.getClass());
u.write();
assertEquals("Wrong struct member base address (2)",
u.getPointer(), u.intStruct.getPointer());
}
public void testWriteUnion() {
SizedUnion u = new SizedUnion();
final int VALUE = 0x12345678;
u.intField = VALUE;
u.setType(int.class);
u.write();
assertEquals("Wrong value written", VALUE, u.getPointer().getInt(0));
}
public void testReadUnion() {
SizedUnion u = new SizedUnion();
final int VALUE = 0x12345678;
u.getPointer().setInt(0, VALUE);
u.read();
assertEquals("int field not read properly", VALUE, u.intField);
assertTrue("byte field not read", u.byteField != 0);
assertTrue("short field not read", u.shortField != 0);
assertTrue("long field not read", u.longField != 0);
assertNotNull("Unselected Pointer not read", u.pointer);
assertNotNull("Union struct field should be initialized", u.structField);
assertNull("Unselected structure should not be read", u.structField.value);
assertNull("Unselected String should be null", u.string);
assertNull("Unselected WString should be null", u.wstring);
}
public void testWriteTypedUnion() {
final int VALUE = 0x12345678;
// write an instance of a direct union class to memory
StructUnion u = new StructUnion();
assertEquals("Wrong union size: " + u, Pointer.SIZE, u.size());
IntStructure intStruct = new IntStructure();
intStruct.value = VALUE;
u.setTypedValue(intStruct);
u.write();
assertEquals("Wrong value written", VALUE, u.getPointer().getInt(0));
// write an instance of a sub class of an union class to memory
u = new StructUnion();
SubIntStructure subIntStructure = new SubIntStructure();
subIntStructure.value = VALUE;
u.setTypedValue(subIntStructure);
u.write();
assertEquals("Wrong value written", VALUE, u.getPointer().getInt(0));
// write an instance of an interface
u = new StructUnion();
Func1 func1 = new Func1() {
@Override
public void callback() {
System.out.println("hi");
}
};
u.setTypedValue(func1);
}
public void testReadTypedUnion() {
StructUnion u = new StructUnion();
assertEquals("Wrong union size: " + u, Pointer.SIZE, u.size());
final int VALUE = 0x12345678;
u.getPointer().setInt(0, VALUE);
assertEquals("int structure not read properly", VALUE, ((IntStructure) u.getTypedValue(IntStructure.class)).value);
}
public void testReadTypeInfo() {
SizedUnion u = new SizedUnion();
assertEquals("Wrong union size: " + u, 16, u.size());
assertNotNull("Type information is missing for union field of type " + BigTestStructure.class, Structure.getTypeInfo(BigTestStructure.class));
assertNotNull("Type information is missing for union instance", u.getTypeInfo());
if (Native.POINTER_SIZE == 4) {
assertEquals("Type size should be that of largest field if no field is active",
Structure.getTypeInfo(BigTestStructure.class).getInt(0),
u.getTypeInfo().getInt(0));
}
else {
assertEquals("Type size should be that of largest field if no field is active",
Structure.getTypeInfo(BigTestStructure.class).getLong(0),
u.getTypeInfo().getLong(0));
}
u.setType(int.class);
assertNotNull("Type information is missing for union field of type " + BigTestStructure.class, Structure.getTypeInfo(BigTestStructure.class));
assertNotNull("Type information is missing for union instance after type set", u.getTypeInfo());
if (Native.POINTER_SIZE == 4) {
assertEquals("Type size should be that of largest field if any field is active",
Structure.getTypeInfo(BigTestStructure.class).getInt(0),
u.getTypeInfo().getInt(0));
}
else {
assertEquals("Type size should be that of largest field if any field is active",
Structure.getTypeInfo(BigTestStructure.class).getLong(0),
u.getTypeInfo().getLong(0));
}
}
public void testArraysInUnion() {
class TestUnion extends Union {
public byte[] bytes = new byte[16];
public short[] shorts = new short[8];
public int[] ints = new int[4];
}
Union u = new TestUnion();
assertEquals("Wrong union size: " + u, 16, u.size());
u.setType(byte[].class);
u.setType(short[].class);
u.setType(int[].class);
}
public void testDuplicateFieldTypes() {
class TestUnion extends Union {
public int field1;
public int field2;
}
TestUnion u = new TestUnion();
assertEquals("Wrong union size: " + u, 4, u.size());
u.setType("field1");
u.field1 = 42;
u.write();
u.setType("field2");
u.read();
assertEquals("Wrong field value after write/read", 42, u.field2);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(UnionTest.class);
}
}