diff --git a/src/main/dig/generic/barrelShifter/barrelShifter.dig b/src/main/dig/generic/barrelShifter/barrelShifter.dig index 351b7c010..3ee714b68 100644 --- a/src/main/dig/generic/barrelShifter/barrelShifter.dig +++ b/src/main/dig/generic/barrelShifter/barrelShifter.dig @@ -108,7 +108,111 @@ shiftBits:=bitsNeededFor(args.dataBits-1); direction := "left"; - + + + + Testcase + + + Label + 4 bits, left + + + Testdata + + D_in sh D + + 1 0 1 + 1 1 2 + 1 2 4 + 1 3 8 + 1 4 1 + + 2 0 2 + 2 1 4 + 2 2 8 + 2 3 0 + 2 4 2 + + + + + generic + dataBits := 4; +direction := "left"; + + + + + + Testcase + + + Label + 4 bits, right + + + Testdata + + D_in sh D + + 1 0 1 + 2 1 1 + 4 2 1 + 8 3 1 + 1 4 1 + + 4 0 4 + 4 1 2 + 4 2 1 + 4 3 0 + 4 4 4 + + 15 1 7 + + + + generic + dataBits := 4; +direction := "right"; + + + + + + Testcase + + + Label + 4 bits, arith + + + Testdata + + D_in sh D + + 1 0 1 + 2 1 1 + 4 2 1 + 8 3 15 + 1 4 1 + + 4 0 4 + 4 1 2 + 4 2 1 + 4 3 0 + 4 4 4 + + 15 1 15 + + + + generic + dataBits := 4; +direction := "arith"; + + + diff --git a/src/main/dig/generic/gray/GrayCounter.dig b/src/main/dig/generic/gray/GrayCounter.dig index 7d76ae064..fb8f0fe47 100644 --- a/src/main/dig/generic/gray/GrayCounter.dig +++ b/src/main/dig/generic/gray/GrayCounter.dig @@ -35,6 +35,10 @@ Testcase + + Label + 3 bits + Testdata @@ -47,8 +51,12 @@ C 0 + + generic + bits := 3; + - + Text @@ -129,6 +137,10 @@ ist als drei.}} Bits 3 + + generic + this.Bits=int(args.bits); + @@ -153,7 +165,59 @@ if (args.bits>3) { bits := 3; - + + + + Testcase + + + Label + 4 bits + + + Testdata + + C G +0 0 +loop (n,(1<<4)-1) +C ((n+1) ^ ((n+1)>>1)) +end loop +C 0 + + + + + generic + bits := 4; + + + + + + Testcase + + + Label + 5 bits + + + Testdata + + C G +0 0 +loop (n,(1<<5)-1) +C ((n+1) ^ ((n+1)>>1)) +end loop +C 0 + + + + + generic + bits := 5; + + + diff --git a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java index 7cb49f504..c85667a09 100644 --- a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java +++ b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java @@ -17,6 +17,7 @@ import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.draw.library.LibraryInterface; import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.lang.Lang; +import de.neemann.digital.testing.TestCaseDescription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -206,8 +207,29 @@ public class SubstituteLibrary implements LibraryInterface { Key k = Keys.getKeyByName(key); if (k == null) { throw new HGSEvalException("key " + key + " is invalid"); - } else + } else { + Class expectedClass = k.getDefault().getClass(); + + val = doImplicitTypeCasts(expectedClass, val); + + boolean isAssignable = expectedClass.isAssignableFrom(val.getClass()); + if (!isAssignable) + throw new HGSEvalException("error writing to " + key + ": value of type " + val.getClass().getSimpleName() + " can't be assigned to " + expectedClass.getSimpleName()); attr.set(k, val); + } + } + + private Object doImplicitTypeCasts(Class expectedClass, Object val) { + if (expectedClass == TestCaseDescription.class) + return new TestCaseDescription(val.toString()); + + if (expectedClass == Integer.class && val instanceof Long) { + long l = (Long) val; + if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) + return (int) l; + } + + return val; } @Override diff --git a/src/main/java/de/neemann/digital/cli/CommandLineTester.java b/src/main/java/de/neemann/digital/cli/CommandLineTester.java index 9a718358a..03c8fba42 100644 --- a/src/main/java/de/neemann/digital/cli/CommandLineTester.java +++ b/src/main/java/de/neemann/digital/cli/CommandLineTester.java @@ -9,18 +9,14 @@ import de.neemann.digital.cli.cli.Argument; import de.neemann.digital.cli.cli.BasicCommand; import de.neemann.digital.cli.cli.CLIException; import de.neemann.digital.core.ErrorDetector; -import de.neemann.digital.core.Model; import de.neemann.digital.draw.elements.Circuit; -import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.lang.Lang; -import de.neemann.digital.testing.TestCaseDescription; -import de.neemann.digital.testing.TestCaseElement; import de.neemann.digital.testing.TestExecutor; import java.io.File; import java.io.IOException; import java.io.PrintStream; -import java.util.ArrayList; +import java.util.List; /** * Tester used from the command line @@ -28,7 +24,7 @@ import java.util.ArrayList; public class CommandLineTester { private final CircuitLoader circuitLoader; - private ArrayList testCases; + private List testCases; private int testsPassed; private boolean allowMissingInputs; @@ -51,19 +47,10 @@ public class CommandLineTester { */ public CommandLineTester useTestCasesFrom(File file) throws IOException { Circuit c = Circuit.loadCircuit(file, circuitLoader.getShapeFactory()); - testCases = getTestCasesFrom(c); + testCases = c.getTestCases(); return this; } - private ArrayList getTestCasesFrom(Circuit circuit) { - ArrayList tsl = new ArrayList<>(); - for (VisualElement el : circuit.getTestCases()) - tsl.add(new TestCase( - el.getElementAttributes().get(TestCaseElement.TESTDATA), - el.getElementAttributes().getLabel())); - return tsl; - } - /** * Executes test test * @@ -72,7 +59,7 @@ public class CommandLineTester { */ public int execute(PrintStream out) { if (testCases == null) - testCases = getTestCasesFrom(circuitLoader.getCircuit()); + testCases = circuitLoader.getCircuit().getTestCases(); int errorCount = 0; @@ -80,28 +67,27 @@ public class CommandLineTester { out.println("no test cases given"); errorCount++; } else { - for (TestCase t : testCases) { + for (Circuit.TestCase t : testCases) { String label = t.getLabel(); if (label.isEmpty()) label = "unnamed"; try { - Model model = circuitLoader.createModel(); ErrorDetector errorDetector = new ErrorDetector(); - model.addObserver(errorDetector); - TestExecutor te = new TestExecutor(t.getTestCaseDescription()) + TestExecutor.Result tr = new TestExecutor(t, circuitLoader.getCircuit(), circuitLoader.getLibrary()) .setAllowMissingInputs(allowMissingInputs) - .create(model); + .addObserver(errorDetector) + .execute(); - if (te.allPassed()) { + if (tr.allPassed()) { out.println(label + ": passed"); testsPassed++; } else { String message = label + ": failed"; - if (te.isErrorOccurred()) + if (tr.isErrorOccurred()) message += " due to an error"; else - message += " (" + te.failedPercent() + "%)"; + message += " (" + tr.failedPercent() + "%)"; out.println(message); errorCount++; } @@ -123,24 +109,6 @@ public class CommandLineTester { return testsPassed; } - private static final class TestCase { - private final TestCaseDescription testCaseDescription; - private final String label; - - private TestCase(TestCaseDescription testCaseDescription, String label) { - this.testCaseDescription = testCaseDescription; - this.label = label; - } - - private TestCaseDescription getTestCaseDescription() { - return testCaseDescription; - } - - private String getLabel() { - return label; - } - } - private CommandLineTester setAllowMissingInputs(boolean allowMissingInputs) { this.allowMissingInputs = allowMissingInputs; return this; diff --git a/src/main/java/de/neemann/digital/core/element/Keys.java b/src/main/java/de/neemann/digital/core/element/Keys.java index 869952ce3..9cceabaf3 100644 --- a/src/main/java/de/neemann/digital/core/element/Keys.java +++ b/src/main/java/de/neemann/digital/core/element/Keys.java @@ -20,6 +20,7 @@ import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.model.InverterConfig; import de.neemann.digital.draw.shapes.CustomCircuitShapeType; import de.neemann.digital.draw.shapes.custom.CustomShapeDescription; +import de.neemann.digital.testing.TestCaseDescription; import de.neemann.gui.Screen; import de.neemann.gui.language.Language; @@ -869,4 +870,10 @@ public final class Keys { public static final Key MIRROR = new Key<>("mirror", false).allowGroupEdit().setSecondary(); + /** + * The test data + */ + public static final Key TESTDATA = + new Key<>("Testdata", () -> new TestCaseDescription("")); + } diff --git a/src/main/java/de/neemann/digital/draw/elements/Circuit.java b/src/main/java/de/neemann/digital/draw/elements/Circuit.java index c9c3ef809..49a14e739 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Circuit.java +++ b/src/main/java/de/neemann/digital/draw/elements/Circuit.java @@ -348,8 +348,79 @@ public class Circuit implements Copyable { * * @return the test case elements */ - public List getTestCases() { - return getElements(v -> v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED)); + public List getTestCases() { + ArrayList tc = new ArrayList<>(); + for (VisualElement ve : getElements(v -> v.equalsDescription(TestCaseElement.DESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED))) { + tc.add(new TestCase(ve)); + } + return tc; + } + + /** + * A simple java bean to encapsulate a test case description + */ + public static final class TestCase implements Comparable { + private final String label; + private final TestCaseDescription testCaseDescription; + private final boolean hasGenericCode; + private final VisualElement visualElement; + + private TestCase(VisualElement visualElement) { + this.visualElement = visualElement; + ElementAttributes attr = visualElement.getElementAttributes(); + this.label = attr.getLabel(); + this.testCaseDescription = attr.get(Keys.TESTDATA); + this.hasGenericCode = !attr.get(Keys.GENERIC).isEmpty(); + } + + /** + * @return the label of the test case + */ + public String getLabel() { + return label; + } + + /** + * @return the test case description + */ + public TestCaseDescription getTestCaseDescription() { + return testCaseDescription; + } + + /** + * @return true if the test case has generic code + */ + public boolean hasGenericCode() { + return hasGenericCode; + } + + /** + * @return the visual element which contains the test case + */ + public VisualElement getVisualElement() { + return visualElement; + } + + @Override + public int compareTo(TestCase o) { + return label.compareTo(o.label); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TestCase testCase = (TestCase) o; + + return label.equals(testCase.label); + } + + @Override + public int hashCode() { + return label.hashCode(); + } + } /** diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index e3988b348..067e60ddc 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -219,7 +219,7 @@ public class ElementLibrary implements Iterable .add(FGNFET.DESCRIPTION) .add(TransGate.DESCRIPTION)) .add(new LibraryNode(Lang.get("lib_misc")) - .add(TestCaseElement.TESTCASEDESCRIPTION) + .add(TestCaseElement.DESCRIPTION) .add(GenericInitCode.DESCRIPTION) .add(DummyElement.RECTDESCRIPTION) .add(PowerSupply.DESCRIPTION) diff --git a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java index eb7dbddea..034c1cecc 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java +++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java @@ -158,7 +158,7 @@ public final class ShapeFactory { map.put(DummyElement.TEXTDESCRIPTION.getName(), TextShape::new); map.put(DummyElement.RECTDESCRIPTION.getName(), RectShape::new); - map.put(TestCaseElement.TESTCASEDESCRIPTION.getName(), TestCaseShape::new); + map.put(TestCaseElement.DESCRIPTION.getName(), TestCaseShape::new); map.put(GenericInitCode.DESCRIPTION.getName(), GenericInitCodeShape::new); map.put(AsyncSeq.DESCRIPTION.getName(), AsyncClockShape::new); diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index efc77d073..706f44706 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -54,7 +54,6 @@ import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.verilog2.VerilogGenerator; import de.neemann.digital.hdl.vhdl2.VHDLGenerator; import de.neemann.digital.lang.Lang; -import de.neemann.digital.testing.TestCaseElement; import de.neemann.digital.testing.TestingDataException; import de.neemann.digital.toolchain.Configuration; import de.neemann.digital.undo.ChangedListener; @@ -1128,11 +1127,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS */ public void startTests() { try { - ArrayList tsl = new ArrayList<>(); - for (VisualElement el : circuitComponent.getCircuit().getTestCases()) - tsl.add(new ValueTableDialog.TestSet( - el.getElementAttributes().get(TestCaseElement.TESTDATA), - el.getElementAttributes().getLabel())); + List tsl = circuitComponent.getCircuit().getTestCases(); if (tsl.isEmpty()) throw new TestingDataException(Lang.get("err_noTestData")); diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 8696c704e..61f0d3de3 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -25,6 +25,7 @@ import de.neemann.digital.gui.Main; import de.neemann.digital.gui.Settings; import de.neemann.digital.gui.components.modification.*; import de.neemann.digital.lang.Lang; +import de.neemann.digital.testing.TestCaseElement; import de.neemann.digital.undo.*; import de.neemann.gui.*; @@ -1121,12 +1122,14 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib } } - if (elementType == GenericInitCode.DESCRIPTION) { - if (element.getElementAttributes().get(Keys.GENERIC).isEmpty()) { - try { - element.getElementAttributes().set(Keys.GENERIC, ElementTypeDescriptionCustom.createDeclarationDefault(getCircuit())); - } catch (NodeException ex) { - new ErrorMessage(Lang.get("msg_errParsingGenerics")).addCause(ex).show(CircuitComponent.this); + if (getCircuit().getAttributes().get(Keys.IS_GENERIC)) { + if (elementType == GenericInitCode.DESCRIPTION || elementType == TestCaseElement.DESCRIPTION) { + if (element.getElementAttributes().get(Keys.GENERIC).isEmpty()) { + try { + element.getElementAttributes().set(Keys.GENERIC, ElementTypeDescriptionCustom.createDeclarationDefault(getCircuit())); + } catch (NodeException ex) { + new ErrorMessage(Lang.get("msg_errParsingGenerics")).addCause(ex).show(CircuitComponent.this); + } } } } diff --git a/src/main/java/de/neemann/digital/gui/components/testing/TestCaseDescriptionDialog.java b/src/main/java/de/neemann/digital/gui/components/testing/TestCaseDescriptionDialog.java index d1179438e..70044becb 100644 --- a/src/main/java/de/neemann/digital/gui/components/testing/TestCaseDescriptionDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/testing/TestCaseDescriptionDialog.java @@ -5,6 +5,7 @@ */ package de.neemann.digital.gui.components.testing; +import de.neemann.digital.core.element.Keys; import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.gui.Main; @@ -14,7 +15,6 @@ import de.neemann.digital.gui.components.modification.ModifyAttribute; import de.neemann.digital.gui.components.table.ShowStringDialog; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.TestCaseDescription; -import de.neemann.digital.testing.TestCaseElement; import de.neemann.digital.testing.Transitions; import de.neemann.digital.testing.parser.ParserException; import de.neemann.gui.ErrorMessage; @@ -103,7 +103,7 @@ public class TestCaseDescriptionDialog extends JDialog { data.setDataString(text.getText()); if (parent instanceof Main) { CircuitComponent cc = ((Main) parent).getCircuitComponent(); - element.getElementAttributes().set(TestCaseElement.TESTDATA, data); + element.getElementAttributes().set(Keys.TESTDATA, data); cc.getMain().startTests(); } } catch (ParserException | IOException e1) { @@ -122,7 +122,7 @@ public class TestCaseDescriptionDialog extends JDialog { && !initialDataString.equals(data.getDataString()) && parent instanceof Main) { CircuitComponent cc = ((Main) parent).getCircuitComponent(); - cc.modify(new ModifyAttribute<>(element, TestCaseElement.TESTDATA, new TestCaseDescription(data))); + cc.modify(new ModifyAttribute<>(element, Keys.TESTDATA, new TestCaseDescription(data))); } dispose(); } catch (ParserException | IOException e1) { diff --git a/src/main/java/de/neemann/digital/gui/components/testing/ValueTableDialog.java b/src/main/java/de/neemann/digital/gui/components/testing/ValueTableDialog.java index 1b4b89730..1b13308db 100644 --- a/src/main/java/de/neemann/digital/gui/components/testing/ValueTableDialog.java +++ b/src/main/java/de/neemann/digital/gui/components/testing/ValueTableDialog.java @@ -6,7 +6,6 @@ package de.neemann.digital.gui.components.testing; import de.neemann.digital.core.ErrorDetector; -import de.neemann.digital.core.Model; import de.neemann.digital.core.NodeException; import de.neemann.digital.data.Value; import de.neemann.digital.data.ValueTable; @@ -15,11 +14,9 @@ import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; -import de.neemann.digital.draw.model.ModelCreator; import de.neemann.digital.gui.SaveAsHelper; import de.neemann.digital.gui.components.data.GraphDialog; import de.neemann.digital.lang.Lang; -import de.neemann.digital.testing.TestCaseDescription; import de.neemann.digital.testing.TestExecutor; import de.neemann.digital.testing.TestingDataException; import de.neemann.gui.IconCreator; @@ -121,40 +118,38 @@ public class ValueTableDialog extends JDialog { * @throws PinException PinException * @throws ElementNotFoundException ElementNotFoundException */ - public ValueTableDialog addTestResult(ArrayList tsl, Circuit circuit, ElementLibrary library) throws TestingDataException, ElementNotFoundException, PinException, NodeException { + public ValueTableDialog addTestResult(java.util.List tsl, Circuit circuit, ElementLibrary library) throws TestingDataException, ElementNotFoundException, PinException, NodeException { Collections.sort(tsl); int i = 0; int errorTabIndex = -1; - for (TestSet ts : tsl) { - Model model = new ModelCreator(circuit, library).createModel(false); + for (Circuit.TestCase ts : tsl) { ErrorDetector errorDetector = new ErrorDetector(); - model.addObserver(errorDetector); try { - TestExecutor testExecutor = new TestExecutor(ts.data).create(model); + TestExecutor.Result testResult = new TestExecutor(ts, circuit, library) + .addObserver(errorDetector) + .execute(); String tabName; Icon tabIcon; - if (testExecutor.allPassed()) { - tabName = Lang.get("msg_test_N_Passed", ts.name); + if (testResult.allPassed()) { + tabName = Lang.get("msg_test_N_Passed", ts.getLabel()); tabIcon = ICON_PASSED; } else { - tabName = Lang.get("msg_test_N_Failed", ts.name); + tabName = Lang.get("msg_test_N_Failed", ts.getLabel()); tabIcon = ICON_FAILED; errorTabIndex = i; } - if (testExecutor.toManyResults()) + if (testResult.toManyResults()) tabName += " " + Lang.get("msg_test_missingLines"); - tp.addTab(tabName, tabIcon, new JScrollPane(createTable(testExecutor.getResult()))); - if (testExecutor.toManyResults()) + tp.addTab(tabName, tabIcon, new JScrollPane(createTable(testResult.getValueTable()))); + if (testResult.toManyResults()) tp.setToolTipTextAt(i, new LineBreaker().toHTML().breakLines(Lang.get("msg_test_missingLines_tt"))); - resultTableData.add(testExecutor.getResult()); + resultTableData.add(testResult.getValueTable()); i++; errorDetector.check(); } catch (Exception e) { - throw new TestingDataException(Lang.get("err_whileExecutingTests_N0", ts.name), e); - } finally { - model.close(); + throw new TestingDataException(Lang.get("err_whileExecutingTests_N0", ts.getLabel()), e); } } if (errorTabIndex >= 0) @@ -200,48 +195,6 @@ public class ValueTableDialog extends JDialog { return this; } - /** - * A TestSet contains the {@link TestCaseDescription} and the name of the TestData. - * Is only a value bean - */ - public static class TestSet implements Comparable { - - private final TestCaseDescription data; - private final String name; - - /** - * Creates a new instance - * - * @param data the TestData - * @param name the name of the data, eg. the used label - */ - public TestSet(TestCaseDescription data, String name) { - this.data = data; - this.name = name; - } - - @Override - public int compareTo(TestSet o) { - return name.compareTo(o.name); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TestSet testSet = (TestSet) o; - - return name.equals(testSet.name); - - } - - @Override - public int hashCode() { - return name.hashCode(); - } - } - private static class ValueRenderer extends DefaultTableCellRenderer { @Override diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java index 1d3cc7cc5..45b624d39 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLCircuit.java @@ -241,7 +241,7 @@ public class HDLCircuit implements Iterable, HDLModel.BitProvider, Prin && !v.equalsDescription(DummyElement.TEXTDESCRIPTION) && !v.equalsDescription(DummyElement.DATADESCRIPTION) && !v.equalsDescription(DummyElement.RECTDESCRIPTION) - && !v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION) + && !v.equalsDescription(TestCaseElement.DESCRIPTION) && !v.equalsDescription(GenericInitCode.DESCRIPTION); } diff --git a/src/main/java/de/neemann/digital/hdl/verilog2/VerilogTestBenchCreator.java b/src/main/java/de/neemann/digital/hdl/verilog2/VerilogTestBenchCreator.java index 795e4f620..aca25323f 100644 --- a/src/main/java/de/neemann/digital/hdl/verilog2/VerilogTestBenchCreator.java +++ b/src/main/java/de/neemann/digital/hdl/verilog2/VerilogTestBenchCreator.java @@ -5,17 +5,15 @@ */ package de.neemann.digital.hdl.verilog2; -import de.neemann.digital.hdl.vhdl2.*; -import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.data.Value; import de.neemann.digital.draw.elements.Circuit; -import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.hdl.model2.HDLCircuit; import de.neemann.digital.hdl.model2.HDLException; import de.neemann.digital.hdl.model2.HDLModel; import de.neemann.digital.hdl.model2.HDLPort; import de.neemann.digital.hdl.printer.CodePrinter; import de.neemann.digital.hdl.printer.CodePrinterStr; +import de.neemann.digital.hdl.vhdl2.Separator; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.TestCaseDescription; import de.neemann.digital.testing.TestingDataException; @@ -27,9 +25,7 @@ import de.neemann.digital.testing.parser.TestRow; import java.io.File; import java.io.IOException; import java.util.ArrayList; - -import static de.neemann.digital.testing.TestCaseElement.TESTDATA; - +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -38,7 +34,7 @@ import java.util.logging.Logger; * The needed test date is taken from the test cases in the circuit */ public class VerilogTestBenchCreator { - private final ArrayList testCases; + private final List testCases; private final HDLCircuit main; private final String topModuleName; private final HDLModel.Renaming renaming; @@ -54,9 +50,7 @@ public class VerilogTestBenchCreator { public VerilogTestBenchCreator(Circuit circuit, HDLModel model, String topModuleName) { this.main = model.getMain(); this.topModuleName = topModuleName; - testCases = new ArrayList<>(); - for (VisualElement ve : circuit.getTestCases()) - testCases.add(ve.getElementAttributes()); + testCases = circuit.getTestCases(); testFileWritten = new ArrayList<>(); renaming = model.getRenaming(); } @@ -75,7 +69,10 @@ public class VerilogTestBenchCreator { if (p > 0) filename = filename.substring(0, p); - for (ElementAttributes tc : testCases) { + for (Circuit.TestCase tc : testCases) { + if (tc.hasGenericCode()) + throw new HDLException(Lang.get("err_hdlTestCaseHasGenericCode")); + String testName = tc.getLabel(); if (testName.length() > 0) testName = filename + "_" + testName + "_tb"; @@ -107,7 +104,7 @@ public class VerilogTestBenchCreator { return testFileWritten; } - private void writeTestBench(CodePrinter out, String moduleName, String testName, ElementAttributes tc) throws IOException, HDLException, TestingDataException, ParserException { + private void writeTestBench(CodePrinter out, String moduleName, String testName, Circuit.TestCase tc) throws IOException, HDLException, TestingDataException, ParserException { out.print("// A testbench for ").println(testName); out.println("`timescale 1us/1ns").println(); out.print("module ").print(testName).println(";"); @@ -131,7 +128,7 @@ public class VerilogTestBenchCreator { } out.dec().println().print(");").println().println(); - TestCaseDescription testdata = tc.get(TESTDATA); + TestCaseDescription testdata = tc.getTestCaseDescription(); ArrayList dataOrder = new ArrayList<>(); ArrayList inputsInOrder = new ArrayList<>(); diff --git a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLTestBenchCreator.java b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLTestBenchCreator.java index 3b1b7d734..892aa63d6 100644 --- a/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLTestBenchCreator.java +++ b/src/main/java/de/neemann/digital/hdl/vhdl2/VHDLTestBenchCreator.java @@ -5,10 +5,8 @@ */ package de.neemann.digital.hdl.vhdl2; -import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.data.Value; import de.neemann.digital.draw.elements.Circuit; -import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.hdl.model2.HDLCircuit; import de.neemann.digital.hdl.model2.HDLException; import de.neemann.digital.hdl.model2.HDLModel; @@ -25,15 +23,14 @@ import de.neemann.digital.testing.parser.TestRow; import java.io.File; import java.io.IOException; import java.util.ArrayList; - -import static de.neemann.digital.testing.TestCaseElement.TESTDATA; +import java.util.List; /** * Creates a test bench for a model. * The needed test data is taken from the test cases in the circuit */ public class VHDLTestBenchCreator { - private final ArrayList testCases; + private final List testCases; private final HDLCircuit main; private final HDLModel.Renaming renaming; private ArrayList testFileWritten; @@ -47,9 +44,7 @@ public class VHDLTestBenchCreator { VHDLTestBenchCreator(Circuit circuit, HDLModel model) { this.main = model.getMain(); this.renaming = model.getRenaming(); - testCases = new ArrayList<>(); - for (VisualElement ve : circuit.getTestCases()) - testCases.add(ve.getElementAttributes()); + testCases = circuit.getTestCases(); testFileWritten = new ArrayList<>(); } @@ -68,7 +63,10 @@ public class VHDLTestBenchCreator { filename = filename.substring(0, p); VHDLRenaming renaming = new VHDLRenaming(); - for (ElementAttributes tc : testCases) { + for (Circuit.TestCase tc : testCases) { + if (tc.hasGenericCode()) + throw new HDLException(Lang.get("err_hdlTestCaseHasGenericCode")); + String testName = tc.getLabel(); if (testName.length() > 0) { testName = filename + "_" + renaming.checkName(testName) + "_tb"; @@ -95,7 +93,7 @@ public class VHDLTestBenchCreator { return testFileWritten; } - private void writeTestBench(CodePrinter out, String testName, ElementAttributes tc) throws IOException, TestingDataException, ParserException { + private void writeTestBench(CodePrinter out, String testName, Circuit.TestCase tc) throws IOException, TestingDataException, ParserException { out.print("-- A testbench for ").println(testName); out.println("LIBRARY ieee;"); out.println("USE ieee.std_logic_1164.all;"); @@ -140,7 +138,7 @@ public class VHDLTestBenchCreator { out.println("process").inc(); - TestCaseDescription testdata = tc.get(TESTDATA); + TestCaseDescription testdata = tc.getTestCaseDescription(); ArrayList dataOrder = new ArrayList<>(); out.println("type pattern_type is record").inc(); diff --git a/src/main/java/de/neemann/digital/testing/FolderTestRunner.java b/src/main/java/de/neemann/digital/testing/FolderTestRunner.java index db9b43441..198a9ed8e 100644 --- a/src/main/java/de/neemann/digital/testing/FolderTestRunner.java +++ b/src/main/java/de/neemann/digital/testing/FolderTestRunner.java @@ -5,11 +5,9 @@ */ package de.neemann.digital.testing; -import de.neemann.digital.core.Model; import de.neemann.digital.core.NodeException; import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.PinException; -import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.draw.model.ModelCreator; @@ -22,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.List; /** * Runs all tests in al circuits in a folder @@ -185,12 +184,7 @@ public class FolderTestRunner { FileToTest f = files.get(i); try { Circuit circuit = Circuit.loadCircuit(f.file, shapeFactory); - ArrayList testCases = new ArrayList<>(); - for (VisualElement el : circuit.getTestCases()) { - String label = el.getElementAttributes().getLabel(); - TestCaseDescription testData = el.getElementAttributes().get(TestCaseElement.TESTDATA); - testCases.add(new TestCase(label, testData)); - } + List testCases = circuit.getTestCases(); if (testCases.isEmpty()) { // if no test data is available, at least check if the model is error free try { @@ -203,21 +197,20 @@ public class FolderTestRunner { } else { StringBuilder sb = new StringBuilder(); int rowCount = 0; - for (TestCase tc : testCases) { - Model model = new ModelCreator(circuit, library).createModel(false); + for (Circuit.TestCase tc : testCases) { try { - TestExecutor te = new TestExecutor(tc.testData).create(model); - if (te.allPassed()) { - rowCount += te.getResult().getRows(); + TestExecutor.Result tr = new TestExecutor(tc, circuit, library).execute(); + if (tr.allPassed()) { + rowCount += tr.getValueTable().getRows(); } else { if (sb.length() > 0) sb.append("; "); - sb.append(Lang.get("msg_test_N_Failed", tc.label)); + sb.append(Lang.get("msg_test_N_Failed", tc.getLabel())); } } catch (TestingDataException | NodeException e) { if (sb.length() > 0) sb.append("; "); - sb.append(tc.label).append(": ").append(e.getMessage()); + sb.append(tc.getLabel()).append(": ").append(e.getMessage()); } } if (sb.length() == 0) { @@ -227,7 +220,7 @@ public class FolderTestRunner { setMessage(f, i, sb.toString(), FileToTest.Status.failed); } - } catch (IOException | NodeException | ElementNotFoundException | PinException | ParserException | RuntimeException e) { + } catch (IOException | ElementNotFoundException | PinException | ParserException | RuntimeException e) { setMessage(f, i, e.getMessage(), FileToTest.Status.error); } } @@ -239,16 +232,6 @@ public class FolderTestRunner { } } - private static final class TestCase { - private final String label; - private final TestCaseDescription testData; - - private TestCase(String label, TestCaseDescription testData) { - this.label = label; - this.testData = testData; - } - } - /** * Interface to notify a listener for changes */ diff --git a/src/main/java/de/neemann/digital/testing/TestCaseDescription.java b/src/main/java/de/neemann/digital/testing/TestCaseDescription.java index 5270751c5..0681cb220 100644 --- a/src/main/java/de/neemann/digital/testing/TestCaseDescription.java +++ b/src/main/java/de/neemann/digital/testing/TestCaseDescription.java @@ -63,7 +63,7 @@ public class TestCaseDescription { } private void check() throws TestingDataException { - if (lines == null) { + if (lines == null || names == null) { try { Parser tdp = new Parser(dataString).parse(); lines = tdp.getLines(); @@ -106,4 +106,9 @@ public class TestCaseDescription { public int hashCode() { return dataString != null ? dataString.hashCode() : 0; } + + @Override + public String toString() { + return dataString; + } } diff --git a/src/main/java/de/neemann/digital/testing/TestCaseElement.java b/src/main/java/de/neemann/digital/testing/TestCaseElement.java index 1106ea7f9..20e206b81 100644 --- a/src/main/java/de/neemann/digital/testing/TestCaseElement.java +++ b/src/main/java/de/neemann/digital/testing/TestCaseElement.java @@ -15,18 +15,13 @@ import de.neemann.digital.core.element.*; */ public class TestCaseElement implements Element { - /** - * the used {@link ElementAttributes} key - */ - public static final Key TESTDATA = new Key<>("Testdata", () -> new TestCaseDescription("")); - /** * The TestCaseElement description */ - public static final ElementTypeDescription TESTCASEDESCRIPTION + public static final ElementTypeDescription DESCRIPTION = new ElementTypeDescription("Testcase", TestCaseElement.class) .addAttribute(Keys.LABEL) - .addAttribute(TESTDATA) + .addAttribute(Keys.TESTDATA) .addAttribute(Keys.ENABLED) .supportsHDL(); diff --git a/src/main/java/de/neemann/digital/testing/TestExecutor.java b/src/main/java/de/neemann/digital/testing/TestExecutor.java index 8b8f4beda..fb1005fc6 100644 --- a/src/main/java/de/neemann/digital/testing/TestExecutor.java +++ b/src/main/java/de/neemann/digital/testing/TestExecutor.java @@ -6,9 +6,16 @@ package de.neemann.digital.testing; import de.neemann.digital.core.*; +import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.wiring.Clock; import de.neemann.digital.data.Value; import de.neemann.digital.data.ValueTable; +import de.neemann.digital.draw.elements.Circuit; +import de.neemann.digital.draw.elements.PinException; +import de.neemann.digital.draw.library.ElementLibrary; +import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.ResolveGenerics; +import de.neemann.digital.draw.model.ModelCreator; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.parser.Context; import de.neemann.digital.testing.parser.LineEmitter; @@ -26,6 +33,7 @@ public class TestExecutor { private static final int ERR_RESULTS = MAX_RESULTS * 2; private final ArrayList names; + private final Model model; private final LineEmitter lines; private final ValueTable results; private boolean errorOccurred; @@ -38,87 +46,117 @@ public class TestExecutor { private boolean allowMissingInputs; /** - * Creates a new testing result + * Creates a new testing result. * - * @param testCaseDescription the testing data - * @throws TestingDataException DataException + * @param testCase the testing data + * @param circuit the circuit + * @param library the library + * @throws TestingDataException DataException + * @throws ElementNotFoundException ElementNotFoundException + * @throws PinException PinException + * @throws NodeException NodeException */ - public TestExecutor(TestCaseDescription testCaseDescription) throws TestingDataException { - names = testCaseDescription.getNames(); - results = new ValueTable(names); - visibleRows = 0; - lines = testCaseDescription.getLines(); + public TestExecutor(Circuit.TestCase testCase, Circuit circuit, ElementLibrary library) throws TestingDataException, NodeException, ElementNotFoundException, PinException { + this(testCase.getTestCaseDescription(), createModel(testCase, circuit, library)); + } + + static private Model createModel(Circuit.TestCase testCase, Circuit circuit, ElementLibrary library) throws NodeException, ElementNotFoundException, PinException { + final Model model; + if (circuit != null && circuit.getAttributes().get(Keys.IS_GENERIC) && testCase.hasGenericCode()) { + Circuit c = new ResolveGenerics().resolveCircuit(testCase.getVisualElement(), circuit, library).getCircuit(); + model = new ModelCreator(c, library, false).createModel(false); + } else + model = new ModelCreator(circuit, library).createModel(false); + return model; } /** - * Creates the result by comparing the testing vector with the given model- + * Use for tests only! Don't use this constructor with a model you have created from a circuit. + * If a circuit is available use the constructor above. * - * @param model the model to check - * @return this for chained calls + * @param testCase the test case + * @param model the model + * @throws TestingDataException TestingDataException + */ + public TestExecutor(TestCaseDescription testCase, Model model) throws TestingDataException { + names = testCase.getNames(); + this.model = model; + results = new ValueTable(names); + visibleRows = 0; + lines = testCase.getLines(); + } + + /** + * Creates the result by comparing the testing vector with the given model + * + * @return the result of the test execution * @throws TestingDataException DataException * @throws NodeException NodeException * @throws ParserException ParserException */ - public TestExecutor create(Model model) throws TestingDataException, NodeException, ParserException { - HashSet usedSignals = new HashSet<>(); - - inputs = new ArrayList<>(); - outputs = new ArrayList<>(); - for (Signal s : model.getInputs()) { - final int index = getIndexOf(s.getName()); - if (index >= 0) { - inputs.add(new TestSignal(index, s.getValue())); - addTo(usedSignals, s.getName()); - } - ObservableValue outValue = s.getBidirectionalReader(); - if (outValue != null) { - final String outName = s.getName() + "_out"; - final int inIndex = getIndexOf(outName); - if (inIndex >= 0) { - outputs.add(new TestSignal(inIndex, outValue)); - addTo(usedSignals, outName); + public TestExecutor.Result execute() throws TestingDataException, NodeException, ParserException { + try { + HashSet usedSignals = new HashSet<>(); + inputs = new ArrayList<>(); + outputs = new ArrayList<>(); + for (Signal s : model.getInputs()) { + final int index = getIndexOf(s.getName()); + if (index >= 0) { + inputs.add(new TestSignal(index, s.getValue())); + addTo(usedSignals, s.getName()); + } + ObservableValue outValue = s.getBidirectionalReader(); + if (outValue != null) { + final String outName = s.getName() + "_out"; + final int inIndex = getIndexOf(outName); + if (inIndex >= 0) { + outputs.add(new TestSignal(inIndex, outValue)); + addTo(usedSignals, outName); + } } } - } - for (Clock c : model.getClocks()) { - final int index = getIndexOf(c.getLabel()); - if (index >= 0) { - inputs.add(new TestSignal(index, c.getClockOutput())); - addTo(usedSignals, c.getLabel()); + for (Clock c : model.getClocks()) { + final int index = getIndexOf(c.getLabel()); + if (index >= 0) { + inputs.add(new TestSignal(index, c.getClockOutput())); + addTo(usedSignals, c.getLabel()); + } } - } - for (Signal s : model.getOutputs()) { - final int index = getIndexOf(s.getName()); - if (index >= 0) { - outputs.add(new TestSignal(index, s.getValue())); - addTo(usedSignals, s.getName()); + for (Signal s : model.getOutputs()) { + final int index = getIndexOf(s.getName()); + if (index >= 0) { + outputs.add(new TestSignal(index, s.getValue())); + addTo(usedSignals, s.getName()); + } } + + for (String name : names) + if (!usedSignals.contains(name)) + if (allowMissingInputs) + inputs.add(new TestSignal(getIndexOf(name), null)); + else + throw new TestingDataException(Lang.get("err_testSignal_N_notFound", name)); + + if (inputs.size() == 0) + throw new TestingDataException(Lang.get("err_noTestInputSignalsDefined")); + + if (outputs.size() == 0) + throw new TestingDataException(Lang.get("err_noTestOutputSignalsDefined")); + + model.init(); + model.addObserver(event -> { + if (event.getType() == ModelEventType.ERROR_OCCURRED) + errorOccurred = true; + }, ModelEventType.ERROR_OCCURRED); + + lines.emitLines(new LineListenerResolveDontCare(values -> checkRow(model, values), inputs), new Context().setModel(model)); + + return new Result(); + } finally { + model.close(); } - - for (String name : names) - if (!usedSignals.contains(name)) - if (allowMissingInputs) - inputs.add(new TestSignal(getIndexOf(name), null)); - else - throw new TestingDataException(Lang.get("err_testSignal_N_notFound", name)); - - if (inputs.size() == 0) - throw new TestingDataException(Lang.get("err_noTestInputSignalsDefined")); - - if (outputs.size() == 0) - throw new TestingDataException(Lang.get("err_noTestOutputSignalsDefined")); - - model.init(); - model.addObserver(event -> { - if (event.getType() == ModelEventType.ERROR_OCCURRED) - errorOccurred = true; - }, ModelEventType.ERROR_OCCURRED); - - lines.emitLines(new LineListenerResolveDontCare(values -> checkRow(model, values), inputs), new Context().setModel(model)); - - return this; } private void addTo(HashSet signals, String name) throws TestingDataException { @@ -205,42 +243,6 @@ public class TestExecutor { toManyResults = true; } - /** - * @return true if all tests have passed - */ - public boolean allPassed() { - return !errorOccurred && failedCount == 0 && passedCount > 0; - } - - /** - * @return true if the test failed due to an error - */ - public boolean isErrorOccurred() { - return errorOccurred; - } - - /** - * @return the percentage of failed test rows - */ - public int failedPercent() { - if (passedCount == 0) - return 100; - int p = 100 * failedCount / passedCount; - if (p == 0 && failedCount > 0) - p = 1; - return p; - } - - /** - * Indicates if there are to many entries in the table to show. - * If there are to many entries, the test results is still correct. - * - * @return true if there are missing items in the results list. - */ - public boolean toManyResults() { - return toManyResults; - } - private int getIndexOf(String name) { if (name == null || name.length() == 0) return -1; @@ -253,13 +255,6 @@ public class TestExecutor { return -1; } - /** - * @return return the result - */ - public ValueTable getResult() { - return results; - } - /** * Allow missing inputs * @@ -271,14 +266,25 @@ public class TestExecutor { return this; } + /** + * Adds a observer to the model of this test executor + * + * @param observer the observer to add + * @return this for chained calls + */ + public TestExecutor addObserver(ModelStateObserverTyped observer) { + model.addObserver(observer); + return this; + } + /** * A test signal */ - public static class TestSignal { + public final static class TestSignal { private final int index; private final ObservableValue value; - TestSignal(int index, ObservableValue value) { + private TestSignal(int index, ObservableValue value) { this.index = index; this.value = value; } @@ -291,4 +297,55 @@ public class TestExecutor { } } + /** + * The result of the test execution + */ + public final class Result { + + private Result() { + } + + /** + * @return true if all tests have passed + */ + public boolean allPassed() { + return !errorOccurred && failedCount == 0 && passedCount > 0; + } + + /** + * @return true if the test failed due to an error + */ + public boolean isErrorOccurred() { + return errorOccurred; + } + + /** + * @return the percentage of failed test rows + */ + public int failedPercent() { + if (passedCount == 0) + return 100; + int p = 100 * failedCount / passedCount; + if (p == 0 && failedCount > 0) + p = 1; + return p; + } + + /** + * Indicates if there are to many entries in the table to show. + * If there are to many entries, the test results is still correct. + * + * @return true if there are missing items in the results list. + */ + public boolean toManyResults() { + return toManyResults; + } + + /** + * @return the value table containing the detailed result + */ + public ValueTable getValueTable() { + return results; + } + } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index 3a929929f..4a928b30d 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1047,6 +1047,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Es fehlt ein Name. Sind z.B. alle Pins benannt? Es sind mehrere Ausgänge miteinander verbunden. Diese Art der Verschaltung wird beim HDL-Export nicht unterstützt ({0}, {1}, {2}). + Testfälle mit generischer Parametrisierung werden im HDL-Export nicht + unterstützt! + unbenanntes Netz Zu viele Variablen! Ungültiger Ausdruck! diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index d6e1e1528..d10de9529 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1057,6 +1057,9 @@ A name is missing. Have e.g. all pins a label set? Several outputs are connected to each other. This type of interconnection is not supported for HDL export. ({0}, {1}, {2}). + Test cases with generic parameterization are not supported in HDL + export! + unnamed net Too many variables! Invalid expression! diff --git a/src/test/java/de/neemann/digital/docu/ScreenShots.java b/src/test/java/de/neemann/digital/docu/ScreenShots.java index c799a795c..6138146fe 100644 --- a/src/test/java/de/neemann/digital/docu/ScreenShots.java +++ b/src/test/java/de/neemann/digital/docu/ScreenShots.java @@ -6,7 +6,6 @@ package de.neemann.digital.docu; import de.neemann.digital.analyse.TruthTable; -import de.neemann.digital.analyse.TruthTableTableModel; import de.neemann.digital.analyse.expression.format.FormatToExpression; import de.neemann.digital.core.element.Keys; import de.neemann.digital.fsm.gui.FSMFrame; @@ -353,7 +352,7 @@ public class ScreenShots { .add(new GuiTester.WindowCheck<>(Main.class, (gt, w) -> w.setSize(WIN_DX, WIN_DY))) .delay(500) .add(new ScreenShot<>(Main.class)) - .add(new TestInGUI.SetMouseToElement((v) -> v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION))) + .add(new TestInGUI.SetMouseToElement((v) -> v.equalsDescription(TestCaseElement.DESCRIPTION))) .mouseClick(InputEvent.BUTTON3_MASK) .delay(500) .add(new GuiTester.WindowCheck<>(AttributeDialog.class, (gt, w) -> { @@ -391,7 +390,7 @@ public class ScreenShots { .add(new GuiTester.WindowCheck<>(Main.class, (gt, w) -> w.setSize(WIN_DX, WIN_DY))) .delay(500) .add(new ScreenShot<>(Main.class)) - .add(new TestInGUI.SetMouseToElement((v) -> v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION))) + .add(new TestInGUI.SetMouseToElement((v) -> v.equalsDescription(TestCaseElement.DESCRIPTION))) .mouseClick(InputEvent.BUTTON3_MASK) .delay(500) .add(new GuiTester.WindowCheck<>(AttributeDialog.class, (gt, w) -> { diff --git a/src/test/java/de/neemann/digital/draw/library/JarComponentManagerTest.java b/src/test/java/de/neemann/digital/draw/library/JarComponentManagerTest.java index e4d40c690..880511f0c 100644 --- a/src/test/java/de/neemann/digital/draw/library/JarComponentManagerTest.java +++ b/src/test/java/de/neemann/digital/draw/library/JarComponentManagerTest.java @@ -5,11 +5,9 @@ */ package de.neemann.digital.draw.library; -import de.neemann.digital.draw.elements.VisualElement; +import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.integration.Resources; import de.neemann.digital.integration.ToBreakRunner; -import de.neemann.digital.testing.TestCaseDescription; -import de.neemann.digital.testing.TestCaseElement; import de.neemann.digital.testing.TestExecutor; import junit.framework.TestCase; @@ -35,13 +33,7 @@ public class JarComponentManagerTest extends TestCase { } }; - for (VisualElement ve : br.getCircuit().getElements()) { - if (ve.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION)) { - TestCaseDescription td = ve.getElementAttributes().get(TestCaseElement.TESTDATA); - TestExecutor tr = new TestExecutor(td).create(br.getModel()); - assertTrue(tr.allPassed()); - } - } + for (Circuit.TestCase tc : br.getCircuit().getTestCases()) + assertTrue(new TestExecutor(tc, br.getCircuit(), br.getLibrary()).execute().allPassed()); } - } diff --git a/src/test/java/de/neemann/digital/hdl/TestHDLExportFlag.java b/src/test/java/de/neemann/digital/hdl/TestHDLExportFlag.java index 9e93e2bab..57976ab2c 100644 --- a/src/test/java/de/neemann/digital/hdl/TestHDLExportFlag.java +++ b/src/test/java/de/neemann/digital/hdl/TestHDLExportFlag.java @@ -43,7 +43,7 @@ public class TestHDLExportFlag extends TestCase { implicitSupported.add(Tunnel.DESCRIPTION); implicitSupported.add(Splitter.DESCRIPTION); - implicitSupported.add(TestCaseElement.TESTCASEDESCRIPTION); + implicitSupported.add(TestCaseElement.DESCRIPTION); implicitSupported.add(GenericInitCode.DESCRIPTION); } diff --git a/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java b/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java index 669151e18..e9a3bdb0b 100644 --- a/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java +++ b/src/test/java/de/neemann/digital/hdl/hgs/ParserTest.java @@ -375,6 +375,19 @@ public class ParserTest extends TestCase { assertEquals("false;", c.toString()); } + public void testStringCreation() throws IOException, ParserException, HGSEvalException { + String code = "?>Test:;").parse(); Context funcs = new Context().declareVar("type", new Function(1) { diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index 2dc450077..a5888dfcd 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -6,7 +6,6 @@ package de.neemann.digital.integration; import de.neemann.digital.core.ErrorDetector; -import de.neemann.digital.core.Model; import de.neemann.digital.core.NodeException; import de.neemann.digital.core.element.Keys; import de.neemann.digital.draw.elements.Circuit; @@ -17,8 +16,6 @@ import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.draw.library.GenericInitCode; import de.neemann.digital.draw.library.ResolveGenerics; import de.neemann.digital.draw.model.ModelCreator; -import de.neemann.digital.testing.TestCaseDescription; -import de.neemann.digital.testing.TestCaseElement; import de.neemann.digital.testing.TestExecutor; import junit.framework.TestCase; @@ -42,7 +39,7 @@ public class TestExamples extends TestCase { public void testDistExamples() throws Exception { File examples = new File(Resources.getRoot().getParentFile().getParentFile(), "/main/dig"); assertEquals(302, new FileScanner(this::check).scan(examples)); - assertEquals(198, testCasesInFiles); + assertEquals(203, testCasesInFiles); } /** @@ -79,29 +76,23 @@ public class TestExamples extends TestCase { assertEquals("wrong locked mode", isLib, (boolean) br.getCircuit().getAttributes().get(Keys.LOCKED_MODE)); try { - for (VisualElement el : br.getCircuit().getElements()) - if (el.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION)) { - testCasesInFiles++; + for (Circuit.TestCase tc : br.getCircuit().getTestCases()) { + testCasesInFiles++; - String label = el.getElementAttributes().getLabel(); - TestCaseDescription td = el.getElementAttributes().get(TestCaseElement.TESTDATA); + String label = tc.getLabel(); - Model model = new ModelCreator(br.getCircuit(), br.getLibrary()).createModel(false); - ErrorDetector ed = new ErrorDetector(); - model.addObserver(ed); - try { - TestExecutor tr = new TestExecutor(td).create(model); + ErrorDetector ed = new ErrorDetector(); + TestExecutor.Result tr = new TestExecutor(tc, br.getCircuit(), br.getLibrary()) + .addObserver(ed) + .execute(); - if (label.contains("Failing")) - assertFalse(dig.getName() + ":" + label, tr.allPassed()); - else - assertTrue(dig.getName() + ":" + label, tr.allPassed()); + if (label.contains("Failing")) + assertFalse(dig.getName() + ":" + label, tr.allPassed()); + else + assertTrue(dig.getName() + ":" + label, tr.allPassed()); - } finally { - model.close(); - } - ed.check(); - } + ed.check(); + } } catch (Exception e) { if (shouldFail) { return; @@ -114,8 +105,15 @@ public class TestExamples extends TestCase { br.close(); } - if (br.getCircuit().getAttributes().get(Keys.IS_GENERIC)) - checkGeneric(br.getCircuit(), br.getLibrary()); + if (br.getCircuit(). + + getAttributes(). + + get(Keys.IS_GENERIC)) + + checkGeneric(br.getCircuit(), br. + + getLibrary()); } private void checkGeneric(Circuit circuit, ElementLibrary library) throws NodeException, ElementNotFoundException, PinException { diff --git a/src/test/java/de/neemann/digital/integration/TestInGUI.java b/src/test/java/de/neemann/digital/integration/TestInGUI.java index fa9958730..ec16e9742 100644 --- a/src/test/java/de/neemann/digital/integration/TestInGUI.java +++ b/src/test/java/de/neemann/digital/integration/TestInGUI.java @@ -61,7 +61,7 @@ import java.util.List; import static de.neemann.digital.draw.shapes.GenericShape.SIZE; import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; import static de.neemann.digital.integration.GuiTester.getBaseContainer; -import static de.neemann.digital.testing.TestCaseElement.TESTDATA; +import static de.neemann.digital.core.element.Keys.TESTDATA; /** * These tests are excluded from the maven build because gui tests are sometimes fragile. @@ -451,7 +451,7 @@ public class TestInGUI extends TestCase { public void testTestEditor() { new GuiTester("dig/manualError/11_editTest.dig") .delay(300) - .add(new SetMouseToElement((v) -> v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION))) + .add(new SetMouseToElement((v) -> v.equalsDescription(TestCaseElement.DESCRIPTION))) .mouseClick(InputEvent.BUTTON3_DOWN_MASK) .delay(300) .type("testIdentzz") @@ -1376,7 +1376,7 @@ public class TestInGUI extends TestCase { @Override public void checkWindow(GuiTester gt, Main main) { main.getCircuitComponent().getCircuit().add( - new VisualElement(TestCaseElement.TESTCASEDESCRIPTION.getName()) + new VisualElement(TestCaseElement.DESCRIPTION.getName()) .setAttribute(TESTDATA, new TestCaseDescription(testdata)) .setShapeFactory(main.getCircuitComponent().getLibrary().getShapeFactory())); } diff --git a/src/test/java/de/neemann/digital/testing/TestResultTest.java b/src/test/java/de/neemann/digital/testing/TestResultTest.java index 15d37e464..47009e9a3 100644 --- a/src/test/java/de/neemann/digital/testing/TestResultTest.java +++ b/src/test/java/de/neemann/digital/testing/TestResultTest.java @@ -47,8 +47,8 @@ public class TestResultTest extends TestCase { + "0 1 1\n" + "1 0 1\n" + "1 1 0\n"); - TestExecutor tr = new TestExecutor(data).create(model); - assertEquals(4,tr.getResult().getRows()); + TestExecutor.Result tr = new TestExecutor(data, model).execute(); + assertEquals(4, tr.getValueTable().getRows()); assertTrue(tr.allPassed()); } @@ -60,14 +60,14 @@ public class TestResultTest extends TestCase { + "0 1 1\n" + "1 0 1\n" + "1 1 0\n"); - TestExecutor te = new TestExecutor(data).create(model); - ValueTable tr = te.getResult(); - assertEquals(4,tr.getRows()); - assertFalse(te.allPassed()); - assertEquals(true, ((MatchedValue) tr.getValue(0, 2)).isPassed()); - assertEquals(true, ((MatchedValue) tr.getValue(1, 2)).isPassed()); - assertEquals(true, ((MatchedValue) tr.getValue(2, 2)).isPassed()); - assertEquals(false, ((MatchedValue) tr.getValue(3, 2)).isPassed()); + TestExecutor.Result tr = new TestExecutor(data, model).execute(); + ValueTable valueTable = tr.getValueTable(); + assertEquals(4, valueTable.getRows()); + assertFalse(tr.allPassed()); + assertEquals(true, ((MatchedValue) valueTable.getValue(0, 2)).isPassed()); + assertEquals(true, ((MatchedValue) valueTable.getValue(1, 2)).isPassed()); + assertEquals(true, ((MatchedValue) valueTable.getValue(2, 2)).isPassed()); + assertEquals(false, ((MatchedValue) valueTable.getValue(3, 2)).isPassed()); } public void testResultDontCare() throws Exception { @@ -78,10 +78,10 @@ public class TestResultTest extends TestCase { + "0 1 1\n" + "1 0 1\n" + "1 1 x\n"); - TestExecutor te = new TestExecutor(data).create(model); - ValueTable tr = te.getResult(); - assertEquals(4,tr.getRows()); - assertTrue(te.allPassed()); + TestExecutor.Result tr = new TestExecutor(data, model).execute(); + ValueTable valueTable = tr.getValueTable(); + assertEquals(4, valueTable.getRows()); + assertTrue(tr.allPassed()); } public void testResultDontCare2() throws Exception { @@ -92,10 +92,10 @@ public class TestResultTest extends TestCase { + "0 1 1\n" + "1 0 1\n" + "1 1 1\n"); - TestExecutor te = new TestExecutor(data).create(model); - ValueTable tr = te.getResult(); - assertEquals(4,tr.getRows()); - assertTrue(te.allPassed()); + TestExecutor.Result tr = new TestExecutor(data, model).execute(); + ValueTable valueTable = tr.getValueTable(); + assertEquals(4, valueTable.getRows()); + assertTrue(tr.allPassed()); } public void testResultDontCareInput() throws Exception { @@ -104,10 +104,10 @@ public class TestResultTest extends TestCase { "A B Y\n" + "x 0 0\n" + "x 1 1\n"); - TestExecutor te = new TestExecutor(data).create(model); - ValueTable tr = te.getResult(); - assertEquals(4,tr.getRows()); - assertTrue(te.allPassed()); + TestExecutor.Result tr = new TestExecutor(data, model).execute(); + ValueTable valueTable = tr.getValueTable(); + assertEquals(4, valueTable.getRows()); + assertTrue(tr.allPassed()); } public void testResultDontCareInput2() throws Exception { @@ -116,10 +116,10 @@ public class TestResultTest extends TestCase { "A B C Y\n" + "x x 0 0\n" + "x x 1 1\n"); - TestExecutor te = new TestExecutor(data).create(model); - ValueTable tr = te.getResult(); - assertEquals(8,tr.getRows()); - assertTrue(te.allPassed()); + TestExecutor.Result tr = new TestExecutor(data, model).execute(); + ValueTable valueTable = tr.getValueTable(); + assertEquals(8, valueTable.getRows()); + assertTrue(tr.allPassed()); } }