package org.erlide.test_support.ui.suites;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.erlide.util.ErlLogger;
import org.erlide.util.erlang.OtpBindings;
import org.erlide.util.erlang.OtpErlang;
import org.erlide.util.erlang.OtpParserException;
import com.ericsson.otp.erlang.OtpErlangException;
import com.ericsson.otp.erlang.OtpErlangLong;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.google.common.collect.Lists;
public class TestCaseData {
enum TestState {
// order is important!
//@formatter:off
NOT_RUN,
SUCCESS,
SKIPPED,
RUNNING,
FAILED
//@formatter:on
}
public class FailLocations {
private final Collection<FailLocation> locations;
public FailLocations(final Collection<OtpErlangObject> locs) {
locations = Lists.newArrayList();
for (final OtpErlangObject item : locs) {
locations.add(new FailLocation(item));
}
// first element points to ourselves, ignore it
locations.remove(locations.iterator().next());
}
public Collection<FailLocation> getLocations() {
return locations;
}
public boolean isEmpty() {
return locations.isEmpty();
}
}
public class FailLocation {
private final OtpErlangObject location;
public FailLocation(final OtpErlangObject location) {
this.location = location;
}
@Override
public String toString() {
return location.toString();
}
}
public class FailReason {
private final Collection<FailStackItem> items;
private final String reason;
public FailReason(final String reason, final Collection<OtpErlangObject> stack) {
this.reason = reason;
items = Lists.newArrayList();
for (final OtpErlangObject item : stack) {
items.add(new FailStackItem(item));
}
}
public Collection<FailStackItem> getStackItems() {
return items;
}
public String getReason() {
return reason;
}
public FailStackItem getFirstStackItem() {
if (items.isEmpty()) {
try {
return new FailStackItem(
OtpErlang.getTermParser().parse("{unknown,unknown,0}"));
} catch (final OtpParserException e) {
// ignored
}
}
return items.iterator().next();
}
}
public class FailStackItem {
private final OtpErlangObject item;
private String m;
private String f;
private OtpErlangObject a;
public FailStackItem(final OtpErlangObject item) {
this.item = item;
}
@Override
public String toString() {
try {
final OtpBindings b = OtpErlang.match("{M:a, F:a, A}", item);
m = b.getQuotedAtom("M");
f = b.getQuotedAtom("F");
a = b.get("A");
final String aa = a.toString();
final String args;
if (a instanceof OtpErlangLong) {
args = " / " + aa;
} else {
final String aas = aa.length() > 2 ? aa.substring(1, aa.length() - 2)
: "";
args = " ( " + aas + " )";
}
return m + " : " + f + args;
} catch (final Exception e) {
ErlLogger.warn(e);
}
return item.toString();
}
public String getModule() {
return m;
}
public String getFunction() {
return f;
}
}
private final String suite;
private final String testcase;
private TestState state;
private FailReason failReason;
private FailLocations failLocations;
private OtpErlangObject skipComment;
public TestCaseData(final String mod, final String fun) {
suite = mod;
testcase = fun;
state = TestState.NOT_RUN;
}
@Override
public String toString() {
return suite + ":" + testcase;
}
public void setRunning() {
state = TestState.RUNNING;
}
public void setSuccesful() {
state = TestState.SUCCESS;
}
public void setFailed(final OtpErlangObject reason,
final Collection<OtpErlangObject> locations) {
state = TestState.FAILED;
failReason = parseReason(reason);
failLocations = new FailLocations(locations);
}
static final List<OtpErlangObject> NO_STACK = new ArrayList<>();
private FailReason parseReason(final OtpErlangObject reason) {
OtpBindings b;
try {
b = OtpErlang.match("{Cause, Stack}", reason);
if (b == null) {
return new FailReason("internal error: " + reason.toString(), NO_STACK);
}
final Collection<OtpErlangObject> stack = b.getList("Stack");
return new FailReason(b.get("Cause").toString(), stack);
} catch (final OtpParserException e) {
ErlLogger.warn(e);
} catch (final OtpErlangException e) {
ErlLogger.warn(e);
}
return null;
}
public String getModule() {
return suite;
}
public String getFunction() {
return testcase;
}
public TestState getState() {
return state;
}
public FailLocations getFailLocations() {
return failLocations;
}
public FailReason getFailStack() {
return failReason;
}
public void setSkipped(final OtpErlangObject comment) {
state = TestState.SKIPPED;
skipComment = comment;
}
public OtpErlangObject getSkipComment() {
return skipComment;
}
}