/* 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); } }