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: print(n); str:=output();";
+ Statement s = new Parser(code).parse(false);
+
+ Context c = new Context().declareVar("n", 3);
+ s.execute(c);
+ assertEquals("Test:3", c.getVar("str"));
+
+ c = new Context().declareVar("n", 12);
+ s.execute(c);
+ assertEquals("Test:12", c.getVar("str"));
+ }
+
public void testAddFunction() throws IOException, ParserException, HGSEvalException {
Statement s = new Parser("a : in =type(Bits)?>;").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());
}
}