Merge "Add failure indicators on the main dashboard."
diff --git a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/DashboardMainServlet.java b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/DashboardMainServlet.java
index 4d7b82c..f499c70 100644
--- a/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/DashboardMainServlet.java
+++ b/web/dashboard/appengine/servlet/src/main/java/com/android/vts/servlet/DashboardMainServlet.java
@@ -16,6 +16,8 @@
package com.android.vts.servlet;
+import com.android.vts.proto.VtsWebStatusMessage;
+import com.android.vts.proto.VtsWebStatusMessage.TestStatusMessage;
import com.android.vts.util.BigtableHelper;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
@@ -26,15 +28,17 @@
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
+import java.util.Map;
import java.util.logging.Level;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
@@ -50,6 +54,8 @@
private static final String DASHBOARD_ALL_LINK = "/?showAll=true";
private static final String DASHBOARD_FAVORITES_LINK = "/";
private static final byte[] EMAIL_FAMILY = Bytes.toBytes("email_to_test");
+ private static final byte[] STATUS_FAMILY = Bytes.toBytes("status");
+ private static final byte[] DATA_QUALIFIER = Bytes.toBytes("data");
private static final String STATUS_TABLE = "vts_status_table";
private static final String ALL_HEADER = "All Tests";
private static final String FAVORITES_HEADER = "Favorites";
@@ -69,6 +75,45 @@
return links;
}
+ /**
+ * Helper class for displaying test entries on the main dashboard.
+ */
+ public class TestDisplay implements Comparable<TestDisplay> {
+ private final String name;
+ private final int failCount;
+
+ /**
+ * Test display constructor.
+ * @param name The name of the test.
+ * @param failCount The number of tests failing.
+ */
+ public TestDisplay(String name, int failCount) {
+ this.name = name;
+ this.failCount = failCount;
+ }
+
+ /**
+ * Get the name of the test.
+ * @return The name of the test.
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Get the number of failing test cases.
+ * @return The number of failing test cases.
+ */
+ public int getFailCount() {
+ return this.failCount;
+ }
+
+ @Override
+ public int compareTo(TestDisplay test) {
+ return this.name.compareTo(test.name);
+ }
+ }
+
@Override
public void doGetHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException {
@@ -77,10 +122,11 @@
RequestDispatcher dispatcher = null;
Table table = BigtableHelper.getTable(TableName.valueOf(STATUS_TABLE));
- List<String> displayedTests = new ArrayList<>();
+ List<TestDisplay> displayedTests = new ArrayList<>();
HTableDescriptor[] tables = BigtableHelper.getTables();
- Set<String> allTables = new HashSet<>();
+ Map<String, Integer> failCountMap = new HashMap<>(); // map from table name to fail count
+
boolean showAll = request.getParameter("showAll") != null;
String header;
String buttonLabel;
@@ -91,13 +137,28 @@
for (HTableDescriptor descriptor : tables) {
String tableName = descriptor.getNameAsString();
if (tableName.startsWith(TABLE_PREFIX)) {
- allTables.add(tableName);
+ failCountMap.put(tableName, -1);
}
}
+ // Read the status table to determine the number of failed test cases in the latest run.
+ Scan scan = new Scan();
+ scan.addColumn(STATUS_FAMILY, DATA_QUALIFIER);
+ ResultScanner scanner = table.getScanner(scan);
+ for (Result result = scanner.next(); result != null; result = scanner.next()) {
+ String tableName = Bytes.toString(result.getRow());
+ byte[] value = result.getValue(STATUS_FAMILY, DATA_QUALIFIER);
+ TestStatusMessage testStatusMessage =
+ VtsWebStatusMessage.TestStatusMessage.parseFrom(value);
+ failCountMap.put(tableName, testStatusMessage.getFailedTestcasesList().size());
+ }
+
if (showAll) {
- for (String tableName : allTables) {
- displayedTests.add(tableName.substring(7));
+ for (String tableName : failCountMap.keySet()) {
+ TestDisplay test = new TestDisplay(
+ tableName.substring(TABLE_PREFIX.length()),
+ failCountMap.get(tableName));
+ displayedTests.add(test);
}
if (displayedTests.size() == 0) {
error = NO_TESTS_ERROR;
@@ -112,15 +173,17 @@
Get get = new Get(Bytes.toBytes(currentUser.getEmail()));
get.addFamily(EMAIL_FAMILY);
Result result = table.get(get);
- if (result != null) {
+ if (result != null && result.listCells() != null) {
List<Cell> cells = result.listCells();
- if (cells != null) {
- for (Cell cell : cells) {
- String test = Bytes.toString(cell.getQualifierArray());
- String val = Bytes.toString(cell.getValueArray());
- if (test != null && val.equals("1") && allTables.contains(test)) {
- displayedTests.add(test.substring(TABLE_PREFIX.length()));
- }
+ for (Cell cell : cells) {
+ String tableName = Bytes.toString(cell.getQualifierArray());
+ String val = Bytes.toString(cell.getValueArray());
+ if (tableName != null && val.equals("1") &&
+ failCountMap.containsKey(tableName)) {
+ TestDisplay test = new TestDisplay(
+ tableName.substring(TABLE_PREFIX.length()),
+ failCountMap.get(tableName));
+ displayedTests.add(test);
}
}
}
@@ -135,10 +198,8 @@
}
Collections.sort(displayedTests);
- String[] testArray = new String[displayedTests.size()];
- displayedTests.toArray(testArray);
response.setStatus(HttpServletResponse.SC_OK);
- request.setAttribute("testNames", testArray);
+ request.setAttribute("testNames", displayedTests);
request.setAttribute("headerLabel", header);
request.setAttribute("showAll", showAll);
request.setAttribute("buttonLabel", buttonLabel);
diff --git a/web/dashboard/appengine/servlet/src/main/webapp/WEB-INF/jsp/dashboard_main.jsp b/web/dashboard/appengine/servlet/src/main/webapp/WEB-INF/jsp/dashboard_main.jsp
index 52eddbe..35e59ba 100644
--- a/web/dashboard/appengine/servlet/src/main/webapp/WEB-INF/jsp/dashboard_main.jsp
+++ b/web/dashboard/appengine/servlet/src/main/webapp/WEB-INF/jsp/dashboard_main.jsp
@@ -36,9 +36,15 @@
<h4 id='section-header'>${headerLabel}</h4>
</div>
<c:forEach items='${testNames}' var='test'>
- <a href='${pageContext.request.contextPath}/show_table?testName=${test}'>
+ <a href='/show_table?testName=${test.getName()}'>
<div class='col s12 card hoverable option valign-wrapper waves-effect'>
- <span class='entry valign'>${test}</span>
+ <span class='entry valign'>${test.getName()}
+ <c:if test='${test.getFailCount() > 0}'>
+ <span class='indicator red center'>
+ ${test.getFailCount()}
+ </span>
+ </c:if>
+ </span>
</div>
</a>
</c:forEach>
diff --git a/web/dashboard/appengine/servlet/src/main/webapp/css/dashboard_main.css b/web/dashboard/appengine/servlet/src/main/webapp/css/dashboard_main.css
index aa18c5f..4849470 100644
--- a/web/dashboard/appengine/servlet/src/main/webapp/css/dashboard_main.css
+++ b/web/dashboard/appengine/servlet/src/main/webapp/css/dashboard_main.css
@@ -42,6 +42,19 @@
.entry {
font-size: 21px;
font-weight: 300;
+ position: relative;
+}
+
+.indicator {
+ color: white;
+ font-size: 12px;
+ font-weight: bold;
+ padding: 1px 6px;
+ position: absolute;
+ right: 0;
+ min-width: 40px;
+ border-radius: 10px;
+ margin-top: 6px;
}
#options {