diff --git a/app/test/processing/app/AbstractGUITest.java b/app/test/processing/app/AbstractGUITest.java index d1db60d98aa..37f0ebefe58 100644 --- a/app/test/processing/app/AbstractGUITest.java +++ b/app/test/processing/app/AbstractGUITest.java @@ -41,30 +41,26 @@ import javax.swing.*; import java.util.Random; -public abstract class AbstractGUITest { +public abstract class AbstractGUITest extends AbstractWithPreferencesTest { protected ArduinoFrameFixture window; @Before public void startUpTheIDE() throws Exception { + // This relies on AbstractWithPreferencesTest to set up the + // non-gui-specific stuff. + System.setProperty("mrj.version", "whynot"); //makes sense only on osx. See https://github.com/alexruiz/fest-swing-1.x/issues/2#issuecomment-86532042 - Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE)); FailOnThreadViolationRepaintManager.install(); - BaseNoGui.initPlatform(); - BaseNoGui.getPlatform().init(); - PreferencesData.init(null); JPopupMenu.setDefaultLightWeightPopupEnabled(false); - Theme.init(); BaseNoGui.getPlatform().setLookAndFeel(); - Base.untitledFolder = FileUtils.createTempFolder("untitled" + new Random().nextInt(Integer.MAX_VALUE), ".tmp"); - DeleteFilesOnShutdown.add(Base.untitledFolder); window = GuiActionRunner.execute(new GuiQuery() { @Override protected ArduinoFrameFixture executeInEDT() throws Throwable { - return new ArduinoFrameFixture(new Base(new String[0]).editors.get(0)); + return new ArduinoFrameFixture(createBase().editors.get(0)); } }); } diff --git a/app/test/processing/app/AbstractWithPreferencesTest.java b/app/test/processing/app/AbstractWithPreferencesTest.java index f0d2f3a2b07..1075aebda4f 100644 --- a/app/test/processing/app/AbstractWithPreferencesTest.java +++ b/app/test/processing/app/AbstractWithPreferencesTest.java @@ -29,26 +29,88 @@ package processing.app; -import cc.arduino.files.DeleteFilesOnShutdown; +import static org.junit.Assert.assertEquals; import org.junit.Before; +import org.junit.After; + import processing.app.helpers.FileUtils; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.util.Random; +import java.util.List; +import java.util.LinkedList; public abstract class AbstractWithPreferencesTest { + /** + * Files or directories that will be deleted after each test. + * Subclasses can add files here in @Test or @Before functions. + */ + protected List deleteAfter = new LinkedList(); + protected File preferencesFile; @Before public void init() throws Exception { - Runtime.getRuntime().addShutdownHook(new Thread(DeleteFilesOnShutdown.INSTANCE)); + File settingsDir = Files.createTempDirectory("arduino_test_settings").toFile(); + deleteAfter.add(settingsDir); + + preferencesFile = new File(settingsDir, "preferences.txt"); + File sketchbookDir = new File(settingsDir, "sketchbook"); + sketchbookDir.mkdir(); + BaseNoGui.initPlatform(); BaseNoGui.getPlatform().init(); - PreferencesData.init(null); + + PreferencesData.init(preferencesFile); + // Do not read anything from e.g. ~/.arduino15 + PreferencesData.set("settings.path", settingsDir.toString()); + // Do not read or write the default ~/Arduino sketchbook + PreferencesData.set("sketchbook.path", sketchbookDir.toString()); + // Do not perform any update checks + PreferencesData.set("update.check", sketchbookDir.toString()); + // Write the defaults, with these changes to file. This allows them + // to be reloaded when creating a Base instance (see getBaseArgs() + // below). + PreferencesData.save(); + Theme.init(); BaseNoGui.initPackages(); Base.untitledFolder = FileUtils.createTempFolder("untitled" + new Random().nextInt(Integer.MAX_VALUE), ".tmp"); - DeleteFilesOnShutdown.add(Base.untitledFolder); + deleteAfter.add(Base.untitledFolder); } + /** + * Returns arguments to be passed to the Base constructor or on the + * commandline to set up the created dummy environment. + */ + protected String[] getBaseArgs() { + return new String[] { + // Preferences are loaded (using --preferences-file) before + // processing any other commandline options (e.g. --pref), so only + // use --preferences-file here. Also, this does not affect the + // "action" mode, for tests that require the GUI to be loaded. + "--preferences-file", preferencesFile.toString(), + }; + } + + /** + * Creates a new instance of Base. Always use this rather than calling + * it directly, to ensure the right settings are used. + */ + protected Base createBase() throws Exception { + Base base = new Base(getBaseArgs()); + // Doublecheck that the right preferencesFile was loaded + assertEquals(preferencesFile, PreferencesData.preferencesFile); + return base; + } + + @After + public void cleanup() throws IOException { + for (File f : deleteAfter) + FileUtils.recursiveDelete(f); + deleteAfter = new LinkedList(); + } } diff --git a/app/test/processing/app/CommandLineTest.java b/app/test/processing/app/CommandLineTest.java index 9ac760b1fbb..1db6afe12f1 100644 --- a/app/test/processing/app/CommandLineTest.java +++ b/app/test/processing/app/CommandLineTest.java @@ -32,22 +32,32 @@ import static org.junit.Assert.*; import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; import org.apache.commons.compress.utils.IOUtils; import org.fest.assertions.Assertions; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import processing.app.helpers.OSUtils; import processing.app.helpers.PreferencesMap; -public class CommandLineTest { +/** + * This extends AbstractWithPreferencesTest which initializes part of + * the internal Arduino structures. Most of that is not required, but it + * also conveniently sets up a settings directory and preferences file, + * which we can use here (through getBaseArgs()). + */ +public class CommandLineTest extends AbstractWithPreferencesTest { - File buildPath; - File arduinoPath; + private static File buildPath; + private static File arduinoPath; - @Before - public void findBuildPaths() throws Exception { + @BeforeClass + public static void findBuildPaths() throws Exception { buildPath = new File(System.getProperty("user.dir")); while (!new File(buildPath, "build").isDirectory()) { buildPath = buildPath.getParentFile(); @@ -72,58 +82,60 @@ public void findBuildPaths() throws Exception { System.out.println("found arduino: " + arduinoPath); } + public Process runArduino(boolean output, boolean success, File wd, String[] extraArgs) throws IOException, InterruptedException { + Runtime rt = Runtime.getRuntime(); + + List args = new ArrayList(); + args.add(arduinoPath.getAbsolutePath()); + args.addAll(Arrays.asList(getBaseArgs())); + args.addAll(Arrays.asList(extraArgs)); + + System.out.println("Running: " + String.join(" ", args)); + + Process pr = rt.exec(args.toArray(new String[0]), null, wd); + if (output) { + IOUtils.copy(pr.getInputStream(), System.out); + IOUtils.copy(pr.getErrorStream(), System.out); + } + pr.waitFor(); + if (success) + assertEquals(0, pr.exitValue()); + return pr; + } + @Test public void testCommandLineBuildWithRelativePath() throws Exception { - Runtime rt = Runtime.getRuntime(); File wd = new File(buildPath, "build/shared/examples/01.Basics/Blink/"); - Process pr = rt - .exec(arduinoPath + " --board arduino:avr:uno --verify Blink.ino", null, - wd); - IOUtils.copy(pr.getInputStream(), System.out); - pr.waitFor(); - assertEquals(0, pr.exitValue()); + runArduino(true, true, wd, new String[] { + "--board", "arduino:avr:uno", + "--verify", "Blink.ino", + }); } @Test public void testCommandLinePreferencesSave() throws Exception { - Runtime rt = Runtime.getRuntime(); File prefFile = File.createTempFile("test_pref", ".txt"); prefFile.deleteOnExit(); - Process pr = rt.exec(new String[] { - arduinoPath.getAbsolutePath(), + runArduino(true, true, null, new String[] { "--save-prefs", "--preferences-file", prefFile.getAbsolutePath(), - "--get-pref", // avoids starting the GUI + "--version", // avoids starting the GUI }); - IOUtils.copy(pr.getInputStream(), System.out); - IOUtils.copy(pr.getErrorStream(), System.out); - pr.waitFor(); - assertEquals(0, pr.exitValue()); - pr = rt.exec(new String[] { - arduinoPath.getAbsolutePath(), + runArduino(true, true, null, new String[] { "--pref", "test_pref=xxx", "--preferences-file", prefFile.getAbsolutePath(), }); - IOUtils.copy(pr.getInputStream(), System.out); - IOUtils.copy(pr.getErrorStream(), System.out); - pr.waitFor(); - assertEquals(0, pr.exitValue()); PreferencesMap prefs = new PreferencesMap(prefFile); assertNull("preference should not be saved", prefs.get("test_pref")); - pr = rt.exec(new String[] { - arduinoPath.getAbsolutePath(), + runArduino(true, true, null, new String[] { "--pref", "test_pref=xxx", "--preferences-file", prefFile.getAbsolutePath(), "--save-prefs", }); - IOUtils.copy(pr.getInputStream(), System.out); - IOUtils.copy(pr.getErrorStream(), System.out); - pr.waitFor(); - assertEquals(0, pr.exitValue()); prefs = new PreferencesMap(prefFile); assertEquals("preference should be saved", "xxx", prefs.get("test_pref")); @@ -131,29 +143,20 @@ public void testCommandLinePreferencesSave() throws Exception { @Test public void testCommandLineVersion() throws Exception { - Runtime rt = Runtime.getRuntime(); - Process pr = rt.exec(new String[]{ - arduinoPath.getAbsolutePath(), + Process pr = runArduino(false, true, null, new String[] { "--version", }); - pr.waitFor(); - Assertions.assertThat(pr.exitValue()) - .as("Process will finish with exit code 0 in --version") - .isEqualTo(0); Assertions.assertThat(new String(IOUtils.toByteArray(pr.getInputStream()))) .matches("Arduino: \\d+\\.\\d+\\.\\d+.*\r?\n"); } @Test public void testCommandLineMultipleAction() throws Exception { - Runtime rt = Runtime.getRuntime(); - Process pr = rt.exec(new String[]{ - arduinoPath.getAbsolutePath(), + Process pr = runArduino(true, false, null, new String[] { "--version", "--verify", }); - pr.waitFor(); Assertions.assertThat(pr.exitValue()) .as("Multiple Action will be rejected") diff --git a/app/test/processing/app/DefaultTargetTest.java b/app/test/processing/app/DefaultTargetTest.java index 37819c84cff..24767bee30d 100644 --- a/app/test/processing/app/DefaultTargetTest.java +++ b/app/test/processing/app/DefaultTargetTest.java @@ -57,7 +57,7 @@ public void testDefaultTarget() throws Exception { PreferencesData.set("board", "unreal_board"); // should not raise an exception - new Base(new String[0]); + createBase(); // skip test if no target platforms are available Assume.assumeNotNull(BaseNoGui.getTargetPlatform()); diff --git a/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java b/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java index 83897b1963c..59dff4c3595 100644 --- a/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java +++ b/app/test/processing/app/HittingEscapeOnCloseConfirmationDialogTest.java @@ -30,6 +30,7 @@ package processing.app; import org.fest.swing.core.KeyPressInfo; +import org.fest.swing.core.matcher.DialogMatcher; import org.fest.swing.finder.WindowFinder; import org.fest.swing.fixture.DialogFixture; import org.junit.Test; @@ -39,6 +40,7 @@ import java.awt.event.KeyEvent; import static org.junit.Assert.assertEquals; +import static processing.app.I18n.tr; public class HittingEscapeOnCloseConfirmationDialogTest extends AbstractGUITest { @@ -49,7 +51,8 @@ public void shouldJustCloseTheDialog() throws Exception { window.close(); - DialogFixture dialog = WindowFinder.findDialog(JDialog.class).using(window.robot); + DialogMatcher matcher = DialogMatcher.withTitle(tr("Close")).andShowing(); + DialogFixture dialog = WindowFinder.findDialog(matcher).using(window.robot); dialog.pressAndReleaseKey(KeyPressInfo.keyCode(KeyEvent.VK_ESCAPE)); EditorConsole console = (EditorConsole) window.scrollPane("console").component(); diff --git a/arduino-core/src/processing/app/PreferencesData.java b/arduino-core/src/processing/app/PreferencesData.java index 01f4568ad5b..11a250d689c 100644 --- a/arduino-core/src/processing/app/PreferencesData.java +++ b/arduino-core/src/processing/app/PreferencesData.java @@ -50,6 +50,9 @@ static public void init(File file) throws Exception { //ignore } + // Start with a clean slate + prefs = new PreferencesMap(); + // start by loading the defaults, in case something // important was deleted from the user prefs try {