Skip to content

Commit

Permalink
re-enable WCE failing tests, fixes to allow proper phoneME operation …
Browse files Browse the repository at this point in the history
…w/r/t AWT classes
  • Loading branch information
twall committed Nov 9, 2011
1 parent d66e9e9 commit 816317b
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 70 deletions.
71 changes: 44 additions & 27 deletions src/com/sun/jna/Native.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Window;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import java.io.File;
import java.io.FilenameFilter;
import java.io.FileOutputStream;
Expand All @@ -32,8 +36,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
Expand Down Expand Up @@ -199,7 +201,7 @@ private Native() { }
* NOTE: On platforms which support signals (non-Windows), JNA uses
* signals to trap errors. This may interfere with the JVM's own use of
* signals. When protected mode is enabled, you should make use of the
* jsig library, if available (see <a href="http://java.sun.com/j2se/1.4.2/docs/guide/vm/signal-chaining.html">Signal Chaining</a>).
* jsig library, if available (see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html">Signal Chaining</a>).
* In short, set the environment variable <code>LD_PRELOAD</code> to the
* path to <code>libjsig.so</code> in your JRE lib directory
* (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your
Expand Down Expand Up @@ -237,7 +239,7 @@ private Native() { }
* @throws HeadlessException if the current VM is running headless
*/
public static long getWindowID(Window w) throws HeadlessException {
return getComponentID(w);
return AWT.getWindowID(w);
}

/** Utility method to get the native window ID for a heavyweight Java
Expand All @@ -247,25 +249,7 @@ public static long getWindowID(Window w) throws HeadlessException {
* @throws HeadlessException if the current VM is running headless
*/
public static long getComponentID(Component c) throws HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException("No native windows when headless");
}
if (c.isLightweight()) {
throw new IllegalArgumentException("Component must be heavyweight");
}
if (!c.isDisplayable())
throw new IllegalStateException("Component must be displayable");
// On X11 VMs prior to 1.5, the window must be visible
if (Platform.isX11()
&& System.getProperty("java.version").startsWith("1.4")) {
if (!c.isVisible()) {
throw new IllegalStateException("Component must be visible");
}
}
// By this point, we're certain that Toolkit.loadLibraries() has
// been called, thus avoiding AWT/JAWT link errors
// (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539705).
return getWindowHandle0(c);
return AWT.getComponentID(c);
}

/** Utility method to get the native window pointer for a Java
Expand All @@ -275,7 +259,7 @@ public static long getComponentID(Component c) throws HeadlessException {
* @throws HeadlessException if the current VM is running headless
*/
public static Pointer getWindowPointer(Window w) throws HeadlessException {
return getComponentPointer(w);
return new Pointer(AWT.getWindowID(w));
}

/** Utility method to get the native window pointer for a heavyweight Java
Expand All @@ -285,10 +269,10 @@ public static Pointer getWindowPointer(Window w) throws HeadlessException {
* @throws HeadlessException if the current VM is running headless
*/
public static Pointer getComponentPointer(Component c) throws HeadlessException {
return new Pointer(getComponentID(c));
return new Pointer(AWT.getComponentID(c));
}

private static native long getWindowHandle0(Component c);
static native long getWindowHandle0(Component c);

/** Convert a direct {@link Buffer} into a {@link Pointer}.
* @throws IllegalArgumentException if the buffer is not direct.
Expand Down Expand Up @@ -1721,7 +1705,7 @@ static Pointer getPointer(long addr) {
* Get a direct ByteBuffer mapped to the memory pointed to by the pointer.
* This method calls through to the JNA NewDirectByteBuffer method.
*
* @param addr byte offset from pointer to start the buffer
* @param addr base address of the JNA-originated memory
* @param length Length of ByteBuffer
* @return a direct ByteBuffer that accesses the memory being pointed to,
*/
Expand All @@ -1741,4 +1725,37 @@ static Pointer getPointer(long addr) {
public static void detach(boolean detach) {
setLastError(detach ? THREAD_DETACH : THREAD_LEAVE_ATTACHED);
}

/** Provides separation of JAWT functionality for the sake of J2ME
* ports which do not include AWT support.
*/
private static class AWT {
static long getWindowID(Window w) throws HeadlessException {
return getComponentID(w);
}
// Declaring the argument as Object rather than Component avoids class not
// found errors on phoneME foundation profile.
static long getComponentID(Object o) throws HeadlessException {
if (GraphicsEnvironment.isHeadless()) {
throw new HeadlessException("No native windows when headless");
}
Component c = (Component)o;
if (c.isLightweight()) {
throw new IllegalArgumentException("Component must be heavyweight");
}
if (!c.isDisplayable())
throw new IllegalStateException("Component must be displayable");
// On X11 VMs prior to 1.5, the window must be visible
if (Platform.isX11()
&& System.getProperty("java.version").startsWith("1.4")) {
if (!c.isVisible()) {
throw new IllegalStateException("Component must be visible");
}
}
// By this point, we're certain that Toolkit.loadLibraries() has
// been called, thus avoiding AWT/JAWT link errors
// (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539705).
return Native.getWindowHandle0(c);
}
}
}
9 changes: 9 additions & 0 deletions src/com/sun/jna/Platform.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public final class Platform {
public static final int WINDOWSCE = 6;

public static final boolean HAS_BUFFERS;
public static final boolean HAS_AWT;
public static final String MATH_LIBRARY_NAME;
public static final String C_LIBRARY_NAME;

Expand Down Expand Up @@ -52,6 +53,14 @@ else if (osName.startsWith("OpenBSD")) {
else {
osType = UNSPECIFIED;
}
boolean hasAWT = false;
try {
Class.forName("java.awt.Component");
hasAWT = true;
}
catch(ClassNotFoundException e) {
}
HAS_AWT = hasAWT;
boolean hasBuffers = false;
try {
Class.forName("java.nio.Buffer");
Expand Down
24 changes: 16 additions & 8 deletions src/com/sun/jna/Structure.java
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,25 @@ Object getField(StructField structField) {
}
}

// WARNING: phoneME fails to set a 'final' field even after calling
// setAccessible(true) on the field
void setField(StructField structField, Object value) {
setField(structField, value, false);
}

void setField(StructField structField, Object value, boolean overrideFinal) {
try {
structField.field.set(this, value);
}
catch(IllegalAccessException e) {
if (Modifier.isFinal(structField.field.getModifiers())) {
throw new UnsupportedOperationException("Read-only (final) structure fields may only be updated from native memory (field '" + structField.name + "' within " + getClass() + ")");
int modifiers = structField.field.getModifiers();
if (Modifier.isFinal(modifiers)) {
if (overrideFinal) {
// WARNING: setAccessible(true) on phoneME does *not* allow overwriting of
// a final field. It also ignores any changes made to the
// field's modifiers (temporarily removing the final flag
// on the field does not work).
throw new UnsupportedOperationException("This VM does not support Structures with final fields (field '" + structField.name + "' within " + getClass() + ")");
}
throw new UnsupportedOperationException("Attempt to write to read-only field '" + structField.name + "' within " + getClass());
}
throw new Error("Unexpectedly unable to write to field '"
+ structField.name + "' within " + getClass()
Expand Down Expand Up @@ -560,10 +570,7 @@ Object readField(StructField structField) {
}

// Update the value on the field
if (Modifier.isFinal(structField.field.getModifiers())) {
structField.field.setAccessible(true);
}
setField(structField, result);
setField(structField, result, true);
return result;
}

Expand Down Expand Up @@ -785,6 +792,7 @@ int calculateSize(boolean force) {
structField.isVolatile = Modifier.isVolatile(modifiers);
structField.isReadOnly = Modifier.isFinal(modifiers);
if (Modifier.isFinal(modifiers)) {
// In most cases, this allows overriding the value of final fields
field.setAccessible(true);
}
structField.field = field;
Expand Down
2 changes: 1 addition & 1 deletion src/com/sun/jna/overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ <h2>Library Global Data</h2>
<a name="crash-protection"></a>
<h2>VM Crash Protection</h2>
It is not uncommon when defining a new library and writing tests to encounter memory access errors which crash the VM. These are often caused by improper mappings or invalid arguments passed to the native library. To generate Java errors instead of crashing the VM, call {@link com.sun.jna.Native#setProtected Native.setProtected(true)}</code>. Not all platforms support this protection; if not, the value of {@link com.sun.jna.Native#isProtected} will remain <code>false</code>.<p>
NOTE: When protected mode is enabled, you should make use of the jsig library, if available (see <a href="http://download.oracle.com/javase/6/docs/technotes/guides//vm/signal-chaining.htmld">Signal Chaining</a>) to avoid interfering with the JVM's use of signals. In short, set the environment variable <code>LD_PRELOAD</code> (or <code>LD_PRELOAD_64</code>) to the path to <code>libjsig.so</code> in your JRE lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your Java application.
NOTE: When protected mode is enabled, you should make use of the jsig library, if available (see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html">Signal Chaining</a>) to avoid interfering with the JVM's use of signals. In short, set the environment variable <code>LD_PRELOAD</code> (or <code>LD_PRELOAD_64</code>) to the path to <code>libjsig.so</code> in your JRE lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your Java application.


<p>
Expand Down
3 changes: 1 addition & 2 deletions test/com/sun/jna/ArgumentsMarshalTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,7 @@ public void testDisableAutoSynch() {
assertEquals("Auto read should be disabled", EXPECTED, s.field);
}

// w32ce crash
public void XFAIL_WCE_testUnionByValueCallbackArgument() throws Exception{
public void testUnionByValueCallbackArgument() throws Exception{
TestLibrary.TestUnion arg = new TestLibrary.TestUnion();
arg.setType(String.class);
final String VALUE = getName();
Expand Down
5 changes: 2 additions & 3 deletions test/com/sun/jna/CallbacksTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ public String callback(String arg) {
assertEquals("Wrong String return", VALUE, value);
}

public void XFAIL_WCE_testStringCallbackMemoryReclamation() throws InterruptedException {
public void testStringCallbackMemoryReclamation() throws InterruptedException {
TestLibrary.StringCallback cb = new TestLibrary.StringCallback() {
public String callback(String arg) {
return arg;
Expand Down Expand Up @@ -623,8 +623,7 @@ public int callback(int arg, IntByReference result) {
assertEquals("Wrong value in by reference memory", VALUE, ref.getValue());
}

// crash
public void XFAIL_WCE_testCallCallbackWithStructByValue() {
public void testCallCallbackWithStructByValue() {
final TestStructure.ByValue s = new TestStructure.ByValue();
final TestStructure innerResult = new TestStructure();
TestStructure.TestCallback cb = new TestStructure.TestCallback() {
Expand Down
48 changes: 30 additions & 18 deletions test/com/sun/jna/LibraryLoadTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,26 @@ public class LibraryLoadTest extends TestCase {
+ (Platform.is64Bit() ? "-d64" : ""));

public void testLoadJNALibrary() {
assertTrue("Point size should never be zero", Pointer.SIZE > 0);
assertTrue("Pointer size should never be zero", Pointer.SIZE > 0);
}

public void testLoadJAWT() {
if (!Platform.HAS_AWT) return;

if (GraphicsEnvironment.isHeadless()) return;

Frame f = new Frame(getName());
f.pack();
try {
// FIXME: this works as a test, but fails in ShapedWindowDemo
// if the JAWT load workaround is not used
Native.getWindowPointer(f);
}
finally {
f.dispose();
// Encapsulate in a separate class to avoid class loading issues where
// AWT is unavailable
AWT.loadJAWT(getName());
}

public void testLoadAWTAfterJNA() {
if (!Platform.HAS_AWT) return;

if (GraphicsEnvironment.isHeadless()) return;

if (Pointer.SIZE > 0) {
Toolkit.getDefaultToolkit();
}
}

Expand All @@ -56,14 +61,6 @@ public static interface CLibrary extends Library {
int geteuid();
}

public void testLoadAWTAfterJNA() {
if (GraphicsEnvironment.isHeadless()) return;

if (Pointer.SIZE > 0) {
Toolkit.getDefaultToolkit();
}
}

private Object load() {
return Native.loadLibrary(Platform.C_LIBRARY_NAME, CLibrary.class);
}
Expand Down Expand Up @@ -162,6 +159,21 @@ public void testLoadProperCLibraryVersion() {
lib.getpwuid(lib.geteuid()));
}

private static class AWT {
public static void loadJAWT(String name) {
Frame f = new Frame(name);
f.pack();
try {
// FIXME: this works as a test, but fails in ShapedWindowDemo
// if the JAWT load workaround is not used
Native.getWindowPointer(f);
}
finally {
f.dispose();
}
}
}

public static void main(String[] args) {
junit.textui.TestRunner.run(LibraryLoadTest.class);
}
Expand Down
15 changes: 8 additions & 7 deletions test/com/sun/jna/NativeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class NativeTest extends TestCase {

public void testLongStringGeneration() {
StringBuffer buf = new StringBuffer();
final int MAX = 2000000;
final int MAX = Platform.isWindowsCE() ? 200000 : 2000000;
for (int i=0;i < MAX;i++) {
buf.append('a');
}
Expand Down Expand Up @@ -345,21 +345,22 @@ public static void main(String[] args) {
if (args.length == 1 && "all".equals(args[0])) {
args = new String[] {
"com.sun.jna.NativeTest",
"com.sun.jna.NativeLibraryTest",
"com.sun.jna.NativeLibraryTest", // 1 wce failure
"com.sun.jna.PointerTest",
"com.sun.jna.MemoryTest",
"com.sun.jna.LibraryLoadTest",
"com.sun.jna.ArgumentsMarshalTest",
"com.sun.jna.ReturnTypesTest",
"com.sun.jna.ReturnTypesTest",
"com.sun.jna.TypeMapperTest",
"com.sun.jna.ByReferenceArgumentsTest",
"com.sun.jna.LastErrorTest",
"com.sun.jna.StructureTest",
"com.sun.jna.StructureTest",// 1 wce failure (ro)
"com.sun.jna.StructureByValueTest",
"com.sun.jna.UnionTest",
"com.sun.jna.IntegerTypeTest",
"com.sun.jna.VMCrashProtectionTest",
"com.sun.jna.CallbacksTest",
"com.sun.jna.CallbacksTest", // 1 wce failure (String
// memory reclamation)
"com.sun.jna.JNAUnloadTest",
"com.sun.jna.DirectTest",
"com.sun.jna.DirectArgumentsMarshalTest",
Expand All @@ -376,8 +377,8 @@ public static void main(String[] args) {
try {
junit.textui.TestRunner.run(Class.forName(args[i]));
}
catch(ClassNotFoundException e) {
System.err.println("No such class: " + args[i]);
catch(Throwable e) {
e.printStackTrace();
}
}
try { Thread.sleep(300000); } catch(Exception e) { }
Expand Down
3 changes: 1 addition & 2 deletions test/com/sun/jna/ReturnTypesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,7 @@ public void testInvokeNullStructure() {
assertNull("Expect null structure return", s);
}

// w32ce crash
public void XFAIL_WCE_testReturnSmallStructureByValue() {
public void testReturnSmallStructureByValue() {
TestSmallStructure s = lib.returnSmallStructureByValue();
assertNotNull("Returned structure must not be null", s);
assertEquals("Wrong char field value (1)", 1, s.c1);
Expand Down
2 changes: 1 addition & 1 deletion test/com/sun/jna/StructureTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ private ROStructure avoidConstantFieldOptimization(ROStructure s) {
return s;
}

// This functionality is no longer supported
// wce/phoneME fails to write final field
public void testReadOnlyField() {
ROStructure s = new ROStructure();
s.getPointer().setInt(0, 42);
Expand Down
2 changes: 1 addition & 1 deletion w32ce-test.lnk
Original file line number Diff line number Diff line change
@@ -1 +1 @@
255#"\storage card\phoneme\personal\bin\cvm.exe" -Djna.boot.library.path="\storage card" -Djna.library.path="\storage card" -cp "\storage card\test.jar;\storage card\junit.jar" com.sun.jna.NativeTest com.sun.jna.LibraryLoadTest
255#"\storage card\phoneme\personal\bin\cvm.exe" -Djna.boot.library.path="\storage card" -Djna.library.path="\storage card" -cp "\storage card\test.jar;\storage card\junit.jar" com.sun.jna.NativeTest all

0 comments on commit 816317b

Please sign in to comment.