Merge branch 'genericTestCases'

This commit is contained in:
hneemann 2020-11-08 08:18:53 +01:00
commit 4208c4de87
28 changed files with 593 additions and 363 deletions

View File

@ -108,7 +108,111 @@ shiftBits:=bitsNeededFor(args.dataBits-1);</string>
direction := &quot;left&quot;;</string>
</entry>
</elementAttributes>
<pos x="400" y="0"/>
<pos x="360" y="200"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>4 bits, left</string>
</entry>
<entry>
<string>Testdata</string>
<testData>
<dataString>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
</dataString>
</testData>
</entry>
<entry>
<string>generic</string>
<string>dataBits := 4;
direction := &quot;left&quot;;</string>
</entry>
</elementAttributes>
<pos x="200" y="0"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>4 bits, right</string>
</entry>
<entry>
<string>Testdata</string>
<testData>
<dataString>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</dataString>
</testData>
</entry>
<entry>
<string>generic</string>
<string>dataBits := 4;
direction := &quot;right&quot;;</string>
</entry>
</elementAttributes>
<pos x="380" y="0"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>4 bits, arith</string>
</entry>
<entry>
<string>Testdata</string>
<testData>
<dataString>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</dataString>
</testData>
</entry>
<entry>
<string>generic</string>
<string>dataBits := 4;
direction := &quot;arith&quot;;</string>
</entry>
</elementAttributes>
<pos x="540" y="0"/>
</visualElement>
</visualElements>
<wires>

View File

@ -35,6 +35,10 @@
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>3 bits</string>
</entry>
<entry>
<string>Testdata</string>
<testData>
@ -47,8 +51,12 @@ C 0
</dataString>
</testData>
</entry>
<entry>
<string>generic</string>
<string>bits := 3;</string>
</entry>
</elementAttributes>
<pos x="620" y="40"/>
<pos x="680" y="40"/>
</visualElement>
<visualElement>
<elementName>Text</elementName>
@ -129,6 +137,10 @@ ist als drei.}}</string>
<string>Bits</string>
<int>3</int>
</entry>
<entry>
<string>generic</string>
<string>this.Bits=int(args.bits);</string>
</entry>
</elementAttributes>
<pos x="680" y="340"/>
</visualElement>
@ -153,7 +165,59 @@ if (args.bits&gt;3) {
<string>bits := 3;</string>
</entry>
</elementAttributes>
<pos x="200" y="160"/>
<pos x="680" y="200"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>4 bits</string>
</entry>
<entry>
<string>Testdata</string>
<testData>
<dataString>C G
0 0
loop (n,(1&lt;&lt;4)-1)
C ((n+1) ^ ((n+1)&gt;&gt;1))
end loop
C 0
</dataString>
</testData>
</entry>
<entry>
<string>generic</string>
<string>bits := 4;</string>
</entry>
</elementAttributes>
<pos x="780" y="40"/>
</visualElement>
<visualElement>
<elementName>Testcase</elementName>
<elementAttributes>
<entry>
<string>Label</string>
<string>5 bits</string>
</entry>
<entry>
<string>Testdata</string>
<testData>
<dataString>C G
0 0
loop (n,(1&lt;&lt;5)-1)
C ((n+1) ^ ((n+1)&gt;&gt;1))
end loop
C 0
</dataString>
</testData>
</entry>
<entry>
<string>generic</string>
<string>bits := 5;</string>
</entry>
</elementAttributes>
<pos x="680" y="120"/>
</visualElement>
</visualElements>
<wires>

View File

@ -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

View File

@ -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<TestCase> testCases;
private List<Circuit.TestCase> 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<TestCase> getTestCasesFrom(Circuit circuit) {
ArrayList<TestCase> 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;

View File

@ -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<Boolean> MIRROR =
new Key<>("mirror", false).allowGroupEdit().setSecondary();
/**
* The test data
*/
public static final Key<TestCaseDescription> TESTDATA =
new Key<>("Testdata", () -> new TestCaseDescription(""));
}

View File

@ -348,8 +348,79 @@ public class Circuit implements Copyable<Circuit> {
*
* @return the test case elements
*/
public List<VisualElement> getTestCases() {
return getElements(v -> v.equalsDescription(TestCaseElement.TESTCASEDESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED));
public List<TestCase> getTestCases() {
ArrayList<TestCase> 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<TestCase> {
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();
}
}
/**

View File

@ -219,7 +219,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
.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)

View File

@ -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);

View File

@ -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<ValueTableDialog.TestSet> tsl = new ArrayList<>();
for (VisualElement el : circuitComponent.getCircuit().getTestCases())
tsl.add(new ValueTableDialog.TestSet(
el.getElementAttributes().get(TestCaseElement.TESTDATA),
el.getElementAttributes().getLabel()));
List<Circuit.TestCase> tsl = circuitComponent.getCircuit().getTestCases();
if (tsl.isEmpty())
throw new TestingDataException(Lang.get("err_noTestData"));

View File

@ -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);
}
}
}
}

View File

@ -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) {

View File

@ -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<TestSet> tsl, Circuit circuit, ElementLibrary library) throws TestingDataException, ElementNotFoundException, PinException, NodeException {
public ValueTableDialog addTestResult(java.util.List<Circuit.TestCase> 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<TestSet> {
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

View File

@ -241,7 +241,7 @@ public class HDLCircuit implements Iterable<HDLNode>, 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);
}

View File

@ -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<ElementAttributes> testCases;
private final List<Circuit.TestCase> 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<HDLPort> dataOrder = new ArrayList<>();
ArrayList<HDLPort> inputsInOrder = new ArrayList<>();

View File

@ -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<ElementAttributes> testCases;
private final List<Circuit.TestCase> testCases;
private final HDLCircuit main;
private final HDLModel.Renaming renaming;
private ArrayList<File> 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<HDLPort> dataOrder = new ArrayList<>();
out.println("type pattern_type is record").inc();

View File

@ -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<TestCase> 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<Circuit.TestCase> 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
*/

View File

@ -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;
}
}

View File

@ -15,18 +15,13 @@ import de.neemann.digital.core.element.*;
*/
public class TestCaseElement implements Element {
/**
* the used {@link ElementAttributes} key
*/
public static final Key<TestCaseDescription> 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();

View File

@ -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<String> 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<String> 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<String> 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<String> 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;
}
}
}

View File

@ -1047,6 +1047,9 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="err_vhdlANameIsMissing">Es fehlt ein Name. Sind z.B. alle Pins benannt?</string>
<string name="err_hdlMultipleOutputsConnectedToNet_N_N_N">Es sind mehrere Ausgänge miteinander verbunden.
Diese Art der Verschaltung wird beim HDL-Export nicht unterstützt ({0}, {1}, {2}).</string>
<string name="err_hdlTestCaseHasGenericCode">Testfälle mit generischer Parametrisierung werden im HDL-Export nicht
unterstützt!
</string>
<string name="err_unnamedNet">unbenanntes Netz</string>
<string name="err_toManyVars">Zu viele Variablen!</string>
<string name="err_invalidExpression">Ungültiger Ausdruck!</string>

View File

@ -1057,6 +1057,9 @@
<string name="err_vhdlANameIsMissing">A name is missing. Have e.g. all pins a label set?</string>
<string name="err_hdlMultipleOutputsConnectedToNet_N_N_N">Several outputs are connected to each other.
This type of interconnection is not supported for HDL export. ({0}, {1}, {2}).</string>
<string name="err_hdlTestCaseHasGenericCode">Test cases with generic parameterization are not supported in HDL
export!
</string>
<string name="err_unnamedNet">unnamed net</string>
<string name="err_toManyVars">Too many variables!</string>
<string name="err_invalidExpression">Invalid expression!</string>

View File

@ -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) -> {

View File

@ -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());
}
}

View File

@ -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);
}

View File

@ -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) {

View File

@ -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 {

View File

@ -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()));
}

View File

@ -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());
}
}