• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package autotest.tko;
2 
3 import autotest.common.JsonRpcCallback;
4 import autotest.common.JsonRpcProxy;
5 import autotest.common.PaddedJsonRpcProxy;
6 import autotest.common.Utils;
7 import autotest.common.ui.DetailView;
8 import autotest.common.ui.NotifyManager;
9 import autotest.common.ui.RealHyperlink;
10 
11 import com.google.gwt.event.logical.shared.OpenEvent;
12 import com.google.gwt.event.logical.shared.OpenHandler;
13 import com.google.gwt.event.logical.shared.ResizeEvent;
14 import com.google.gwt.event.logical.shared.ResizeHandler;
15 import com.google.gwt.json.client.JSONNumber;
16 import com.google.gwt.json.client.JSONObject;
17 import com.google.gwt.json.client.JSONString;
18 import com.google.gwt.json.client.JSONValue;
19 import com.google.gwt.user.client.Window;
20 import com.google.gwt.user.client.ui.Composite;
21 import com.google.gwt.user.client.ui.DisclosurePanel;
22 import com.google.gwt.user.client.ui.FlexTable;
23 import com.google.gwt.user.client.ui.FlowPanel;
24 import com.google.gwt.user.client.ui.HTML;
25 import com.google.gwt.user.client.ui.Panel;
26 import com.google.gwt.user.client.ui.ScrollPanel;
27 import com.google.gwt.user.client.ui.SimplePanel;
28 
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.List;
33 
34 class TestDetailView extends DetailView {
35     private static final int NO_TEST_ID = -1;
36 
37     private static final JsonRpcProxy logLoadingProxy =
38         new PaddedJsonRpcProxy(Utils.RETRIEVE_LOGS_URL);
39 
40     private int testId = NO_TEST_ID;
41     private String jobTag;
42     private List<LogFileViewer> logFileViewers = new ArrayList<LogFileViewer>();
43     private RealHyperlink logLink = new RealHyperlink("(view all logs)");
44     private RealHyperlink testLogLink = new RealHyperlink("(view test logs)");
45     private Panel logPanel;
46     private Panel attributePanel = new SimplePanel();
47 
48     private class LogFileViewer extends Composite
49                                 implements OpenHandler<DisclosurePanel>, ResizeHandler {
50         private DisclosurePanel panel;
51         private ScrollPanel scroller; // ScrollPanel wrapping log contents
52         private String logFilePath;
53 
54         private JsonRpcCallback rpcCallback = new JsonRpcCallback() {
55             @Override
56             public void onError(JSONObject errorObject) {
57                 super.onError(errorObject);
58                 String errorString = getErrorString(errorObject);
59                 if (errorString.equals("")) {
60                     errorString = "Failed to load log "+ logFilePath;
61                 }
62                 setStatusText(errorString);
63             }
64 
65             @Override
66             public void onSuccess(JSONValue result) {
67                 handle(result);
68             }
69         };
70 
LogFileViewer(String logFilePath, String logFileName)71         public LogFileViewer(String logFilePath, String logFileName) {
72             this.logFilePath = logFilePath;
73             panel = new DisclosurePanel(logFileName);
74             panel.addOpenHandler(this);
75             panel.addStyleName("log-file-panel");
76             initWidget(panel);
77 
78             Window.addResizeHandler(this);
79         }
80 
81         @Override
onOpen(OpenEvent<DisclosurePanel> event)82         public void onOpen(OpenEvent<DisclosurePanel> event) {
83             JSONObject params = new JSONObject();
84             params.put("path", new JSONString(getLogUrl()));
85             logLoadingProxy.rpcCall("dummy", params, rpcCallback);
86 
87             setStatusText("Loading...");
88         }
89 
getLogUrl()90         private String getLogUrl() {
91             return Utils.getLogsUrl(jobTag + "/" + logFilePath);
92         }
93 
handle(JSONValue value)94         public void handle(JSONValue value) {
95             String logContents = value.isString().stringValue();
96             if (logContents.equals("")) {
97                 setStatusText("Log file is empty");
98             } else {
99                 setLogText(logContents);
100             }
101         }
102 
setLogText(String text)103         private void setLogText(String text) {
104             panel.clear();
105             scroller = new ScrollPanel();
106             scroller.getElement().setInnerText(text);
107             panel.add(scroller);
108             setScrollerWidth();
109         }
110 
111         /**
112          * Firefox fails to set relative widths correctly for elements with overflow: scroll (or
113          * auto, or hidden).  Instead, it just expands the element to fit the contents.  So we use
114          * this trick to dynamically implement width: 100%.
115          */
setScrollerWidth()116         private void setScrollerWidth() {
117             assert panel.isOpen();
118             scroller.setWidth("0px"); // allow the parent to assume its natural size
119             int targetWidthPx = scroller.getParent().getOffsetWidth();
120             NotifyManager.getInstance().log(targetWidthPx + "px");
121             scroller.setWidth(targetWidthPx + "px");
122         }
123 
124         @Override
onResize(ResizeEvent event)125         public void onResize(ResizeEvent event) {
126             if (panel.isOpen()) {
127                 setScrollerWidth();
128             }
129         }
130 
setStatusText(String status)131         private void setStatusText(String status) {
132             panel.clear();
133             panel.add(new HTML("<i>" + status + "</i>"));
134         }
135     }
136 
137     private static class AttributeTable extends Composite {
138         private DisclosurePanel container = new DisclosurePanel("Test attributes");
139         private FlexTable table = new FlexTable();
140 
AttributeTable(JSONObject attributes)141         public AttributeTable(JSONObject attributes) {
142             processAttributes(attributes);
143             setupTableStyle();
144             container.add(table);
145             initWidget(container);
146         }
147 
processAttributes(JSONObject attributes)148         private void processAttributes(JSONObject attributes) {
149             if (attributes.size() == 0) {
150                 table.setText(0, 0, "No test attributes");
151                 return;
152             }
153 
154             List<String> sortedKeys = new ArrayList<String>(attributes.keySet());
155             Collections.sort(sortedKeys);
156             for (String key : sortedKeys) {
157                 String value = Utils.jsonToString(attributes.get(key));
158                 int row = table.getRowCount();
159                 table.setText(row, 0, key);
160                 table.setText(row, 1, value);
161             }
162         }
163 
setupTableStyle()164         private void setupTableStyle() {
165             container.addStyleName("test-attributes");
166         }
167     }
168 
169     @Override
initialize()170     public void initialize() {
171         super.initialize();
172 
173         addWidget(attributePanel, "td_attributes");
174         logPanel = new FlowPanel();
175         addWidget(logPanel, "td_log_files");
176         testLogLink.setOpensNewWindow(true);
177         addWidget(testLogLink, "td_view_logs_link");
178         logLink.setOpensNewWindow(true);
179         addWidget(logLink, "td_view_logs_link");
180     }
181 
addLogViewers(String testName)182     private void addLogViewers(String testName) {
183         logPanel.clear();
184         addLogFileViewer(testName + "/debug/" + testName + ".DEBUG", "Test debug log");
185         addLogFileViewer(testName + "/debug/" + testName + ".ERROR", "Test error log");
186         addLogFileViewer("status.log", "Job status log");
187         addLogFileViewer("debug/autoserv.DEBUG", "Job debug log");
188         addLogFileViewer("debug/autoserv.ERROR", "Job error log");
189     }
190 
addLogFileViewer(String logPath, String logName)191     private void addLogFileViewer(String logPath, String logName) {
192         LogFileViewer viewer = new LogFileViewer(logPath, logName);
193         logFileViewers.add(viewer);
194         logPanel.add(viewer);
195     }
196 
197     @Override
fetchData()198     protected void fetchData() {
199         JSONObject params = new JSONObject();
200         params.put("test_idx", new JSONNumber(testId));
201         rpcProxy.rpcCall("get_detailed_test_views", params, new JsonRpcCallback() {
202             @Override
203             public void onSuccess(JSONValue result) {
204                 JSONObject test;
205                 try {
206                     test = Utils.getSingleObjectFromArray(result.isArray());
207                 }
208                 catch (IllegalArgumentException exc) {
209                     NotifyManager.getInstance().showError("No such job found");
210                     resetPage();
211                     return;
212                 }
213 
214                 showTest(test);
215             }
216 
217             @Override
218             public void onError(JSONObject errorObject) {
219                 super.onError(errorObject);
220                 resetPage();
221             }
222         });
223     }
224 
225     @Override
setObjectId(String id)226     protected void setObjectId(String id) {
227         try {
228             testId = Integer.parseInt(id);
229         }
230         catch (NumberFormatException exc) {
231             throw new IllegalArgumentException();
232         }
233     }
234 
235     @Override
getObjectId()236     protected String getObjectId() {
237         if (testId == NO_TEST_ID) {
238             return NO_OBJECT;
239         }
240         return Integer.toString(testId);
241     }
242 
243     @Override
getDataElementId()244     protected String getDataElementId() {
245         return "td_data";
246     }
247 
248     @Override
getFetchControlsElementId()249     protected String getFetchControlsElementId() {
250         return "td_fetch_controls";
251     }
252 
253     @Override
getNoObjectText()254     protected String getNoObjectText() {
255         return "No test selected";
256     }
257 
258     @Override
getTitleElementId()259     protected String getTitleElementId() {
260         return "td_title";
261     }
262 
263     @Override
getElementId()264     public String getElementId() {
265         return "test_detail_view";
266     }
267 
268     @Override
display()269     public void display() {
270         super.display();
271         CommonPanel.getPanel().setConditionVisible(false);
272     }
273 
showTest(JSONObject test)274     protected void showTest(JSONObject test) {
275         String testName = test.get("test_name").isString().stringValue();
276         jobTag = test.get("job_tag").isString().stringValue();
277 
278         showText(testName, "td_test");
279         showText(jobTag, "td_job_tag");
280         showField(test, "job_name", "td_job_name");
281         showField(test, "status", "td_status");
282         showField(test, "reason", "td_reason");
283         showField(test, "test_started_time", "td_test_started");
284         showField(test, "test_finished_time", "td_test_finished");
285         showField(test, "hostname", "td_hostname");
286         showField(test, "platform", "td_platform");
287         showField(test, "kernel", "td_kernel");
288 
289         String[] labels = Utils.JSONtoStrings(test.get("labels").isArray());
290         String labelList = Utils.joinStrings(", ", Arrays.asList(labels));
291         if (labelList.equals("")) {
292             labelList = "none";
293         }
294         showText(labelList, "td_test_labels");
295 
296         JSONObject attributes = test.get("attributes").isObject();
297         attributePanel.clear();
298         attributePanel.add(new AttributeTable(attributes));
299 
300         logLink.setHref(Utils.getRetrieveLogsUrl(jobTag));
301         testLogLink.setHref(Utils.getRetrieveLogsUrl(jobTag) + "/" + testName);
302         addLogViewers(testName);
303 
304         displayObjectData("Test " + testName + " (job " + jobTag + ")");
305     }
306     @Override
resetPage()307     public void resetPage() {
308         super.resetPage();
309     }
310 }
311