improved test result dialog

This commit is contained in:
hneemann 2016-07-07 08:49:16 +02:00
parent de3af4c4d1
commit 9ec6f52206
11 changed files with 281 additions and 90 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"></string>
<string name="rot_180">180°</string>

View File

@ -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"></string>
<string name="rot_180">180°</string>

View File

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

View File

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

View File

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