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