mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-16 16:34:47 -04:00
improved test result dialog
This commit is contained in:
parent
de3af4c4d1
commit
9ec6f52206
@ -0,0 +1,40 @@
|
||||
package de.neemann.digital.gui.components.test;
|
||||
|
||||
import de.neemann.digital.core.ObservableValue;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
/**
|
||||
* A matched value.
|
||||
* The value itself represents the result and the expected value is contained as a member variable
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
public class MatchedValue extends Value {
|
||||
private final Value expected;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param expected the expected value
|
||||
* @param found the found value
|
||||
*/
|
||||
public MatchedValue(Value expected, ObservableValue found) {
|
||||
super(found);
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if test is passed
|
||||
*/
|
||||
public boolean isPassed() {
|
||||
return isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isPassed())
|
||||
return super.toString();
|
||||
else
|
||||
return Lang.get("msg_testExp_N0_found_N1", expected, super.toString());
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
public class TestData implements Iterable<int[]> {
|
||||
public class TestData implements Iterable<Value[]> {
|
||||
|
||||
/**
|
||||
* the default instance
|
||||
@ -16,7 +16,7 @@ public class TestData implements Iterable<int[]> {
|
||||
public static final TestData DEFAULT = new TestData("");
|
||||
|
||||
private String dataString;
|
||||
private transient ArrayList<int[]> lines;
|
||||
private transient ArrayList<Value[]> lines;
|
||||
private transient ArrayList<String> names;
|
||||
|
||||
TestData(String data) {
|
||||
@ -33,7 +33,7 @@ public class TestData implements Iterable<int[]> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<int[]> iterator() {
|
||||
public Iterator<Value[]> iterator() {
|
||||
return lines.iterator();
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ public class TestData implements Iterable<int[]> {
|
||||
/**
|
||||
* @return the data lines
|
||||
*/
|
||||
public ArrayList<int[]> getLines() {
|
||||
public ArrayList<Value[]> getLines() {
|
||||
check();
|
||||
return lines;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import java.util.StringTokenizer;
|
||||
public class TestDataParser {
|
||||
|
||||
private final BufferedReader r;
|
||||
private final ArrayList<int[]> lines;
|
||||
private final ArrayList<Value[]> lines;
|
||||
private final ArrayList<String> names;
|
||||
private int lineNumber;
|
||||
|
||||
@ -46,7 +46,7 @@ public class TestDataParser {
|
||||
|
||||
String line;
|
||||
while ((line = readNonEmptyLine(r)) != null) {
|
||||
int[] row = new int[names.size()];
|
||||
Value[] row = new Value[names.size()];
|
||||
tok = new StringTokenizer(line);
|
||||
int cols = tok.countTokens();
|
||||
if (cols != names.size())
|
||||
@ -56,10 +56,7 @@ public class TestDataParser {
|
||||
String num = null;
|
||||
try {
|
||||
num = tok.nextToken();
|
||||
if (num.toUpperCase().equals("X"))
|
||||
row[i] = -1;
|
||||
else
|
||||
row[i] = Integer.parseInt(num);
|
||||
row[i]=new Value(num);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new DataException(Lang.get("err_notANumber_N0_inLine_N1", num, lineNumber));
|
||||
}
|
||||
@ -86,7 +83,7 @@ public class TestDataParser {
|
||||
/**
|
||||
* @return Returns the data lines
|
||||
*/
|
||||
public ArrayList<int[]> getLines() {
|
||||
public ArrayList<Value[]> getLines() {
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package de.neemann.digital.gui.components.test;
|
||||
|
||||
import de.neemann.digital.core.Model;
|
||||
import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.core.ObservableValue;
|
||||
import de.neemann.digital.core.Signal;
|
||||
import de.neemann.digital.core.wiring.Clock;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
@ -16,10 +17,10 @@ import java.util.ArrayList;
|
||||
public class TestResult implements TableModel {
|
||||
|
||||
private final ArrayList<String> names;
|
||||
private final ArrayList<Line> lines;
|
||||
private final ArrayList<int[]> values;
|
||||
private ArrayList<TestInput> inputs;
|
||||
private ArrayList<TestOutput> outputs;
|
||||
private final ArrayList<Value[]> lines;
|
||||
private final ArrayList<MatchedValue[]> results;
|
||||
private ArrayList<TestSignal> inputs;
|
||||
private ArrayList<TestSignal> outputs;
|
||||
private boolean allPassed;
|
||||
|
||||
/**
|
||||
@ -29,8 +30,8 @@ public class TestResult implements TableModel {
|
||||
*/
|
||||
public TestResult(TestData testData) {
|
||||
names = testData.getNames();
|
||||
values = testData.getLines();
|
||||
lines = new ArrayList<>();
|
||||
lines = testData.getLines();
|
||||
results = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,29 +47,33 @@ public class TestResult implements TableModel {
|
||||
inputs = new ArrayList<>();
|
||||
outputs = new ArrayList<>();
|
||||
for (Signal s : model.getInputs())
|
||||
inputs.add(new TestSignal(s, getIndexOf(s.getName())));
|
||||
inputs.add(new TestSignal(getIndexOf(s.getName()), s.getValue()));
|
||||
for (Clock c : model.getClocks())
|
||||
inputs.add(new TestClock(c, getIndexOf(c.getClockOutput().getName())));
|
||||
inputs.add(new TestSignal(getIndexOf(c.getClockOutput().getName()), c.getClockOutput()));
|
||||
|
||||
for (Signal s : model.getOutputs())
|
||||
outputs.add(new TestSignal(s, getIndexOf(s.getName())));
|
||||
outputs.add(new TestSignal(getIndexOf(s.getName()), s.getValue()));
|
||||
|
||||
model.init();
|
||||
|
||||
for (int[] row : values) {
|
||||
for (TestInput in : inputs)
|
||||
in.setFrom(row);
|
||||
for (Value[] row : lines) {
|
||||
|
||||
MatchedValue[] res = new MatchedValue[row.length];
|
||||
|
||||
for (TestSignal in : inputs) {
|
||||
row[in.index].setTo(in.value);
|
||||
res[in.index]=new MatchedValue(row[in.index], in.value);
|
||||
}
|
||||
|
||||
model.doStep();
|
||||
|
||||
boolean ok = true;
|
||||
for (TestOutput out : outputs) {
|
||||
if (!out.check(row)) {
|
||||
ok = false;
|
||||
for (TestSignal out : outputs) {
|
||||
MatchedValue matchedValue = new MatchedValue(row[out.index], out.value);
|
||||
res[out.index]= matchedValue;
|
||||
if (!matchedValue.isPassed())
|
||||
allPassed = false;
|
||||
}
|
||||
}
|
||||
lines.add(new Line(row, ok));
|
||||
results.add(res);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -107,75 +112,34 @@ public class TestResult implements TableModel {
|
||||
}
|
||||
}
|
||||
|
||||
private interface TestInput {
|
||||
void setFrom(int[] row);
|
||||
}
|
||||
|
||||
private interface TestOutput {
|
||||
boolean check(int[] row);
|
||||
}
|
||||
|
||||
private class TestSignal implements TestInput, TestOutput {
|
||||
private final Signal s;
|
||||
private class TestSignal {
|
||||
private final int index;
|
||||
private final ObservableValue value;
|
||||
|
||||
TestSignal(Signal s, int index) {
|
||||
this.s = s;
|
||||
TestSignal(int index, ObservableValue value) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrom(int[] row) {
|
||||
s.getValue().setValue(row[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(int[] row) {
|
||||
int val = row[index];
|
||||
return val < 0 || val == s.getValue().getValue();
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private class TestClock implements TestInput {
|
||||
private final Clock c;
|
||||
private final int index;
|
||||
|
||||
TestClock(Clock c, int index) {
|
||||
this.c = c;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrom(int[] row) {
|
||||
c.getClockOutput().setValue(row[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return lines.size();
|
||||
return results.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return names.size() + 1;
|
||||
return names.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
if (columnIndex < names.size())
|
||||
return names.get(columnIndex);
|
||||
else
|
||||
return "";
|
||||
return names.get(columnIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getColumnClass(int columnIndex) {
|
||||
if (columnIndex < names.size())
|
||||
return Integer.class;
|
||||
else
|
||||
return Boolean.class;
|
||||
return MatchedValue.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -185,7 +149,17 @@ public class TestResult implements TableModel {
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
return lines.get(rowIndex).getCol(columnIndex);
|
||||
return getValue(rowIndex, columnIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the typed value
|
||||
* @param rowIndex rowIndex
|
||||
* @param columnIndex columnIndex
|
||||
* @return the value
|
||||
*/
|
||||
public MatchedValue getValue(int rowIndex, int columnIndex) {
|
||||
return results.get(rowIndex)[columnIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -5,13 +5,27 @@ import de.neemann.digital.core.NodeException;
|
||||
import de.neemann.digital.lang.Lang;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Dialog to show the test results.
|
||||
*
|
||||
* @author hneemann
|
||||
*/
|
||||
public class TestResultDialog extends JDialog {
|
||||
private static final Color FAILED_COLOR = new Color(255, 200, 200);
|
||||
|
||||
/**
|
||||
* Creates a new result dialog.
|
||||
*
|
||||
* @param owner the parent frame
|
||||
* @param tsl list of test sets
|
||||
* @param model the model to test
|
||||
* @throws NodeException NodeException
|
||||
* @throws DataException DataException
|
||||
*/
|
||||
public TestResultDialog(JFrame owner, ArrayList<TestSet> tsl, Model model) throws NodeException, DataException {
|
||||
super(owner, Lang.get("msg_testResult"), true);
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
@ -19,12 +33,16 @@ public class TestResultDialog extends JDialog {
|
||||
JTabbedPane tp = new JTabbedPane();
|
||||
for (TestSet ts : tsl) {
|
||||
TestResult tr = new TestResult(ts.data).create(model);
|
||||
|
||||
JTable table = new JTable(tr);
|
||||
table.setDefaultRenderer(MatchedValue.class, new MyRenderer());
|
||||
|
||||
String tabName;
|
||||
if (tr.isAllPassed())
|
||||
tabName = Lang.get("msg_test_N_Passed", ts.name);
|
||||
else
|
||||
tabName = Lang.get("msg_test_N_Failed", ts.name);
|
||||
tp.addTab(tabName, new JScrollPane(new JTable(tr)));
|
||||
tp.addTab(tabName, new JScrollPane(table));
|
||||
}
|
||||
|
||||
getContentPane().add(tp);
|
||||
@ -32,14 +50,43 @@ public class TestResultDialog extends JDialog {
|
||||
setLocationRelativeTo(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* A TestSet contains the {@link TestData} and the name of the TestData.
|
||||
* Is only a value bean
|
||||
*/
|
||||
public static class TestSet {
|
||||
|
||||
private final TestData 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(TestData data, String name) {
|
||||
this.data = data;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
JLabel comp = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
MatchedValue v = (MatchedValue) value;
|
||||
|
||||
comp.setText(v.toString());
|
||||
comp.setHorizontalAlignment(JLabel.CENTER);
|
||||
|
||||
if (v.isPassed())
|
||||
comp.setBackground(Color.WHITE);
|
||||
else
|
||||
comp.setBackground(FAILED_COLOR);
|
||||
|
||||
return comp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
package de.neemann.digital.gui.components.test;
|
||||
|
||||
import de.neemann.digital.core.ObservableValue;
|
||||
|
||||
/**
|
||||
* @author hneemann
|
||||
*/
|
||||
public class Value {
|
||||
|
||||
private final long value;
|
||||
private final boolean highZ;
|
||||
private final boolean dontCare;
|
||||
|
||||
public Value(ObservableValue ov) {
|
||||
this.value = ov.getValue();
|
||||
this.highZ = ov.isHighZ();
|
||||
this.dontCare = false;
|
||||
}
|
||||
|
||||
public Value(String val) {
|
||||
val = val.toUpperCase().trim();
|
||||
if (val.equals("X")) {
|
||||
highZ = false;
|
||||
value = 0;
|
||||
dontCare = true;
|
||||
} else {
|
||||
dontCare = false;
|
||||
if (val.equals("Z")) {
|
||||
highZ = true;
|
||||
value = 0;
|
||||
} else {
|
||||
highZ = false;
|
||||
value = Long.parseLong(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEqualTo(ObservableValue ov) {
|
||||
return isEqualTo(new Value(ov));
|
||||
}
|
||||
|
||||
public boolean isEqualTo(Value v) {
|
||||
if (this == v) return true;
|
||||
if (v == null) return false;
|
||||
|
||||
if (dontCare || v.dontCare) return true;
|
||||
|
||||
if (highZ && v.highZ) return true;
|
||||
if (highZ != v.highZ) return false;
|
||||
|
||||
return value == v.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (dontCare)
|
||||
return "X";
|
||||
if (highZ)
|
||||
return "Z";
|
||||
return ObservableValue.getHexString(value);
|
||||
}
|
||||
|
||||
public boolean isDontCare() {
|
||||
return dontCare;
|
||||
}
|
||||
|
||||
public boolean isHighZ() {
|
||||
return highZ;
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setTo(ObservableValue ov) {
|
||||
ov.set(value, isHighZ());
|
||||
}
|
||||
}
|
@ -365,6 +365,7 @@ Die Icons stammen aus dem Tango Desktop Project.</string>
|
||||
<string name="msg_testResult">Testergebnis</string>
|
||||
<string name="msg_test_N_Passed">{0}: ok</string>
|
||||
<string name="msg_test_N_Failed">{0}: Fehler</string>
|
||||
<string name="msg_testExp_N0_found_N1">E: {0} / F: {1}</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="rot_0">0°</string>
|
||||
<string name="rot_180">180°</string>
|
||||
|
@ -366,6 +366,7 @@ The icons are taken from the Tango Desktop Project.</string>
|
||||
<string name="msg_testResult">Test result</string>
|
||||
<string name="msg_test_N_Passed">{0} passed</string>
|
||||
<string name="msg_test_N_Failed">{0} failed</string>
|
||||
<string name="msg_testExp_N0_found_N1">E: {0} / F: {1}</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="rot_0">0°</string>
|
||||
<string name="rot_180">180°</string>
|
||||
|
@ -12,12 +12,20 @@ public class TestDataParserTest extends TestCase {
|
||||
assertEquals(2,td.getNames().size());
|
||||
assertEquals(3,td.getLines().size());
|
||||
|
||||
assertEquals(0, td.getLines().get(0)[0]);
|
||||
assertEquals(1, td.getLines().get(0)[1]);
|
||||
assertEquals(1, td.getLines().get(1)[0]);
|
||||
assertEquals(0, td.getLines().get(1)[1]);
|
||||
assertEquals(-1, td.getLines().get(2)[0]);
|
||||
assertEquals(-1, td.getLines().get(2)[1]);
|
||||
assertEquals(0, td.getLines().get(0)[0].getValue());
|
||||
assertFalse(td.getLines().get(0)[0].isDontCare());
|
||||
|
||||
assertEquals(1, td.getLines().get(0)[1].getValue());
|
||||
assertFalse(td.getLines().get(0)[1].isDontCare());
|
||||
|
||||
assertEquals(1, td.getLines().get(1)[0].getValue());
|
||||
assertFalse(td.getLines().get(1)[0].isDontCare());
|
||||
|
||||
assertEquals(0, td.getLines().get(1)[1].getValue());
|
||||
assertFalse(td.getLines().get(1)[0].isDontCare());
|
||||
|
||||
assertTrue(td.getLines().get(2)[0].isDontCare());
|
||||
assertTrue(td.getLines().get(2)[1].isDontCare());
|
||||
}
|
||||
|
||||
public void testMissingValue() {
|
||||
|
@ -55,10 +55,10 @@ public class TestResultTest extends TestCase {
|
||||
+ "1 1 0\n");
|
||||
TestResult tr = new TestResult(data).create(model);
|
||||
assertFalse(tr.isAllPassed());
|
||||
assertEquals(true, tr.getValueAt(0,4));
|
||||
assertEquals(true, tr.getValueAt(1,4));
|
||||
assertEquals(true, tr.getValueAt(2,4));
|
||||
assertEquals(false, tr.getValueAt(3,4));
|
||||
assertEquals(true, tr.getValue(0,2).isPassed());
|
||||
assertEquals(true, tr.getValue(1,2).isPassed());
|
||||
assertEquals(true, tr.getValue(2,2).isPassed());
|
||||
assertEquals(false, tr.getValue(3,2).isPassed());
|
||||
}
|
||||
|
||||
public void testResultErrorDC() throws Exception {
|
||||
|
@ -0,0 +1,45 @@
|
||||
package de.neemann.digital.gui.components.test;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author hneemann
|
||||
*/
|
||||
public class ValueTest extends TestCase {
|
||||
|
||||
public void testSimple() throws Exception {
|
||||
Value v = new Value("X");
|
||||
assertTrue(v.isDontCare());
|
||||
|
||||
v = new Value("Z");
|
||||
assertTrue(v.isHighZ());
|
||||
assertFalse(v.isDontCare());
|
||||
|
||||
v = new Value("8");
|
||||
assertFalse(v.isHighZ());
|
||||
assertFalse(v.isDontCare());
|
||||
assertEquals(8, v.getValue());
|
||||
}
|
||||
|
||||
public void testCompare() throws Exception {
|
||||
assertTrue(new Value("X").isEqualTo(new Value("X")));
|
||||
assertTrue(new Value("Z").isEqualTo(new Value("X")));
|
||||
assertTrue(new Value("X").isEqualTo(new Value("Z")));
|
||||
assertTrue(new Value("1").isEqualTo(new Value("X")));
|
||||
assertTrue(new Value("X").isEqualTo(new Value("1")));
|
||||
|
||||
assertTrue(new Value("Z").isEqualTo(new Value("Z")));
|
||||
assertFalse(new Value("Z").isEqualTo(new Value("1")));
|
||||
assertFalse(new Value("1").isEqualTo(new Value("Z")));
|
||||
|
||||
assertTrue(new Value("0").isEqualTo(new Value("0")));
|
||||
assertTrue(new Value("1").isEqualTo(new Value("1")));
|
||||
assertFalse(new Value("0").isEqualTo(new Value("1")));
|
||||
}
|
||||
|
||||
public void testToString() throws Exception {
|
||||
assertEquals("X",new Value("X").toString());
|
||||
assertEquals("Z",new Value("Z").toString());
|
||||
assertEquals("2",new Value("2").toString());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user