mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
GP-0 Added ability to ignore specific pcode test failures. Corrected
BigInteger to BigFloat conversion used by INT2FLOAT emulation op.
This commit is contained in:
parent
a3ca5a67e1
commit
f56e922d43
9 changed files with 284 additions and 105 deletions
|
@ -18,6 +18,7 @@ package ghidra.test.processors.support;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.jdom.Document;
|
import org.jdom.Document;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
@ -44,6 +45,8 @@ public class PCodeTestCombinedTestResults {
|
||||||
private File xmlFile;
|
private File xmlFile;
|
||||||
private File htmlFile;
|
private File htmlFile;
|
||||||
|
|
||||||
|
private Map<String, Set<String>> ignoredJunitTestNames = new HashMap<>();
|
||||||
|
|
||||||
private Map<String, PCodeTestResults> combinedResults = new HashMap<>();
|
private Map<String, PCodeTestResults> combinedResults = new HashMap<>();
|
||||||
|
|
||||||
PCodeTestCombinedTestResults(File reportsDir, boolean readExisting) throws IOException {
|
PCodeTestCombinedTestResults(File reportsDir, boolean readExisting) throws IOException {
|
||||||
|
@ -57,12 +60,31 @@ public class PCodeTestCombinedTestResults {
|
||||||
public PCodeTestResults getTestResults(String jUnitName, boolean create) {
|
public PCodeTestResults getTestResults(String jUnitName, boolean create) {
|
||||||
PCodeTestResults testResults = combinedResults.get(jUnitName);
|
PCodeTestResults testResults = combinedResults.get(jUnitName);
|
||||||
if (testResults == null && create) {
|
if (testResults == null && create) {
|
||||||
testResults = new PCodeTestResults(jUnitName);
|
testResults = new PCodeTestResults(jUnitName, new IgnoreTestPredicate(jUnitName));
|
||||||
combinedResults.put(jUnitName, testResults);
|
combinedResults.put(jUnitName, testResults);
|
||||||
}
|
}
|
||||||
return testResults;
|
return testResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class IgnoreTestPredicate implements Predicate<String> {
|
||||||
|
|
||||||
|
private String jUnitName;
|
||||||
|
|
||||||
|
IgnoreTestPredicate(String jUnitName) {
|
||||||
|
this.jUnitName = jUnitName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(String testName) {
|
||||||
|
Set<String> ignoredTestNames = ignoredJunitTestNames.get(jUnitName);
|
||||||
|
if (ignoredTestNames != null) {
|
||||||
|
return ignoredTestNames.contains(testName);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void restoreFromXml() throws IOException {
|
private void restoreFromXml() throws IOException {
|
||||||
|
|
||||||
FileInputStream istream = new FileInputStream(xmlFile);
|
FileInputStream istream = new FileInputStream(xmlFile);
|
||||||
|
@ -80,8 +102,10 @@ public class PCodeTestCombinedTestResults {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<Element> elementList = root.getChildren(PCodeTestResults.TAG_NAME);
|
List<Element> elementList = root.getChildren(PCodeTestResults.TAG_NAME);
|
||||||
for (Element element : elementList) {
|
for (Element element : elementList) {
|
||||||
PCodeTestResults testResults = new PCodeTestResults(element);
|
String jUnitName = PCodeTestResults.getJunitName(element);
|
||||||
combinedResults.put(testResults.getJUnitName(), testResults);
|
PCodeTestResults testResults =
|
||||||
|
new PCodeTestResults(element, new IgnoreTestPredicate(jUnitName));
|
||||||
|
combinedResults.put(jUnitName, testResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (org.jdom.JDOMException je) {
|
catch (org.jdom.JDOMException je) {
|
||||||
|
@ -93,6 +117,14 @@ public class PCodeTestCombinedTestResults {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addIgnoredTests(String junitName, String... testNames) {
|
||||||
|
Set<String> ignoredTestSet =
|
||||||
|
ignoredJunitTestNames.computeIfAbsent(junitName, n -> new HashSet<>());
|
||||||
|
for (String testName : testNames) {
|
||||||
|
ignoredTestSet.add(testName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void saveToXml() throws IOException {
|
void saveToXml() throws IOException {
|
||||||
|
|
||||||
File dir = xmlFile.getParentFile();
|
File dir = xmlFile.getParentFile();
|
||||||
|
@ -226,7 +258,9 @@ public class PCodeTestCombinedTestResults {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int count =
|
int count =
|
||||||
computeCharCount(testResults.passCount) + computeCharCount(testResults.failCount) +
|
computeCharCount(testResults.passCount) +
|
||||||
|
computeCharCount(testResults.ignoredCount) +
|
||||||
|
computeCharCount(testResults.failCount) +
|
||||||
computeCharCount(testResults.callOtherCount) + 2;
|
computeCharCount(testResults.callOtherCount) + 2;
|
||||||
charCount = Math.max(count, charCount);
|
charCount = Math.max(count, charCount);
|
||||||
}
|
}
|
||||||
|
@ -433,6 +467,8 @@ public class PCodeTestCombinedTestResults {
|
||||||
getSummaryHighlightColorClass(testResults) + "\">");
|
getSummaryHighlightColorClass(testResults) + "\">");
|
||||||
writeResultCount(w, testResults.summaryPassCount, Palette.GREEN);
|
writeResultCount(w, testResults.summaryPassCount, Palette.GREEN);
|
||||||
w.print("/");
|
w.print("/");
|
||||||
|
writeResultCount(w, testResults.summaryIgnoreCount, Palette.GRAY);
|
||||||
|
w.print("/");
|
||||||
writeResultCount(w, testResults.summaryFailCount, Palette.RED);
|
writeResultCount(w, testResults.summaryFailCount, Palette.RED);
|
||||||
w.print("/");
|
w.print("/");
|
||||||
writeResultCount(w, testResults.summaryCallOtherCount, Palette.ORANGE);
|
writeResultCount(w, testResults.summaryCallOtherCount, Palette.ORANGE);
|
||||||
|
@ -485,9 +521,10 @@ public class PCodeTestCombinedTestResults {
|
||||||
for (NamedTestColumn namedTestColumn : namedTestColumns) {
|
for (NamedTestColumn namedTestColumn : namedTestColumns) {
|
||||||
String testName = namedTestColumn.getTestName();
|
String testName = namedTestColumn.getTestName();
|
||||||
int pass = testResults.getPassResult(groupName, testName);
|
int pass = testResults.getPassResult(groupName, testName);
|
||||||
|
int ignored = testResults.getIgnoredResult(groupName, testName);
|
||||||
int fail = testResults.getFailResult(groupName, testName);
|
int fail = testResults.getFailResult(groupName, testName);
|
||||||
int callother = testResults.getCallOtherResult(groupName, testName);
|
int callother = testResults.getCallOtherResult(groupName, testName);
|
||||||
int total = pass + fail + callother;
|
int total = pass + ignored + fail + callother;
|
||||||
int totalAsserts = testResults.getTotalAsserts(groupName, testName);
|
int totalAsserts = testResults.getTotalAsserts(groupName, testName);
|
||||||
|
|
||||||
boolean severeFailure = testResults.hadSevereFailure(groupName, testName);
|
boolean severeFailure = testResults.hadSevereFailure(groupName, testName);
|
||||||
|
@ -515,6 +552,8 @@ public class PCodeTestCombinedTestResults {
|
||||||
else {
|
else {
|
||||||
writeResultCount(w, pass, Palette.GREEN);
|
writeResultCount(w, pass, Palette.GREEN);
|
||||||
w.print("/");
|
w.print("/");
|
||||||
|
writeResultCount(w, ignored, Palette.GRAY);
|
||||||
|
w.print("/");
|
||||||
writeResultCount(w, fail, Palette.RED);
|
writeResultCount(w, fail, Palette.RED);
|
||||||
w.print("/");
|
w.print("/");
|
||||||
writeResultCount(w, callother, Palette.ORANGE);
|
writeResultCount(w, callother, Palette.ORANGE);
|
||||||
|
|
|
@ -48,6 +48,10 @@ public class PCodeTestControlBlock extends PCodeTestAbstractControlBlock {
|
||||||
|
|
||||||
private List<PCodeTestGroup> testGroups; // test group data
|
private List<PCodeTestGroup> testGroups; // test group data
|
||||||
|
|
||||||
|
// accumulators for tests pass/fail results which have been designated as ignored
|
||||||
|
private int ignoredPassed = 0;
|
||||||
|
private int ignoredFailed = 0;
|
||||||
|
|
||||||
// TestInfo data read from program memory
|
// TestInfo data read from program memory
|
||||||
private Address onPassFunctionAddress;
|
private Address onPassFunctionAddress;
|
||||||
private Address onErrorFunctionAddress;
|
private Address onErrorFunctionAddress;
|
||||||
|
@ -319,6 +323,40 @@ public class PCodeTestControlBlock extends PCodeTestAbstractControlBlock {
|
||||||
emuWrite(emuTestRunner.getEmulatorHelper(), addr, SIZEOF_U4, value);
|
emuWrite(emuTestRunner.getEmulatorHelper(), addr, SIZEOF_U4, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resultIgnored(String testGroupName, String testName, boolean passed) {
|
||||||
|
if (passed) {
|
||||||
|
++ignoredPassed;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++ignoredFailed;
|
||||||
|
}
|
||||||
|
testResults.addIgnoredResult(testGroupName, testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of passed tests which should be ignored
|
||||||
|
* @return number of passed tests which should be ignored
|
||||||
|
*/
|
||||||
|
int getNumberPassedIgnored() {
|
||||||
|
return ignoredPassed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of failed tests which should be ignored
|
||||||
|
* @return number of failed tests which should be ignored
|
||||||
|
*/
|
||||||
|
int getNumberFailedIgnored() {
|
||||||
|
return ignoredFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear ignored test result accumulators
|
||||||
|
*/
|
||||||
|
void clearNumberIgnored() {
|
||||||
|
ignoredFailed = 0;
|
||||||
|
ignoredPassed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get 'numfail' field value from emulation memory state
|
* Get 'numfail' field value from emulation memory state
|
||||||
* @param emuTestRunner emulator test runner
|
* @param emuTestRunner emulator test runner
|
||||||
|
|
|
@ -35,6 +35,10 @@ public class PCodeTestGroup implements Comparable<PCodeTestGroup> {
|
||||||
*/
|
*/
|
||||||
public static final String FUNCTION_NAME_PREFIX = "main_";
|
public static final String FUNCTION_NAME_PREFIX = "main_";
|
||||||
|
|
||||||
|
public static final String IGNORED_TAG = "IGNORED";
|
||||||
|
private static final String IGNORED_FAILED_TAG = "(" + IGNORED_TAG + ")";
|
||||||
|
private static final String IGNORED_PASSED_TAG = "(Passed and " + IGNORED_TAG + ")";
|
||||||
|
|
||||||
public final String testGroupName;
|
public final String testGroupName;
|
||||||
public final Address functionEntryPtr;
|
public final Address functionEntryPtr;
|
||||||
// public final int testCount; // TODO: not yet fully implemented - do not use!
|
// public final int testCount; // TODO: not yet fully implemented - do not use!
|
||||||
|
@ -57,31 +61,41 @@ public class PCodeTestGroup implements Comparable<PCodeTestGroup> {
|
||||||
return testGroupName + "@" + functionEntryPtr;
|
return testGroupName + "@" + functionEntryPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isIgnoredTest(String testName) {
|
||||||
|
return mainTestControlBlock.getTestResults().isIgnoredTest(testName);
|
||||||
|
}
|
||||||
|
|
||||||
void testPassed(String testName, String errFileName, int errLineNum, Program program,
|
void testPassed(String testName, String errFileName, int errLineNum, Program program,
|
||||||
TestLogger logger) {
|
TestLogger logger) {
|
||||||
|
if (isIgnoredTest(testName)) {
|
||||||
|
mainTestControlBlock.resultIgnored(testGroupName, testName, true);
|
||||||
|
String testDetail =
|
||||||
|
getTestDetail(testName, errFileName, errLineNum, program, IGNORED_PASSED_TAG);
|
||||||
|
testFailures.add(testDetail);
|
||||||
|
logger.log(this, "WARNING! Ignored Test Passed: " + testDetail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
mainTestControlBlock.getTestResults().addPassResult(testGroupName, testName);
|
mainTestControlBlock.getTestResults().addPassResult(testGroupName, testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testFailed(String testName, String errFileName, int errLineNum, boolean callOtherFailure,
|
void testFailed(String testName, String errFileName, int errLineNum, boolean callOtherFailure,
|
||||||
Program program, TestLogger logger) {
|
Program program, TestLogger logger) {
|
||||||
if (callOtherFailure) {
|
String ignoreTag = "";
|
||||||
|
if (isIgnoredTest(testName)) {
|
||||||
|
mainTestControlBlock.resultIgnored(testGroupName, testName, false);
|
||||||
|
ignoreTag = IGNORED_FAILED_TAG;
|
||||||
|
}
|
||||||
|
else if (callOtherFailure) {
|
||||||
mainTestControlBlock.getTestResults().addCallOtherResult(testGroupName, testName);
|
mainTestControlBlock.getTestResults().addCallOtherResult(testGroupName, testName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mainTestControlBlock.getTestResults().addFailResult(testGroupName, testName);
|
mainTestControlBlock.getTestResults().addFailResult(testGroupName, testName);
|
||||||
}
|
}
|
||||||
String failure = testName;
|
String testDetail = getTestDetail(testName, errFileName, errLineNum, program, ignoreTag);
|
||||||
if (testName != null) {
|
testFailures.add(testDetail);
|
||||||
Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, testName,
|
|
||||||
err -> Msg.error(this, err));
|
|
||||||
if (symbol != null) {
|
|
||||||
failure += " @ " + symbol.getAddress().toString(true);
|
|
||||||
}
|
|
||||||
failure += " (" + errFileName + ":" + errLineNum + ")";
|
|
||||||
}
|
|
||||||
testFailures.add(failure);
|
|
||||||
logger.log(this,
|
logger.log(this,
|
||||||
"Test Failed: " + failure + (callOtherFailure ? " (callother error)" : ""));
|
"Test Failed: " + testDetail +
|
||||||
|
(callOtherFailure ? " (callother error)" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
void severeTestFailure(String testName, String errFileName, int errLineNum, Program program,
|
void severeTestFailure(String testName, String errFileName, int errLineNum, Program program,
|
||||||
|
@ -94,6 +108,20 @@ public class PCodeTestGroup implements Comparable<PCodeTestGroup> {
|
||||||
testFailures.clear();
|
testFailures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getTestDetail(String testName, String errFileName, int errLineNum,
|
||||||
|
Program program, String ignoreTag) {
|
||||||
|
String testDetail = testName;
|
||||||
|
if (testName != null) {
|
||||||
|
Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, testName,
|
||||||
|
err -> Msg.error(this, err));
|
||||||
|
if (symbol != null) {
|
||||||
|
testDetail += " @ " + symbol.getAddress().toString(true);
|
||||||
|
}
|
||||||
|
testDetail += " (" + errFileName + ":" + errLineNum + ") " + ignoreTag;
|
||||||
|
}
|
||||||
|
return testDetail;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return list of recorded emulation test failures
|
* @return list of recorded emulation test failures
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,13 +18,15 @@ package ghidra.test.processors.support;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import org.jdom.Attribute;
|
import org.jdom.Attribute;
|
||||||
import org.jdom.Element;
|
import org.jdom.Element;
|
||||||
|
|
||||||
public class PCodeTestResults {
|
public class PCodeTestResults {
|
||||||
|
|
||||||
private String jUnitName;
|
private final String jUnitName;
|
||||||
|
private final Predicate<String> ignoreTestPredicate;
|
||||||
|
|
||||||
boolean summaryHasIngestErrors;
|
boolean summaryHasIngestErrors;
|
||||||
boolean summaryHasRelocationErrors;
|
boolean summaryHasRelocationErrors;
|
||||||
|
@ -32,6 +34,7 @@ public class PCodeTestResults {
|
||||||
|
|
||||||
int summaryTotalAsserts;
|
int summaryTotalAsserts;
|
||||||
int summaryPassCount;
|
int summaryPassCount;
|
||||||
|
int summaryIgnoreCount;
|
||||||
int summaryFailCount;
|
int summaryFailCount;
|
||||||
int summaryCallOtherCount;
|
int summaryCallOtherCount;
|
||||||
int summarySevereFailures;
|
int summarySevereFailures;
|
||||||
|
@ -41,17 +44,91 @@ public class PCodeTestResults {
|
||||||
// map keys formed with "<groupName>.<testName>" string
|
// map keys formed with "<groupName>.<testName>" string
|
||||||
private Map<String, TestResults> results = new HashMap<>();
|
private Map<String, TestResults> results = new HashMap<>();
|
||||||
|
|
||||||
PCodeTestResults(String jUnitName) {
|
private static String XML_VERSION = "1";
|
||||||
|
|
||||||
|
public static String TAG_NAME = "PCodeTestResults";
|
||||||
|
|
||||||
|
PCodeTestResults(String jUnitName, Predicate<String> ignoreTestPredicate) {
|
||||||
this.jUnitName = jUnitName;
|
this.jUnitName = jUnitName;
|
||||||
|
this.ignoreTestPredicate = ignoreTestPredicate;
|
||||||
time = System.currentTimeMillis();
|
time = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PCodeTestResults(Element root, Predicate<String> ignoreTestPredicate) {
|
||||||
|
|
||||||
|
if (!TAG_NAME.equals(root.getName())) {
|
||||||
|
throw new IllegalArgumentException("Unsupported root element: " + root.getName());
|
||||||
|
}
|
||||||
|
String ver = root.getAttributeValue("VERSION");
|
||||||
|
if (!XML_VERSION.equals(ver)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Unsupported XML format version " + ver + ", required format is " + XML_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
jUnitName = getJunitName(root);
|
||||||
|
this.ignoreTestPredicate = ignoreTestPredicate;
|
||||||
|
|
||||||
|
time = 0;
|
||||||
|
String timeStr = root.getAttributeValue("TIME");
|
||||||
|
if (timeStr != null) {
|
||||||
|
try {
|
||||||
|
time = Long.parseLong(timeStr);
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
summaryHasIngestErrors = getAttributeValue(root, "INGEST_ERR", false);
|
||||||
|
summaryHasRelocationErrors = getAttributeValue(root, "RELOC_ERR", false);
|
||||||
|
summaryHasDisassemblyErrors = getAttributeValue(root, "DIS_ERR", false);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Element> elementList = root.getChildren("TestResults");
|
||||||
|
for (Element element : elementList) {
|
||||||
|
|
||||||
|
String testName = element.getAttributeValue("NAME");
|
||||||
|
if (testName == null) {
|
||||||
|
throw new IllegalArgumentException("Invalid TestResults element in XML");
|
||||||
|
}
|
||||||
|
TestResults testResults = new TestResults();
|
||||||
|
testResults.totalAsserts = getAttributeValue(element, "TOTAL_ASSERTS", 0);
|
||||||
|
testResults.passCount = getAttributeValue(element, "PASS", 0);
|
||||||
|
testResults.ignoredCount = getAttributeValue(element, "IGNORE", 0);
|
||||||
|
testResults.failCount = getAttributeValue(element, "FAIL", 0);
|
||||||
|
testResults.callOtherCount = getAttributeValue(element, "CALLOTHER", 0);
|
||||||
|
testResults.severeFailure = getAttributeValue(element, "SEVERE_FAILURE", false);
|
||||||
|
|
||||||
|
summaryTotalAsserts += testResults.totalAsserts;
|
||||||
|
summaryPassCount += testResults.passCount;
|
||||||
|
summaryIgnoreCount += testResults.ignoredCount;
|
||||||
|
summaryFailCount += testResults.failCount;
|
||||||
|
summaryCallOtherCount += testResults.callOtherCount;
|
||||||
|
if (testResults.severeFailure) {
|
||||||
|
++summarySevereFailures;
|
||||||
|
}
|
||||||
|
|
||||||
|
results.put(testName, testResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getJunitName(Element root) {
|
||||||
|
return root.getAttributeValue("JUNIT");
|
||||||
|
}
|
||||||
|
|
||||||
public String getJUnitName() {
|
public String getJUnitName() {
|
||||||
return jUnitName;
|
return jUnitName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
|
private static DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm");
|
||||||
|
|
||||||
|
public boolean isIgnoredTest(String testName) {
|
||||||
|
if (ignoreTestPredicate != null) {
|
||||||
|
return ignoreTestPredicate.test(testName);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTime() {
|
public String getTime() {
|
||||||
if (time == 0) {
|
if (time == 0) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -131,6 +208,21 @@ public class PCodeTestResults {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addIgnoredResult(String groupName, String testName) {
|
||||||
|
String groupTestName = getGroupTestName(groupName, testName);
|
||||||
|
getTestResults(groupTestName, true).ignoredCount++;
|
||||||
|
summaryIgnoreCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIgnoredResult(String groupName, String testName) {
|
||||||
|
String groupTestName = getGroupTestName(groupName, testName);
|
||||||
|
TestResults testResults = getTestResults(groupTestName, false);
|
||||||
|
if (testResults != null) {
|
||||||
|
return testResults.ignoredCount;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void addFailResult(String groupName, String testName) {
|
void addFailResult(String groupName, String testName) {
|
||||||
String groupTestName = getGroupTestName(groupName, testName);
|
String groupTestName = getGroupTestName(groupName, testName);
|
||||||
getTestResults(groupTestName, true).failCount++;
|
getTestResults(groupTestName, true).failCount++;
|
||||||
|
@ -183,71 +275,13 @@ public class PCodeTestResults {
|
||||||
summaryHasDisassemblyErrors = false;
|
summaryHasDisassemblyErrors = false;
|
||||||
summaryTotalAsserts = 0;
|
summaryTotalAsserts = 0;
|
||||||
summaryPassCount = 0;
|
summaryPassCount = 0;
|
||||||
|
summaryIgnoreCount = 0;
|
||||||
summaryFailCount = 0;
|
summaryFailCount = 0;
|
||||||
summaryCallOtherCount = 0;
|
summaryCallOtherCount = 0;
|
||||||
summarySevereFailures = 0;
|
summarySevereFailures = 0;
|
||||||
time = System.currentTimeMillis();
|
time = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String XML_VERSION = "1";
|
|
||||||
|
|
||||||
public static String TAG_NAME = "PCodeTestResults";
|
|
||||||
|
|
||||||
public PCodeTestResults(Element root) {
|
|
||||||
|
|
||||||
if (!TAG_NAME.equals(root.getName())) {
|
|
||||||
throw new IllegalArgumentException("Unsupported root element: " + root.getName());
|
|
||||||
}
|
|
||||||
String ver = root.getAttributeValue("VERSION");
|
|
||||||
if (!XML_VERSION.equals(ver)) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Unsupported XML format version " + ver + ", required format is " + XML_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
jUnitName = root.getAttributeValue("JUNIT");
|
|
||||||
|
|
||||||
time = 0;
|
|
||||||
String timeStr = root.getAttributeValue("TIME");
|
|
||||||
if (timeStr != null) {
|
|
||||||
try {
|
|
||||||
time = Long.parseLong(timeStr);
|
|
||||||
}
|
|
||||||
catch (NumberFormatException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summaryHasIngestErrors = getAttributeValue(root, "INGEST_ERR", false);
|
|
||||||
summaryHasRelocationErrors = getAttributeValue(root, "RELOC_ERR", false);
|
|
||||||
summaryHasDisassemblyErrors = getAttributeValue(root, "DIS_ERR", false);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
List<Element> elementList = root.getChildren("TestResults");
|
|
||||||
for (Element element : elementList) {
|
|
||||||
|
|
||||||
String testName = element.getAttributeValue("NAME");
|
|
||||||
if (testName == null) {
|
|
||||||
throw new IllegalArgumentException("Invalid TestResults element in XML");
|
|
||||||
}
|
|
||||||
TestResults testResults = new TestResults();
|
|
||||||
testResults.totalAsserts = getAttributeValue(element, "TOTAL_ASSERTS", 0);
|
|
||||||
testResults.passCount = getAttributeValue(element, "PASS", 0);
|
|
||||||
testResults.failCount = getAttributeValue(element, "FAIL", 0);
|
|
||||||
testResults.callOtherCount = getAttributeValue(element, "CALLOTHER", 0);
|
|
||||||
testResults.severeFailure = getAttributeValue(element, "SEVERE_FAILURE", false);
|
|
||||||
|
|
||||||
summaryTotalAsserts += testResults.totalAsserts;
|
|
||||||
summaryPassCount += testResults.passCount;
|
|
||||||
summaryFailCount += testResults.failCount;
|
|
||||||
summaryCallOtherCount += testResults.callOtherCount;
|
|
||||||
if (testResults.severeFailure) {
|
|
||||||
++summarySevereFailures;
|
|
||||||
}
|
|
||||||
|
|
||||||
results.put(testName, testResults);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getAttributeValue(Element element, String attrName, int defaultValue) {
|
int getAttributeValue(Element element, String attrName, int defaultValue) {
|
||||||
String val = element.getAttributeValue(attrName);
|
String val = element.getAttributeValue(attrName);
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
|
@ -305,6 +339,8 @@ public class PCodeTestResults {
|
||||||
element.setAttribute(
|
element.setAttribute(
|
||||||
new Attribute("TOTAL_ASSERTS", Integer.toString(testResults.totalAsserts)));
|
new Attribute("TOTAL_ASSERTS", Integer.toString(testResults.totalAsserts)));
|
||||||
element.setAttribute(new Attribute("PASS", Integer.toString(testResults.passCount)));
|
element.setAttribute(new Attribute("PASS", Integer.toString(testResults.passCount)));
|
||||||
|
element.setAttribute(
|
||||||
|
new Attribute("IGNORE", Integer.toString(testResults.ignoredCount)));
|
||||||
element.setAttribute(new Attribute("FAIL", Integer.toString(testResults.failCount)));
|
element.setAttribute(new Attribute("FAIL", Integer.toString(testResults.failCount)));
|
||||||
element.setAttribute(
|
element.setAttribute(
|
||||||
new Attribute("CALLOTHER", Integer.toString(testResults.callOtherCount)));
|
new Attribute("CALLOTHER", Integer.toString(testResults.callOtherCount)));
|
||||||
|
@ -319,6 +355,7 @@ public class PCodeTestResults {
|
||||||
static class TestResults {
|
static class TestResults {
|
||||||
int totalAsserts;
|
int totalAsserts;
|
||||||
int passCount;
|
int passCount;
|
||||||
|
int ignoredCount;
|
||||||
int failCount;
|
int failCount;
|
||||||
int callOtherCount;
|
int callOtherCount;
|
||||||
|
|
||||||
|
@ -326,9 +363,10 @@ public class PCodeTestResults {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
// TODO Auto-generated method stub
|
return "{" + passCount + "/" + ignoredCount + "/" + failCount + "/" + callOtherCount +
|
||||||
return "{" + passCount + "/" + failCount + "/" + callOtherCount + "(" + totalAsserts +
|
"(" + totalAsserts +
|
||||||
")}";
|
")}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ package ghidra.test.processors.support;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.math.*;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -1180,6 +1181,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
// Initialize pass/fail counts at runtime to detect severe failure
|
// Initialize pass/fail counts at runtime to detect severe failure
|
||||||
testGroup.mainTestControlBlock.setNumberPassed(testRunner, Integer.MIN_VALUE);
|
testGroup.mainTestControlBlock.setNumberPassed(testRunner, Integer.MIN_VALUE);
|
||||||
testGroup.mainTestControlBlock.setNumberFailed(testRunner, Integer.MIN_VALUE);
|
testGroup.mainTestControlBlock.setNumberFailed(testRunner, Integer.MIN_VALUE);
|
||||||
|
testGroup.mainTestControlBlock.clearNumberIgnored();
|
||||||
|
|
||||||
boolean done;
|
boolean done;
|
||||||
if (traceDisabled) {
|
if (traceDisabled) {
|
||||||
|
@ -1190,6 +1192,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
}
|
}
|
||||||
|
|
||||||
int pass = testGroup.mainTestControlBlock.getNumberPassed(testRunner);
|
int pass = testGroup.mainTestControlBlock.getNumberPassed(testRunner);
|
||||||
|
int ignoredPassed = testGroup.mainTestControlBlock.getNumberPassedIgnored();
|
||||||
|
int ignoredFailed = testGroup.mainTestControlBlock.getNumberFailedIgnored();
|
||||||
int callOtherErrors = testRunner.getCallOtherErrors();
|
int callOtherErrors = testRunner.getCallOtherErrors();
|
||||||
int fail = testGroup.mainTestControlBlock.getNumberFailed(testRunner);
|
int fail = testGroup.mainTestControlBlock.getNumberFailed(testRunner);
|
||||||
|
|
||||||
|
@ -1199,21 +1203,31 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
pass + " fail " + fail);
|
pass + " fail " + fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pass -= ignoredPassed;
|
||||||
pass -= callOtherErrors;
|
pass -= callOtherErrors;
|
||||||
|
fail -= ignoredFailed;
|
||||||
|
|
||||||
String passFailText = "Passed: " + pass + " Failed: " + fail;
|
String passFailText = "Passed: " + pass + " Ignored: " +
|
||||||
|
(ignoredFailed + ignoredPassed) + " Failed: " + fail;
|
||||||
if (callOtherErrors != 0) {
|
if (callOtherErrors != 0) {
|
||||||
passFailText += " Passed(w/CALLOTHER): " + callOtherErrors;
|
passFailText += " Passed(w/CALLOTHER): " + callOtherErrors;
|
||||||
}
|
}
|
||||||
passFailText += " Expected Assertions: " + totalExpectedAsserts;
|
passFailText += " Expected Assertions: " + totalExpectedAsserts;
|
||||||
log(testGroup, passFailText);
|
log(testGroup, passFailText);
|
||||||
|
|
||||||
|
boolean hasFailures = false;
|
||||||
List<String> testFailures = testGroup.getTestFailures();
|
List<String> testFailures = testGroup.getTestFailures();
|
||||||
if (!testFailures.isEmpty()) {
|
if (!testFailures.isEmpty()) {
|
||||||
log(testGroup, "TEST FAILURES:");
|
if (!traceDisabled) {
|
||||||
|
log(testGroup, "TEST FAILURE SUMMARY:");
|
||||||
|
}
|
||||||
for (String testFailure : testFailures) {
|
for (String testFailure : testFailures) {
|
||||||
|
if (!traceDisabled) {
|
||||||
log(testGroup, " >>> " + testFailure);
|
log(testGroup, " >>> " + testFailure);
|
||||||
}
|
}
|
||||||
|
// failure is any entry not marked as ignored
|
||||||
|
hasFailures |= (testFailure.indexOf(PCodeTestGroup.IGNORED_TAG) < 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!done) {
|
if (!done) {
|
||||||
|
@ -1235,12 +1249,12 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
}
|
}
|
||||||
failTest(testRunner, msg.toString());
|
failTest(testRunner, msg.toString());
|
||||||
}
|
}
|
||||||
int ranCnt = pass + fail + callOtherErrors;
|
int ranCnt = pass + fail + callOtherErrors + ignoredFailed + ignoredPassed;
|
||||||
if ((totalExpectedAsserts != 0) && (totalExpectedAsserts != ranCnt)) {
|
if ((totalExpectedAsserts != 0) && (totalExpectedAsserts != ranCnt)) {
|
||||||
failTest(testRunner,
|
failTest(testRunner,
|
||||||
"ERROR Unexpected number of assertions ( " + passFailText + " )");
|
"ERROR Unexpected number of assertions ( " + passFailText + " )");
|
||||||
}
|
}
|
||||||
if (fail != 0 || callOtherErrors != 0 || testFailures.size() != 0) {
|
if (fail != 0 || callOtherErrors != 0 || hasFailures) {
|
||||||
failTest(testRunner,
|
failTest(testRunner,
|
||||||
"ERROR One or more group tests failed ( " + passFailText + " )");
|
"ERROR One or more group tests failed ( " + passFailText + " )");
|
||||||
}
|
}
|
||||||
|
@ -1424,6 +1438,17 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E
|
||||||
return maxAddr;
|
return maxAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add specified test names to the set of tests which should be ignored due to know issues
|
||||||
|
* or limitations. The tests will still be executed, if present, however they will
|
||||||
|
* not be included in pass/fail counts. They will appear in log as "(IGNORED)" test
|
||||||
|
* result.
|
||||||
|
* @param testNames one or more test names to be ignored
|
||||||
|
*/
|
||||||
|
protected void addIgnoredTests(String... testNames) {
|
||||||
|
combinedResults.addIgnoredTests(getClass().getSimpleName(), testNames);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Protected helper methods which may be overriden
|
// Protected helper methods which may be overriden
|
||||||
//
|
//
|
||||||
|
|
|
@ -136,7 +136,8 @@
|
||||||
<DIV ID="topLeftTable" STYLE="position: absolute; top: 0; left: 0;">
|
<DIV ID="topLeftTable" STYLE="position: absolute; top: 0; left: 0;">
|
||||||
<TABLE ID="headerTable1" BORDER=1 CELLSPACING=0 CELLPADDING=0 style="height: 100; cursor: pointer;" onclick="toggleHeaderHeight()" onmouseover="mouseOverHeader()" onmouseout="mouseOutHeader()">
|
<TABLE ID="headerTable1" BORDER=1 CELLSPACING=0 CELLPADDING=0 style="height: 100; cursor: pointer;" onclick="toggleHeaderHeight()" onmouseover="mouseOverHeader()" onmouseout="mouseOutHeader()">
|
||||||
<TR>
|
<TR>
|
||||||
<TD CLASS="TestNameHead"><DIV STYLE="position:absolute; left: 8px; top: 5px; ">P-Code Test Results</DIV><DIV STYLE="position:absolute; left: 140px; bottom: 5px; "><font color="green" size="2">Pass</font>/<font color="red" size="2">Fail</font>/<font color="orange" size="2">CallOther</font></DIV></TD>
|
<TD CLASS="TestNameHead"><DIV STYLE="position:absolute; left: 8px; top: 5px; ">P-Code Test Results</DIV><DIV STYLE="position:absolute; left: 140px; bottom: 5px; ">
|
||||||
|
<font color="green" size="2">Pass</font>/<font color="gray" size="2">Ignore</font>/<font color="red" size="2">Fail</font>/<font color="orange" size="2">CallOther</font></DIV></TD>
|
||||||
<TD CLASS="DateTimeHead" ALIGN="center" VALIGN="bottom"><DIV CLASS="r90">DATE/TIME</DIV></TD>
|
<TD CLASS="DateTimeHead" ALIGN="center" VALIGN="bottom"><DIV CLASS="r90">DATE/TIME</DIV></TD>
|
||||||
<TD CLASS="ResultSummaryHead" ALIGN="center" VALIGN="bottom"><DIV CLASS="r90">SUMMARY</DIV></TD>
|
<TD CLASS="ResultSummaryHead" ALIGN="center" VALIGN="bottom"><DIV CLASS="r90">SUMMARY</DIV></TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
|
|
@ -518,6 +518,9 @@ public class EmulatorHelper implements MemoryFaultHandler, EmulatorConfiguration
|
||||||
if (t instanceof CancelledException) {
|
if (t instanceof CancelledException) {
|
||||||
throw (CancelledException) t;
|
throw (CancelledException) t;
|
||||||
}
|
}
|
||||||
|
Msg.error(this,
|
||||||
|
"Emulation failure at " + emulator.getExecuteAddress() + ": " + program.getName(),
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,7 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
|
||||||
* @param scale value's scale (signed value with the biased range of expbits)
|
* @param scale value's scale (signed value with the biased range of expbits)
|
||||||
* @throws IllegalArgumentException if invalid unscaled and scale values are specified based upon the fracbits and expbits values.
|
* @throws IllegalArgumentException if invalid unscaled and scale values are specified based upon the fracbits and expbits values.
|
||||||
*/
|
*/
|
||||||
BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled,
|
BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled, int scale) {
|
||||||
int scale) {
|
|
||||||
this.fracbits = fracbits;
|
this.fracbits = fracbits;
|
||||||
this.expbits = expbits;
|
this.expbits = expbits;
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
|
@ -151,21 +150,6 @@ public strictfp class BigFloat implements Comparable<BigFloat> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the BigFloat with the given number of bits representing the given BigInteger.
|
|
||||||
*
|
|
||||||
* @param fracbits number of fractional bits
|
|
||||||
* @param expbits number of bits in the exponent
|
|
||||||
* @param i an integer
|
|
||||||
* @return a BigFloat representing i
|
|
||||||
*/
|
|
||||||
public static BigFloat valueOf(int fracbits, int expbits, BigInteger i) {
|
|
||||||
BigFloat f = new BigFloat(fracbits, expbits, FloatKind.FINITE, i.signum() >= 0 ? +1 : -1,
|
|
||||||
i.abs(), fracbits);
|
|
||||||
f.scaleUpTo(fracbits + 1);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the BigFloat with the given number of bits representing zero.
|
* Return the BigFloat with the given number of bits representing zero.
|
||||||
*
|
*
|
||||||
|
|
|
@ -897,7 +897,7 @@ public strictfp class FloatFormat {
|
||||||
else {
|
else {
|
||||||
a = Utils.convertToUnsignedValue(a, sizein);
|
a = Utils.convertToUnsignedValue(a, sizein);
|
||||||
}
|
}
|
||||||
return getEncoding(BigFloat.valueOf(frac_size, exp_size, a));
|
return getEncoding(valueOf(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long opFloat2Float(long a, FloatFormat outformat) { // convert between floating
|
public long opFloat2Float(long a, FloatFormat outformat) { // convert between floating
|
||||||
|
@ -968,4 +968,27 @@ public strictfp class FloatFormat {
|
||||||
return getEncoding(fa);
|
return getEncoding(fa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigFloat valueOf(BigInteger value) {
|
||||||
|
|
||||||
|
BigInteger unscaled = value;
|
||||||
|
int sign = 1;
|
||||||
|
if (unscaled.signum() < 0) {
|
||||||
|
sign = -1;
|
||||||
|
unscaled = unscaled.negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ulen = unscaled.bitLength();
|
||||||
|
int shift = frac_size + 1 - ulen;
|
||||||
|
|
||||||
|
unscaled = unscaled.shiftLeft(shift);
|
||||||
|
|
||||||
|
int scale = frac_size - shift;
|
||||||
|
|
||||||
|
if (scale > bias) {
|
||||||
|
return BigFloat.infinity(frac_size, exp_size, sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BigFloat(frac_size, exp_size, FloatKind.FINITE, sign, unscaled, scale);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue