diff --git a/jme3-desktop/src/test/java/LibraryLoaderTest.java b/jme3-core/src/test/java/com/jme3/IntegrationTest.java similarity index 81% rename from jme3-desktop/src/test/java/LibraryLoaderTest.java rename to jme3-core/src/test/java/com/jme3/IntegrationTest.java index 4b3833a8a..22d6f3d95 100644 --- a/jme3-desktop/src/test/java/LibraryLoaderTest.java +++ b/jme3-core/src/test/java/com/jme3/IntegrationTest.java @@ -29,22 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +package com.jme3; -import com.jme3.system.NativeLibraryLoader; -import java.io.File; -import java.util.Arrays; -import org.junit.Test; - -/** - * - * @author Kirill Vainer - */ -public class LibraryLoaderTest { - - @Test - public void whatever() { - File[] nativeJars = NativeLibraryLoader.getJarsWithNatives(); - System.out.println(Arrays.toString(nativeJars)); - } - +public interface IntegrationTest { } diff --git a/jme3-core/src/test/java/com/jme3/app/AppSettingsIT.java b/jme3-core/src/test/java/com/jme3/app/AppSettingsIT.java new file mode 100644 index 000000000..7657d149a --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/app/AppSettingsIT.java @@ -0,0 +1,60 @@ +package com.jme3.app; + +import com.jme3.IntegrationTest; +import com.jme3.scene.Mesh; +import com.jme3.system.AppSettings; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.prefs.BackingStoreException; +import org.junit.Test; + +import static org.junit.Assert.*; +import org.junit.experimental.categories.Category; + +@Category(IntegrationTest.class) +public class AppSettingsIT { + + private static final String APPSETTINGS_KEY = "JME_AppSettingsTest"; + + @Test + public void testPreferencesSaveLoad() throws BackingStoreException { + AppSettings settings = new AppSettings(false); + settings.putBoolean("TestBool", true); + settings.putInteger("TestInt", 123); + settings.putString("TestStr", "HelloWorld"); + settings.putFloat("TestFloat", 123.567f); + settings.put("TestObj", new Mesh()); // Objects not supported by preferences + settings.save(APPSETTINGS_KEY); + + AppSettings loadedSettings = new AppSettings(false); + loadedSettings.load(APPSETTINGS_KEY); + + assertEquals(true, loadedSettings.getBoolean("TestBool")); + assertEquals(123, loadedSettings.getInteger("TestInt")); + assertEquals("HelloWorld", loadedSettings.getString("TestStr")); + assertEquals(123.567f, loadedSettings.get("TestFloat")); + } + + @Test + public void testStreamSaveLoad() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + AppSettings settings = new AppSettings(false); + settings.putBoolean("TestBool", true); + settings.putInteger("TestInt", 123); + settings.putString("TestStr", "HelloWorld"); + settings.putFloat("TestFloat", 123.567f); + settings.put("TestObj", new Mesh()); // Objects not supported by file settings + settings.save(baos); + + AppSettings loadedSettings = new AppSettings(false); + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + loadedSettings.load(bais); + + assertEquals(true, loadedSettings.getBoolean("TestBool")); + assertEquals(123, loadedSettings.getInteger("TestInt")); + assertEquals("HelloWorld", loadedSettings.getString("TestStr")); + assertEquals(123.567f, loadedSettings.get("TestFloat")); + } +} diff --git a/jme3-core/src/test/java/com/jme3/app/ApplicationTest.java b/jme3-core/src/test/java/com/jme3/app/ApplicationTest.java new file mode 100644 index 000000000..e046f773f --- /dev/null +++ b/jme3-core/src/test/java/com/jme3/app/ApplicationTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2009-2015 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.app; + +import com.jme3.system.AppSettings; +import com.jme3.system.JmeContext.Type; +import com.jme3.system.JmeSystem; +import com.jme3.system.JmeSystemDelegate; +import com.jme3.system.NullContext; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import static org.mockito.Mockito.*; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ApplicationTest { + + @Before + public void setUp() { + Logger.getLogger("com.jme3").setLevel(Level.OFF); + } + + private static class NullDisplayContext extends NullContext { + + @Override + public Type getType() { + return Type.Display; + } + } + + @Test + public void testExceptionInvokesHandleError() throws InterruptedException { + JmeSystemDelegate del = mock(JmeSystemDelegate.class); + JmeSystem.setSystemDelegate(del); + + Application app = new Application() { + @Override + public void update() { + super.update(); + throw new IllegalStateException("Some Error"); + } + }; + + when(del.newContext((AppSettings) anyObject(), eq(Type.Display))).thenReturn(new NullDisplayContext()); + + app.start(true); + app.stop(true); + + verify(del).showErrorDialog(anyString()); + } +} diff --git a/jme3-desktop/build.gradle b/jme3-desktop/build.gradle index 0a77d7d72..d03de1eed 100644 --- a/jme3-desktop/build.gradle +++ b/jme3-desktop/build.gradle @@ -4,4 +4,5 @@ if (!hasProperty('mainClass')) { dependencies { compile project(':jme3-core') + testCompile project(path: ':jme3-core', configuration: 'testOutput') } diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java index 707937e78..f9259f277 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java +++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java @@ -35,6 +35,8 @@ import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -44,9 +46,9 @@ import java.util.logging.Logger; /** * Utility class to register, extract, and load native libraries. *
- * Register your own libraries via the {@link #registerNativeLibrary(String, Platform, String, String)} method, for - * each platform. - * You can then extract this library (depending on platform), by + * Register your own libraries via the + * {@link #registerNativeLibrary(String, Platform, String, String)} method, for + * each platform. You can then extract this library (depending on platform), by * using {@link #loadNativeLibrary(java.lang.String, boolean) }. *
* Example:
@@ -62,80 +64,82 @@ import java.util.logging.Logger; * This will register the library. Load it via:
*
  * NativeLibraryLoader.loadNativeLibrary("mystuff", true);
- * 
- * It will load the right library automatically based on the platform. - * + * It will load the right library automatically based on the + * platform. + * * @author Kirill Vainer */ public final class NativeLibraryLoader { - + private static final Logger logger = Logger.getLogger(NativeLibraryLoader.class.getName()); private static final byte[] buf = new byte[1024 * 100]; private static File extractionFolderOverride = null; private static File extractionFolder = null; - + private static final HashMap nativeLibraryMap = new HashMap(); - + /** * Register a new known library. - * + * * This simply registers a known library, the actual extraction and loading - * is performed by calling {@link #loadNativeLibrary(java.lang.String, boolean) }. - * - * @param name The name / ID of the library (not OS or architecture specific). - * @param platform The platform for which the in-natives-jar path has - * been specified for. - * @param path The path inside the natives-jar or classpath - * corresponding to this library. Must be compatible with the platform - * argument. - * @param extractAsName The filename that the library should be extracted as, - * if null, use the same name as in the path. + * is performed by calling {@link #loadNativeLibrary(java.lang.String, boolean) + * }. + * + * @param name The name / ID of the library (not OS or architecture + * specific). + * @param platform The platform for which the in-natives-jar path has been + * specified for. + * @param path The path inside the natives-jar or classpath corresponding to + * this library. Must be compatible with the platform argument. + * @param extractAsName The filename that the library should be extracted + * as, if null, use the same name as in the path. */ public static void registerNativeLibrary(String name, Platform platform, String path, String extractAsName) { nativeLibraryMap.put(new NativeLibrary.Key(name, platform), new NativeLibrary(name, platform, path, extractAsName)); } - + /** * Register a new known JNI library. - * + * * This simply registers a known library, the actual extraction and loading - * is performed by calling {@link #loadNativeLibrary(java.lang.String, boolean) }. - * - * This method should be called several times for each library name, - * each time specifying a different platform + path combination. - * - * @param name The name / ID of the library (not OS or architecture specific). - * @param platform The platform for which the in-natives-jar path has - * been specified for. - * @param path The path inside the natives-jar or classpath - * corresponding to this library. Must be compatible with the platform - * argument. + * is performed by calling {@link #loadNativeLibrary(java.lang.String, boolean) + * }. + * + * This method should be called several times for each library name, each + * time specifying a different platform + path combination. + * + * @param name The name / ID of the library (not OS or architecture + * specific). + * @param platform The platform for which the in-natives-jar path has been + * specified for. + * @param path The path inside the natives-jar or classpath corresponding to + * this library. Must be compatible with the platform argument. */ public static void registerNativeLibrary(String name, Platform platform, String path) { registerNativeLibrary(name, platform, path, null); } - + static { // LWJGL registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll"); registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll"); - registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so"); - registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so"); - registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); - registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); + registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so"); + registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so"); + registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); + registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); // OpenAL // For OSX: Need to add lib prefix when extracting registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll"); registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll"); - registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so"); - registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so"); - registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); - registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); + registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so"); + registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so"); + registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); + registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); // LWJGL 3.x registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/lwjgl32.dll"); @@ -173,39 +177,39 @@ public final class NativeLibraryLoader { // BulletJme registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll"); registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll"); - registerNativeLibrary("bulletjme", Platform.Linux32, "native/linux/x86/libbulletjme.so"); - registerNativeLibrary("bulletjme", Platform.Linux64, "native/linux/x86_64/libbulletjme.so"); - registerNativeLibrary("bulletjme", Platform.MacOSX32, "native/osx/x86/libbulletjme.dylib"); - registerNativeLibrary("bulletjme", Platform.MacOSX64, "native/osx/x86_64/libbulletjme.dylib"); - + registerNativeLibrary("bulletjme", Platform.Linux32, "native/linux/x86/libbulletjme.so"); + registerNativeLibrary("bulletjme", Platform.Linux64, "native/linux/x86_64/libbulletjme.so"); + registerNativeLibrary("bulletjme", Platform.MacOSX32, "native/osx/x86/libbulletjme.dylib"); + registerNativeLibrary("bulletjme", Platform.MacOSX64, "native/osx/x86_64/libbulletjme.dylib"); + // JInput // For OSX: Need to rename extension jnilib -> dylib when extracting registerNativeLibrary("jinput", Platform.Windows32, "native/windows/jinput-raw.dll"); registerNativeLibrary("jinput", Platform.Windows64, "native/windows/jinput-raw_64.dll"); - registerNativeLibrary("jinput", Platform.Linux32, "native/windows/libjinput-linux.so"); - registerNativeLibrary("jinput", Platform.Linux64, "native/windows/libjinput-linux64.so"); - registerNativeLibrary("jinput", Platform.MacOSX32, "native/macosx/libjinput-osx.jnilib", "libjinput-osx.dylib"); - registerNativeLibrary("jinput", Platform.MacOSX64, "native/macosx/libjinput-osx.jnilib", "libjinput-osx.dylib"); - + registerNativeLibrary("jinput", Platform.Linux32, "native/windows/libjinput-linux.so"); + registerNativeLibrary("jinput", Platform.Linux64, "native/windows/libjinput-linux64.so"); + registerNativeLibrary("jinput", Platform.MacOSX32, "native/macosx/libjinput-osx.jnilib", "libjinput-osx.dylib"); + registerNativeLibrary("jinput", Platform.MacOSX64, "native/macosx/libjinput-osx.jnilib", "libjinput-osx.dylib"); + // JInput Auxiliary (only required on Windows) registerNativeLibrary("jinput-dx8", Platform.Windows32, "native/windows/jinput-dx8.dll"); registerNativeLibrary("jinput-dx8", Platform.Windows64, "native/windows/jinput-dx8_64.dll"); - registerNativeLibrary("jinput-dx8", Platform.Linux32, null); - registerNativeLibrary("jinput-dx8", Platform.Linux64, null); - registerNativeLibrary("jinput-dx8", Platform.MacOSX32, null); - registerNativeLibrary("jinput-dx8", Platform.MacOSX64, null); + registerNativeLibrary("jinput-dx8", Platform.Linux32, null); + registerNativeLibrary("jinput-dx8", Platform.Linux64, null); + registerNativeLibrary("jinput-dx8", Platform.MacOSX32, null); + registerNativeLibrary("jinput-dx8", Platform.MacOSX64, null); } - + private NativeLibraryLoader() { } - + /** * Determine if native bullet is on the classpath. - * - * Currently the context extracts the native bullet libraries, so - * this method is needed to determine if it is needed. - * Ideally, native bullet should be responsible for its own natives. - * + * + * Currently the context extracts the native bullet libraries, so this + * method is needed to determine if it is needed. Ideally, native bullet + * should be responsible for its own natives. + * * @return True native bullet is on the classpath, false otherwise. */ public static boolean isUsingNativeBullet() { @@ -216,35 +220,37 @@ public final class NativeLibraryLoader { return false; } } - + /** - * Specify a custom location where native libraries should - * be extracted to. Ensure this is a unique path not used - * by other applications to extract their libraries. - * Set to null to restore default + * Specify a custom location where native libraries should be extracted to. + * Ensure this is a unique path not used by other applications to extract + * their libraries. Set to null to restore default * functionality. - * + * * @param path Path where to extract native libraries. */ public static void setCustomExtractionFolder(String path) { - extractionFolderOverride = new File(path).getAbsoluteFile(); + if (path != null) { + extractionFolderOverride = new File(path).getAbsoluteFile(); + } else { + extractionFolderOverride = null; + } } /** - * Returns the folder where native libraries will be extracted. - * This is automatically determined at run-time based on the - * following criteria:
+ * Returns the folder where native libraries will be extracted. This is + * automatically determined at run-time based on the following criteria:
*