1 /* 2 * Copyright (c) 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you 5 * may not use this file except in compliance with the License. You may 6 * obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 * implied. See the License for the specific language governing 14 * permissions and limitations under the License. 15 */ 16 17 package com.android.vts.servlet; 18 19 import com.android.vts.entity.CodeCoverageEntity; 20 import com.android.vts.entity.TestCaseRunEntity; 21 import com.android.vts.entity.TestEntity; 22 import com.android.vts.entity.TestRunEntity; 23 import com.android.vts.proto.VtsReportMessage.TestCaseResult; 24 import com.android.vts.util.DatastoreHelper; 25 import com.android.vts.util.FilterUtil; 26 import com.android.vts.util.TestResults; 27 import com.google.appengine.api.datastore.DatastoreService; 28 import com.google.appengine.api.datastore.DatastoreServiceFactory; 29 import com.google.appengine.api.datastore.Entity; 30 import com.google.appengine.api.datastore.Key; 31 import com.google.appengine.api.datastore.KeyFactory; 32 import com.google.appengine.api.datastore.Query.Filter; 33 import com.google.appengine.api.datastore.Query.SortDirection; 34 import com.google.gson.Gson; 35 import java.io.IOException; 36 import java.util.ArrayList; 37 import java.util.List; 38 import java.util.Map; 39 import java.util.logging.Level; 40 import javax.servlet.RequestDispatcher; 41 import javax.servlet.ServletException; 42 import javax.servlet.http.HttpServletRequest; 43 import javax.servlet.http.HttpServletResponse; 44 45 /** Servlet for handling requests to load individual tables. */ 46 public class ShowTableServlet extends BaseServlet { 47 private static final String TABLE_JSP = "WEB-INF/jsp/show_table.jsp"; 48 // Error message displayed on the webpage is tableName passed is null. 49 private static final String TABLE_NAME_ERROR = "Error : Table name must be passed!"; 50 private static final String PROFILING_DATA_ALERT = "No profiling data was found."; 51 private static final int MAX_BUILD_IDS_PER_PAGE = 10; 52 53 @Override getNavParentType()54 public PageType getNavParentType() { 55 return PageType.TOT; 56 } 57 58 @Override getBreadcrumbLinks(HttpServletRequest request)59 public List<Page> getBreadcrumbLinks(HttpServletRequest request) { 60 List<Page> links = new ArrayList<>(); 61 String testName = request.getParameter("testName"); 62 links.add(new Page(PageType.TABLE, testName, "?testName=" + testName)); 63 return links; 64 } 65 processTestRun(TestResults testResults, Entity testRun)66 public static void processTestRun(TestResults testResults, Entity testRun) { 67 TestRunEntity testRunEntity = TestRunEntity.fromEntity(testRun); 68 if (testRunEntity == null) { 69 return; 70 } 71 72 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 73 List<Key> gets = new ArrayList<>(); 74 for (long testCaseId : testRunEntity.getTestCaseIds()) { 75 gets.add(KeyFactory.createKey(TestCaseRunEntity.KIND, testCaseId)); 76 } 77 78 List<Entity> testCases = new ArrayList<>(); 79 Map<Key, Entity> entityMap = datastore.get(gets); 80 for (Key key : gets) { 81 if (entityMap.containsKey(key)) { 82 testCases.add(entityMap.get(key)); 83 } 84 } 85 86 testResults.addTestRun(testRun, testCases); 87 } 88 89 @Override doGetHandler(HttpServletRequest request, HttpServletResponse response)90 public void doGetHandler(HttpServletRequest request, HttpServletResponse response) 91 throws IOException { 92 boolean unfiltered = request.getParameter("unfiltered") != null; 93 boolean showPresubmit = request.getParameter("showPresubmit") != null; 94 boolean showPostsubmit = request.getParameter("showPostsubmit") != null; 95 96 Long startTime = null; // time in microseconds 97 Long endTime = null; // time in microseconds 98 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService(); 99 RequestDispatcher dispatcher = null; 100 101 // message to display if profiling point data is not available 102 String profilingDataAlert = ""; 103 104 if (request.getParameter("testName") == null) { 105 request.setAttribute("testName", TABLE_NAME_ERROR); 106 return; 107 } 108 String testName = request.getParameter("testName"); 109 110 if (request.getParameter("startTime") != null) { 111 String time = request.getParameter("startTime"); 112 try { 113 startTime = Long.parseLong(time); 114 startTime = startTime > 0 ? startTime : null; 115 } catch (NumberFormatException e) { 116 startTime = null; 117 } 118 } 119 if (request.getParameter("endTime") != null) { 120 String time = request.getParameter("endTime"); 121 try { 122 endTime = Long.parseLong(time); 123 endTime = endTime > 0 ? endTime : null; 124 } catch (NumberFormatException e) { 125 endTime = null; 126 } 127 } 128 129 // If no params are specified, set to default of postsubmit-only. 130 if (!(showPresubmit || showPostsubmit)) { 131 showPostsubmit = true; 132 } 133 134 // If unfiltered, set showPre- and Post-submit to true for accurate UI. 135 if (unfiltered) { 136 showPostsubmit = true; 137 showPresubmit = true; 138 } 139 140 // Add result names to list 141 List<String> resultNames = new ArrayList<>(); 142 for (TestCaseResult r : TestCaseResult.values()) { 143 resultNames.add(r.name()); 144 } 145 146 TestResults testResults = new TestResults(testName); 147 148 SortDirection dir = SortDirection.DESCENDING; 149 if (startTime != null && endTime == null) { 150 dir = SortDirection.ASCENDING; 151 } 152 Key testKey = KeyFactory.createKey(TestEntity.KIND, testName); 153 154 Filter typeFilter = FilterUtil.getTestTypeFilter(showPresubmit, showPostsubmit, unfiltered); 155 Filter testFilter = 156 FilterUtil.getTimeFilter( 157 testKey, TestRunEntity.KIND, startTime, endTime, typeFilter); 158 159 Map<String, String[]> parameterMap = request.getParameterMap(); 160 List<Filter> userTestFilters = FilterUtil.getUserTestFilters(parameterMap); 161 userTestFilters.add(0, testFilter); 162 Filter userDeviceFilter = FilterUtil.getUserDeviceFilter(parameterMap); 163 164 List<Key> gets = 165 FilterUtil.getMatchingKeys( 166 testKey, 167 TestRunEntity.KIND, 168 userTestFilters, 169 userDeviceFilter, 170 dir, 171 MAX_BUILD_IDS_PER_PAGE); 172 Map<Key, Entity> entityMap = datastore.get(gets); 173 for (Key key : gets) { 174 if (!entityMap.containsKey(key)) { 175 continue; 176 } 177 processTestRun(testResults, entityMap.get(key)); 178 } 179 testResults.processReport(); 180 181 if (testResults.profilingPointNames.length == 0) { 182 profilingDataAlert = PROFILING_DATA_ALERT; 183 } 184 185 FilterUtil.setAttributes(request, parameterMap); 186 187 request.setAttribute("testName", request.getParameter("testName")); 188 189 request.setAttribute("error", profilingDataAlert); 190 191 // pass values by converting to JSON 192 request.setAttribute("headerRow", new Gson().toJson(testResults.headerRow)); 193 request.setAttribute("timeGrid", new Gson().toJson(testResults.timeGrid)); 194 request.setAttribute("durationGrid", new Gson().toJson(testResults.durationGrid)); 195 request.setAttribute("summaryGrid", new Gson().toJson(testResults.summaryGrid)); 196 request.setAttribute("resultsGrid", new Gson().toJson(testResults.resultsGrid)); 197 request.setAttribute("profilingPointNames", testResults.profilingPointNames); 198 request.setAttribute("resultNames", resultNames); 199 request.setAttribute("resultNamesJson", new Gson().toJson(resultNames)); 200 request.setAttribute("logInfoMap", new Gson().toJson(testResults.logInfoMap)); 201 202 // data for pie chart 203 request.setAttribute( 204 "topBuildResultCounts", new Gson().toJson(testResults.totResultCounts)); 205 request.setAttribute("topBuildId", testResults.totBuildId); 206 request.setAttribute("startTime", new Gson().toJson(testResults.startTime)); 207 request.setAttribute("endTime", new Gson().toJson(testResults.endTime)); 208 request.setAttribute( 209 "hasNewer", 210 new Gson() 211 .toJson( 212 DatastoreHelper.hasNewer( 213 testKey, TestRunEntity.KIND, testResults.endTime))); 214 request.setAttribute( 215 "hasOlder", 216 new Gson() 217 .toJson( 218 DatastoreHelper.hasOlder( 219 testKey, TestRunEntity.KIND, testResults.startTime))); 220 request.setAttribute("unfiltered", unfiltered); 221 request.setAttribute("showPresubmit", showPresubmit); 222 request.setAttribute("showPostsubmit", showPostsubmit); 223 224 request.setAttribute("branches", new Gson().toJson(DatastoreHelper.getAllBranches())); 225 request.setAttribute("devices", new Gson().toJson(DatastoreHelper.getAllBuildFlavors())); 226 227 dispatcher = request.getRequestDispatcher(TABLE_JSP); 228 try { 229 dispatcher.forward(request, response); 230 } catch (ServletException e) { 231 logger.log(Level.SEVERE, "Servlet Exception caught : " + e.toString()); 232 } 233 } 234 } 235