fix test config

This commit is contained in:
Bane Stojkovic
2026-11-04 10:15:08 +01:00
parent e751c20e93
commit 2ae30b9630
24 changed files with 246 additions and 101 deletions
@@ -0,0 +1,102 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.Map;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
import org.diylc.serialization.ProjectFileManager;
/**
* Gives a test a blank configuration: both the shared {@link ConfigurationManager} and the shared
* {@link InMemoryConfigurationManager} start empty on every call, with no listeners, so nothing a
* previous test or a previous run saved or registered can influence the next one. The
* configuration lives in a temporary directory, never in the user's own {@code ~/diylc}:
* initializing against the real {@code config.xml} copied it to a new
* {@code config.xml.<timestamp>} on every run that could not read it, and left that file exposed
* to whatever a test might write.
*
* @author Branislav Stojkovic
*/
public final class TestConfiguration {
private static final String APP_NAME = "diylc";
private static File directory;
private TestConfiguration() {}
public static synchronized void initialize() {
ConfigurationManager configurationManager = ConfigurationManager.getInstance();
if (directory == null) {
ProjectFileManager.configure(configurationManager.getSerializer());
try {
directory = Files.createTempDirectory("diylc-test").toFile();
} catch (IOException e) {
throw new IllegalStateException("Could not create a temporary configuration directory", e);
}
}
// initialize() reads back whatever an earlier test saved, and starts empty only without a file
new File(directory, APP_NAME + File.separator + "config.xml").delete();
// the configuration directory is resolved from user.home once, inside initialize()
String userHome = System.getProperty("user.home");
try {
System.setProperty("user.home", directory.getAbsolutePath());
configurationManager.initialize(APP_NAME);
} finally {
System.setProperty("user.home", userHome);
}
clearListeners(configurationManager);
resetInMemoryConfiguration();
}
// initialize() replaces the values but keeps the listeners, so objects from earlier tests, such
// as a CustomTreeModel nothing displays any more, would still react to this test's writes
private static void clearListeners(ConfigurationManager configurationManager) {
try {
Field listeners = ConfigurationManager.class.getDeclaredField("listeners");
listeners.setAccessible(true);
((Map<?, ?>) listeners.get(configurationManager)).clear();
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Could not clear configuration listeners", e);
}
}
// InMemoryConfigurationManager offers no way to clear its singleton, which every presenter that
// tests create shares, including the one inside CloudSyncJob; getInstance() makes a new, empty
// one once the field is cleared
private static void resetInMemoryConfiguration() {
try {
Field instance = InMemoryConfigurationManager.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, null);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Could not reset the in-memory configuration", e);
}
}
}
@@ -29,9 +29,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.IConfigListener;
import org.diylc.appframework.miscutils.IConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.IPlugInPort;
import org.diylc.core.Template;
import org.diylc.presenter.VariantManager;
@@ -51,10 +51,7 @@ public class DeletedVariantsTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
@SuppressWarnings("unchecked")
@@ -27,7 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.PropertyWrapper;
import org.diylc.core.IDIYComponent;
import org.diylc.core.Template;
@@ -54,10 +54,7 @@ public class FactoryVariantsTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
@SuppressWarnings("unchecked")
@@ -23,7 +23,7 @@ package org.diylc.components.displays;
import java.awt.Color;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.Display;
import org.diylc.components.displays.CharacterLCD.LCDInterface;
import org.diylc.components.displays.CharacterLCD.LCDSize;
@@ -40,10 +40,7 @@ public class CharacterLCDTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static CharacterLCD of(LCDSize lcdSize, LCDInterface lcdInterface) {
@@ -24,7 +24,7 @@ package org.diylc.components.displays;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.IComponentTransformer;
import org.diylc.common.Orientation;
import org.diylc.components.displays.LEDBarGraph.BarColor;
@@ -43,10 +43,7 @@ public class LEDBarGraphTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
/** Each segment has its own anode and cathode, so the package grows with the count. */
@@ -25,7 +25,7 @@ import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.displays.LEDMatrix.Modules;
import org.diylc.components.maker.MakerBoardTestSupport;
import org.junit.Assert;
@@ -42,10 +42,7 @@ public class LEDMatrixTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -25,7 +25,7 @@ import java.awt.Color;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.Display;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.maker.MakerBoardTestSupport;
@@ -44,10 +44,7 @@ public class Nokia5110LCDTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -28,7 +28,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.Display;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.displays.OLEDDisplay.Layout;
@@ -50,10 +50,7 @@ public class OLEDDisplayTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -25,7 +25,7 @@ import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.displays.SevenSegmentDisplay.Common;
import org.diylc.components.displays.SevenSegmentDisplay.DisplayType;
import org.diylc.components.displays.SevenSegmentDisplay.Punctuation;
@@ -44,10 +44,7 @@ public class SevenSegmentDisplayTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -29,7 +29,7 @@ import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.Display;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.displays.TFTDisplay.Controller;
@@ -51,10 +51,7 @@ public class TFTDisplayTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -26,7 +26,7 @@ import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.maker.MakerBoardTestSupport;
import org.junit.Assert;
@@ -45,10 +45,7 @@ public class WS2812BBreakoutTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -25,7 +25,7 @@ import java.awt.Shape;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.maker.MakerBoardTestSupport;
import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit;
@@ -44,10 +44,7 @@ public class WS2812BJewelTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -29,7 +29,7 @@ import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.displays.WS2812BPanel.Silk;
import org.diylc.components.maker.MakerBoardTestSupport;
@@ -49,10 +49,7 @@ public class WS2812BPanelTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double px(double millimetres) {
@@ -27,7 +27,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.AbstractMakerBoard.LedType;
import org.diylc.components.displays.WS2812BRing.RingSize;
import org.diylc.components.maker.MakerBoardTestSupport;
@@ -46,10 +46,7 @@ public class WS2812BRingTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -26,7 +26,7 @@ import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.maker.MakerBoardTestSupport;
import org.junit.Assert;
@@ -42,10 +42,7 @@ public class WS2812BStickTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static Rectangle2D ledPackage(WS2812BStick stick, int index) {
@@ -26,7 +26,7 @@ import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Set;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.components.AbstractMakerBoard;
import org.diylc.components.displays.WS2812BStrip.Density;
import org.diylc.components.maker.MakerBoardTestSupport;
@@ -46,10 +46,7 @@ public class WS2812BStripTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private static double mm(double px) {
@@ -25,7 +25,7 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.core.IDIYComponent;
import org.diylc.netlist.Node;
import org.diylc.components.displays.WS2812BStrip;
@@ -51,10 +51,7 @@ public class BoardRailTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
@Test
@@ -31,6 +31,7 @@ import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.diylc.TestConfiguration;
import org.diylc.common.ComponentType;
import org.diylc.common.DefaultComponentTransformer;
import org.diylc.common.Orientation;
@@ -48,16 +49,12 @@ import org.diylc.presenter.ComponentProcessor;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.diylc.appframework.miscutils.ConfigurationManager;
public class MakerComponentsTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
private final List<Class<? extends IDIYComponent<?>>> releasedMakerComponentClasses = Arrays.<Class<? extends IDIYComponent<?>>>asList(
@@ -35,7 +35,7 @@ import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.ComponentType;
import org.diylc.common.PropertyWrapper;
import org.diylc.core.ComponentState;
@@ -92,10 +92,7 @@ public class MakerVariantSweepTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
/** Problems are collected so that a run reports every bad variant rather than just the first. */
@@ -41,7 +41,7 @@ import java.util.Set;
import org.junit.BeforeClass;
import org.junit.Test;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.Orientation;
import org.diylc.components.connectivity.HookupWire;
import org.diylc.components.electromechanical.ClosedJack1_4;
@@ -81,10 +81,7 @@ public class AiEditScriptEditorTest {
@BeforeClass
public static void setUp() {
try {
ConfigurationManager.getInstance().initialize("diylc");
} catch (Exception ignored) {
}
TestConfiguration.initialize();
}
@Test
@@ -19,7 +19,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
import org.diylc.appframework.update.VersionNumber;
import org.diylc.swingframework.export.DrawingExporter;
@@ -52,7 +51,7 @@ public class RegressionTestRunner {
// System.err.println("Could not initialize log4j configuration: " + e.getMessage());
// }
ConfigurationManager.getInstance().initialize("diylc-test");
TestConfiguration.initialize();
String basePath = args[0];
String command = args[1];
@@ -8,7 +8,6 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.PropertyConfigurator;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
import org.diylc.common.ComponentType;
@@ -30,7 +29,7 @@ public class TestBase {
System.err.println("Could not initialize log4j configuration: " + e.getMessage());
}
ConfigurationManager.getInstance().initialize("diylc-test");
TestConfiguration.initialize();
view = new MockView();
presenter = new Presenter(view, InMemoryConfigurationManager.getInstance());
}
@@ -0,0 +1,102 @@
/*
DIY Layout Creator (DIYLC).
Copyright (c) 2009-2025 held jointly by the individual authors.
This file is part of DIYLC.
DIYLC is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DIYLC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diylc;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.util.Map;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
import org.diylc.serialization.ProjectFileManager;
/**
* Gives a test a blank configuration: both the shared {@link ConfigurationManager} and the shared
* {@link InMemoryConfigurationManager} start empty on every call, with no listeners, so nothing a
* previous test or a previous run saved or registered can influence the next one. The
* configuration lives in a temporary directory, never in the user's own {@code ~/diylc}:
* initializing against the real {@code config.xml} copied it to a new
* {@code config.xml.<timestamp>} on every run that could not read it, and left that file exposed
* to whatever a test might write.
*
* @author Branislav Stojkovic
*/
public final class TestConfiguration {
private static final String APP_NAME = "diylc";
private static File directory;
private TestConfiguration() {}
public static synchronized void initialize() {
ConfigurationManager configurationManager = ConfigurationManager.getInstance();
if (directory == null) {
ProjectFileManager.configure(configurationManager.getSerializer());
try {
directory = Files.createTempDirectory("diylc-test").toFile();
} catch (IOException e) {
throw new IllegalStateException("Could not create a temporary configuration directory", e);
}
}
// initialize() reads back whatever an earlier test saved, and starts empty only without a file
new File(directory, APP_NAME + File.separator + "config.xml").delete();
// the configuration directory is resolved from user.home once, inside initialize()
String userHome = System.getProperty("user.home");
try {
System.setProperty("user.home", directory.getAbsolutePath());
configurationManager.initialize(APP_NAME);
} finally {
System.setProperty("user.home", userHome);
}
clearListeners(configurationManager);
resetInMemoryConfiguration();
}
// initialize() replaces the values but keeps the listeners, so objects from earlier tests, such
// as a CustomTreeModel nothing displays any more, would still react to this test's writes
private static void clearListeners(ConfigurationManager configurationManager) {
try {
Field listeners = ConfigurationManager.class.getDeclaredField("listeners");
listeners.setAccessible(true);
((Map<?, ?>) listeners.get(configurationManager)).clear();
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Could not clear configuration listeners", e);
}
}
// InMemoryConfigurationManager offers no way to clear its singleton, which every presenter that
// tests create shares, including the one inside CloudSyncJob; getInstance() makes a new, empty
// one once the field is cleared
private static void resetInMemoryConfiguration() {
try {
Field instance = InMemoryConfigurationManager.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, null);
} catch (ReflectiveOperationException e) {
throw new IllegalStateException("Could not reset the in-memory configuration", e);
}
}
}
@@ -39,8 +39,8 @@ import org.junit.rules.TemporaryFolder;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.appframework.miscutils.InMemoryConfigurationManager;
import org.diylc.TestConfiguration;
import org.diylc.common.DummyView;
import org.diylc.plugins.cloud.model.IServiceAPI;
import org.diylc.plugins.cloud.model.ProjectEntity;
@@ -196,7 +196,7 @@ public class CloudSyncJobTests {
}
private byte[] emptyProject() throws IOException {
ConfigurationManager.getInstance().initialize("diylc-test");
TestConfiguration.initialize();
File file = folder.newFile("empty.diy");
new Presenter(new DummyView(), InMemoryConfigurationManager.getInstance())
.saveProjectToFile(file.getAbsolutePath(), false);