Improved Test experience by a lot; added first tests for Am2904, Am2910
[Mograsim.git] / net.mograsim.logic.model.am2900 / test / net / mograsim / logic / model / am2900 / TestEnvironmentHelper.java
diff --git a/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestEnvironmentHelper.java b/net.mograsim.logic.model.am2900/test/net/mograsim/logic/model/am2900/TestEnvironmentHelper.java
deleted file mode 100644 (file)
index 9ac4030..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-package net.mograsim.logic.model.am2900;
-
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Objects;
-import java.util.Queue;
-import java.util.Set;
-import java.util.TreeSet;
-
-import net.mograsim.logic.core.components.BitDisplay;
-import net.mograsim.logic.core.components.ManualSwitch;
-import net.mograsim.logic.core.timeline.Timeline;
-import net.mograsim.logic.model.am2900.TestableCircuit.Result;
-import net.mograsim.logic.model.model.ViewModel;
-import net.mograsim.logic.model.model.ViewModelModifiable;
-import net.mograsim.logic.model.model.components.GUIComponent;
-import net.mograsim.logic.model.model.components.atomic.GUIBitDisplay;
-import net.mograsim.logic.model.model.components.atomic.GUIManualSwitch;
-import net.mograsim.logic.model.model.components.submodels.SubmodelComponent;
-import net.mograsim.logic.model.model.wires.GUIWire;
-import net.mograsim.logic.model.model.wires.Pin;
-import net.mograsim.logic.model.modeladapter.LogicModelParameters;
-import net.mograsim.logic.model.modeladapter.ViewLogicModelAdapter;
-import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
-import net.mograsim.logic.model.util.ModellingTool;
-
-public class TestEnvironmentHelper
-{
-       private final TestableCircuit testEnvInstance;
-       private final Class<?> testEnvClass;
-       private final String modelId;
-       private Field componentField;
-       private Field timelineField;
-
-       private GUIComponent component;
-       private Timeline timeline;
-       private ViewModelModifiable viewModel;
-       private ModellingTool modellingTool;
-       private HashMap<String, GUIManualSwitch> idSwitchMap = new HashMap<>();
-       private HashMap<String, GUIBitDisplay> idDisplayMap = new HashMap<>();
-
-       private DebugState debug = DebugState.NO_DEBUG;
-       private Set<String> wireDebugChangeSet;
-       private boolean debugWires = false;
-       public int debugEventThreshold = 10_000;
-       public int debugEventCount = 500;
-       private int eventCounter;
-
-       public TestEnvironmentHelper(TestableCircuit testEnv, String modelId)
-       {
-               this.testEnvInstance = testEnv;
-               this.modelId = modelId;
-               this.testEnvClass = testEnvInstance.getClass();
-               for (Field f : testEnvClass.getDeclaredFields())
-               {
-                       if (GUIComponent.class.isAssignableFrom(f.getType()))
-                       {
-                               componentField = f;
-                               componentField.setAccessible(true);
-                       } else if (Timeline.class.isAssignableFrom(f.getType()))
-                       {
-                               timelineField = f;
-                               timelineField.setAccessible(true);
-                       }
-               }
-               if (componentField == null || timelineField == null)
-                       throw new IllegalStateException("No component or timeline field found!");
-       }
-
-       public void setup(DebugState debug)
-       {
-               this.debug = debug;
-               // Create view model
-               viewModel = new ViewModelModifiable();
-               modellingTool = ModellingTool.createFor(viewModel);
-               component = IndirectGUIComponentCreator.createComponent(viewModel, modelId);
-               setField(componentField, component);
-
-               component.getPins().values().forEach(this::extendModelPin);
-
-               // Create logic model
-               LogicModelParameters params = new LogicModelParameters();
-               params.gateProcessTime = 50;
-               params.wireTravelTime = 10;
-               timeline = ViewLogicModelAdapter.convert(viewModel, params);
-               setField(timelineField, timeline);
-
-               // Bind switches/displays to this test class
-               component.getPins().values().forEach(this::bindModelPin);
-
-               if (debug == DebugState.DEBUG_AT_PERFORMANCE_COST)
-               {
-                       setupDebugging();
-               }
-               timeline.addEventAddedListener(te -> eventCounter++);
-       }
-
-       private void extendModelPin(Pin p)
-       {
-               String javaIdentId = idToJavaIdentifier(p.name);
-               try
-               {
-                       Field f = testEnvClass.getDeclaredField(javaIdentId);
-                       Class<?> type = f.getType();
-                       if (ManualSwitch.class.isAssignableFrom(type))
-                       {
-                               GUIManualSwitch gms = new GUIManualSwitch(viewModel, p.logicWidth);
-                               modellingTool.connect(p, gms.getOutputPin());
-                               idSwitchMap.put(p.name, gms);
-                       } else if (BitDisplay.class.isAssignableFrom(type))
-                       {
-                               GUIBitDisplay gbd = new GUIBitDisplay(viewModel, p.logicWidth);
-                               modellingTool.connect(p, gbd.getInputPin());
-                               idDisplayMap.put(p.name, gbd);
-                       } else if (SwitchWithDisplay.class.isAssignableFrom(type))
-                       {
-                               SwitchWithDisplay swd = new SwitchWithDisplay(viewModel, p);
-                               setField(f, swd);
-                       } else
-                       {
-                               fail("unkown field type " + type);
-                       }
-               }
-               catch (NoSuchFieldException | SecurityException e)
-               {
-                       fail(e);
-               }
-       }
-
-       private void bindModelPin(Pin p)
-       {
-               String javaIdentId = idToJavaIdentifier(p.name);
-               if (idDisplayMap.containsKey(p.name))
-                       setField(javaIdentId, idDisplayMap.get(p.name).getBitDisplay());
-               if (idSwitchMap.containsKey(p.name))
-                       setField(javaIdentId, idSwitchMap.get(p.name).getManualSwitch());
-       }
-
-       private void setupDebugging()
-       {
-               // Debug code
-               HashSet<GUIWire> wiresIncludingSubmodels = new HashSet<>();
-               Queue<ViewModel> modelsToIterate = new LinkedList<>();
-               modelsToIterate.add(viewModel);
-               while (modelsToIterate.size() > 0)
-               {
-                       ViewModel model = modelsToIterate.poll();
-                       wiresIncludingSubmodels.addAll(model.getWiresByName().values());
-                       for (GUIComponent comp : model.getComponentsByName().values())
-                               if (comp instanceof SubmodelComponent)
-                                       modelsToIterate.offer(((SubmodelComponent) comp).submodel);
-               }
-               System.out.println(wiresIncludingSubmodels.size());
-               viewModel.setRedrawHandler(() -> wiresIncludingSubmodels.forEach(w ->
-               {
-                       if (debugWires)
-                       {
-                               wireDebugChangeSet.add(w.toString());
-                       }
-               }));
-       }
-
-       public Result run()
-       {
-               // Normal execution until completion or eventLimit
-               int eventLimit = debugEventThreshold;
-               eventCounter = 0;
-               debugWires = false;
-               while (eventCounter < eventLimit)
-               {
-                       timeline.executeNext();
-                       if (!timeline.hasNext())
-                               return Result.SUCCESS;
-               }
-
-               // Start debugging if event limit is reached (if debug is active)
-               if (debug == DebugState.DEBUG_AT_PERFORMANCE_COST)
-                       return debugThisRun();
-
-               return Result.OUT_OF_TIME;
-       }
-
-       private Result debugThisRun()
-       {
-               int eventLimit = debugEventThreshold;
-               debugWires = true;
-               wireDebugChangeSet = new TreeSet<>();
-               Set<String> oldChangeSet;
-               // observe wire changes to detect, if we are really stuck in an endless loop
-               do
-               {
-                       eventLimit += debugEventCount;
-                       oldChangeSet = wireDebugChangeSet;
-                       wireDebugChangeSet = new TreeSet<>();
-                       while (eventCounter < eventLimit)
-                       {
-                               timeline.executeNext();
-                               if (!timeline.hasNext())
-                               {
-                                       // no endless loop, but more events needed than expected
-                                       System.out.println("run() took longer than expected: " + eventCounter);
-                                       return Result.SUCCESS;
-                               }
-                       }
-               } while (!oldChangeSet.equals(wireDebugChangeSet));
-               // if stuck, abort execution and print wires
-               System.err.print("Problematic Wire updates:");
-               wireDebugChangeSet.forEach(System.out::println);
-               System.err.println("run() failed: " + eventCounter);
-               return Result.OUT_OF_TIME;
-       }
-
-       private static String idToJavaIdentifier(String s)
-       {
-               StringBuilder sb = new StringBuilder(s.length());
-               char c = s.charAt(0);
-               sb.append(Character.isJavaIdentifierStart(c) ? c : '_');
-               for (int i = 1; i < s.length(); i++)
-                       sb.append(Character.isJavaIdentifierPart(c = s.charAt(i)) ? c : '_');
-               return sb.toString();
-       }
-
-       private <S> void setField(Field f, S value)
-       {
-               try
-               {
-                       f.set(testEnvInstance, Objects.requireNonNull(value));
-               }
-               catch (Exception e)
-               {
-                       fail(e);
-               }
-       }
-
-       private <S> void setField(String name, S value)
-       {
-               try
-               {
-                       Field f = testEnvClass.getDeclaredField(name);
-                       f.setAccessible(true);
-                       f.set(testEnvInstance, Objects.requireNonNull(value));
-               }
-               catch (Exception e)
-               {
-                       fail(e);
-               }
-       }
-
-       public enum DebugState
-       {
-               NO_DEBUG, DEBUG_AT_PERFORMANCE_COST;
-       }
-}