blob: 0a700f66c0392aa168428f57b00d2ea26fafbe27 [file] [log] [blame]
package autotest.tko;
import autotest.common.JsonRpcCallback;
import autotest.common.JsonRpcProxy;
import autotest.common.PaddedJsonRpcProxy;
import autotest.common.Utils;
import autotest.common.ui.DetailView;
import autotest.common.ui.NotifyManager;
import autotest.common.ui.RealHyperlink;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
class TestDetailView extends DetailView {
private static final int NO_TEST_ID = -1;
private static final JsonRpcProxy logLoadingProxy =
new PaddedJsonRpcProxy(Utils.RETRIEVE_LOGS_URL);
private int testId = NO_TEST_ID;
private String jobTag;
private List<LogFileViewer> logFileViewers = new ArrayList<LogFileViewer>();
private RealHyperlink logLink = new RealHyperlink("(view all logs)");
private RealHyperlink testLogLink = new RealHyperlink("(view test logs)");
private Panel logPanel;
private Panel attributePanel = new SimplePanel();
private class LogFileViewer extends Composite
implements OpenHandler<DisclosurePanel>, ResizeHandler {
private DisclosurePanel panel;
private ScrollPanel scroller; // ScrollPanel wrapping log contents
private String logFilePath;
private JsonRpcCallback rpcCallback = new JsonRpcCallback() {
@Override
public void onError(JSONObject errorObject) {
super.onError(errorObject);
String errorString = getErrorString(errorObject);
if (errorString.equals("")) {
errorString = "Failed to load log "+ logFilePath;
}
setStatusText(errorString);
}
@Override
public void onSuccess(JSONValue result) {
handle(result);
}
};
public LogFileViewer(String logFilePath, String logFileName) {
this.logFilePath = logFilePath;
panel = new DisclosurePanel(logFileName);
panel.addOpenHandler(this);
panel.addStyleName("log-file-panel");
initWidget(panel);
Window.addResizeHandler(this);
}
@Override
public void onOpen(OpenEvent<DisclosurePanel> event) {
JSONObject params = new JSONObject();
params.put("path", new JSONString(getLogUrl()));
logLoadingProxy.rpcCall("dummy", params, rpcCallback);
setStatusText("Loading...");
}
private String getLogUrl() {
return Utils.getLogsUrl(jobTag + "/" + logFilePath);
}
public void handle(JSONValue value) {
String logContents = value.isString().stringValue();
if (logContents.equals("")) {
setStatusText("Log file is empty");
} else {
setLogText(logContents);
}
}
private void setLogText(String text) {
panel.clear();
scroller = new ScrollPanel();
scroller.getElement().setInnerText(text);
panel.add(scroller);
setScrollerWidth();
}
/**
* Firefox fails to set relative widths correctly for elements with overflow: scroll (or
* auto, or hidden). Instead, it just expands the element to fit the contents. So we use
* this trick to dynamically implement width: 100%.
*/
private void setScrollerWidth() {
assert panel.isOpen();
scroller.setWidth("0px"); // allow the parent to assume its natural size
int targetWidthPx = scroller.getParent().getOffsetWidth();
NotifyManager.getInstance().log(targetWidthPx + "px");
scroller.setWidth(targetWidthPx + "px");
}
@Override
public void onResize(ResizeEvent event) {
if (panel.isOpen()) {
setScrollerWidth();
}
}
private void setStatusText(String status) {
panel.clear();
panel.add(new HTML("<i>" + status + "</i>"));
}
}
private static class AttributeTable extends Composite {
private DisclosurePanel container = new DisclosurePanel("Test attributes");
private FlexTable table = new FlexTable();
public AttributeTable(JSONObject attributes) {
processAttributes(attributes);
setupTableStyle();
container.add(table);
initWidget(container);
}
private void processAttributes(JSONObject attributes) {
if (attributes.size() == 0) {
table.setText(0, 0, "No test attributes");
return;
}
List<String> sortedKeys = new ArrayList<String>(attributes.keySet());
Collections.sort(sortedKeys);
for (String key : sortedKeys) {
String value = Utils.jsonToString(attributes.get(key));
int row = table.getRowCount();
table.setText(row, 0, key);
table.setText(row, 1, value);
}
}
private void setupTableStyle() {
container.addStyleName("test-attributes");
}
}
@Override
public void initialize() {
super.initialize();
addWidget(attributePanel, "td_attributes");
logPanel = new FlowPanel();
addWidget(logPanel, "td_log_files");
testLogLink.setOpensNewWindow(true);
addWidget(testLogLink, "td_view_logs_link");
logLink.setOpensNewWindow(true);
addWidget(logLink, "td_view_logs_link");
}
private void addLogViewers(String testName) {
logPanel.clear();
addLogFileViewer(testName + "/debug/" + testName + ".DEBUG", "Test debug log");
addLogFileViewer(testName + "/debug/" + testName + ".ERROR", "Test error log");
addLogFileViewer("status.log", "Job status log");
addLogFileViewer("debug/autoserv.DEBUG", "Job debug log");
addLogFileViewer("debug/autoserv.ERROR", "Job error log");
}
private void addLogFileViewer(String logPath, String logName) {
LogFileViewer viewer = new LogFileViewer(logPath, logName);
logFileViewers.add(viewer);
logPanel.add(viewer);
}
@Override
protected void fetchData() {
JSONObject params = new JSONObject();
params.put("test_idx", new JSONNumber(testId));
rpcProxy.rpcCall("get_detailed_test_views", params, new JsonRpcCallback() {
@Override
public void onSuccess(JSONValue result) {
JSONObject test;
try {
test = Utils.getSingleObjectFromArray(result.isArray());
}
catch (IllegalArgumentException exc) {
NotifyManager.getInstance().showError("No such job found");
resetPage();
return;
}
showTest(test);
}
@Override
public void onError(JSONObject errorObject) {
super.onError(errorObject);
resetPage();
}
});
}
@Override
protected void setObjectId(String id) {
try {
testId = Integer.parseInt(id);
}
catch (NumberFormatException exc) {
throw new IllegalArgumentException();
}
}
@Override
protected String getObjectId() {
if (testId == NO_TEST_ID) {
return NO_OBJECT;
}
return Integer.toString(testId);
}
@Override
protected String getDataElementId() {
return "td_data";
}
@Override
protected String getFetchControlsElementId() {
return "td_fetch_controls";
}
@Override
protected String getNoObjectText() {
return "No test selected";
}
@Override
protected String getTitleElementId() {
return "td_title";
}
@Override
public String getElementId() {
return "test_detail_view";
}
@Override
public void display() {
super.display();
CommonPanel.getPanel().setConditionVisible(false);
}
protected void showTest(JSONObject test) {
String testName = test.get("test_name").isString().stringValue();
jobTag = test.get("job_tag").isString().stringValue();
showText(testName, "td_test");
showText(jobTag, "td_job_tag");
showField(test, "job_name", "td_job_name");
showField(test, "status", "td_status");
showField(test, "reason", "td_reason");
showField(test, "test_started_time", "td_test_started");
showField(test, "test_finished_time", "td_test_finished");
showField(test, "hostname", "td_hostname");
showField(test, "platform", "td_platform");
showField(test, "kernel", "td_kernel");
String[] labels = Utils.JSONtoStrings(test.get("labels").isArray());
String labelList = Utils.joinStrings(", ", Arrays.asList(labels));
if (labelList.equals("")) {
labelList = "none";
}
showText(labelList, "td_test_labels");
JSONObject attributes = test.get("attributes").isObject();
attributePanel.clear();
attributePanel.add(new AttributeTable(attributes));
logLink.setHref(Utils.getRetrieveLogsUrl(jobTag));
testLogLink.setHref(Utils.getRetrieveLogsUrl(jobTag) + "/" + testName);
addLogViewers(testName);
displayObjectData("Test " + testName + " (job " + jobTag + ")");
}
@Override
public void resetPage() {
super.resetPage();
}
}