blob: 4e88bcc3ed9f2abbf7e52286772f3af0f4022a68 [file] [log] [blame]
/*
* Copyright (c) 2017 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.vts.servlet;
import com.android.vts.entity.DeviceInfoEntity;
import com.android.vts.entity.TestPlanEntity;
import com.android.vts.entity.TestPlanRunEntity;
import com.android.vts.entity.TestRunEntity;
import com.android.vts.util.DatastoreHelper;
import com.android.vts.util.FilterUtil;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.SortDirection;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.Set;
import java.util.HashSet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
public class ShowPlanReleaseServlet extends BaseServlet {
private static final String PLAN_RELEASE_JSP = "WEB-INF/jsp/show_plan_release.jsp";
private static final int MAX_RUNS_PER_PAGE = 90;
@Override
public PageType getNavParentType() {
return PageType.RELEASE;
}
@Override
public List<Page> getBreadcrumbLinks(HttpServletRequest request) {
List<Page> links = new ArrayList<>();
String planName = request.getParameter("plan");
links.add(new Page(PageType.PLAN_RELEASE, planName.toUpperCase(), "?plan=" + planName));
return links;
}
/**
* Model to describe each test plan run .
*/
private class TestPlanRunMetadata implements Comparable<TestPlanRunMetadata> {
public final TestPlanRunEntity testPlanRun;
public final List<String> devices;
public final Set<DeviceInfoEntity> deviceSet;
public TestPlanRunMetadata(TestPlanRunEntity testPlanRun) {
this.testPlanRun = testPlanRun;
this.devices = new ArrayList<>();
this.deviceSet = new HashSet<>();
}
public void addDevice(DeviceInfoEntity device) {
if (device == null || deviceSet.contains(device))
return;
devices.add(device.branch + "/" + device.buildFlavor + " (" + device.buildId + ")");
deviceSet.add(device);
}
public JsonObject toJson() {
JsonObject obj = new JsonObject();
obj.add("testPlanRun", testPlanRun.toJson());
obj.add("deviceInfo", new JsonPrimitive(StringUtils.join(devices, ", ")));
return obj;
}
@Override
public int compareTo(TestPlanRunMetadata o) {
return new Long(o.testPlanRun.startTimestamp)
.compareTo(this.testPlanRun.startTimestamp);
}
}
@Override
public void doGetHandler(HttpServletRequest request, HttpServletResponse response)
throws IOException {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Long startTime = null; // time in microseconds
Long endTime = null; // time in microseconds
if (request.getParameter("startTime") != null) {
String time = request.getParameter("startTime");
try {
startTime = Long.parseLong(time);
startTime = startTime > 0 ? startTime : null;
} catch (NumberFormatException e) {
startTime = null;
}
}
if (request.getParameter("endTime") != null) {
String time = request.getParameter("endTime");
try {
endTime = Long.parseLong(time);
endTime = endTime > 0 ? endTime : null;
} catch (NumberFormatException e) {
endTime = null;
}
}
SortDirection dir = SortDirection.DESCENDING;
if (startTime != null && endTime == null) {
dir = SortDirection.ASCENDING;
}
boolean unfiltered = request.getParameter("unfiltered") != null;
boolean showPresubmit = request.getParameter("showPresubmit") != null;
boolean showPostsubmit = request.getParameter("showPostsubmit") != null;
// If no params are specified, set to default of postsubmit-only.
if (!(showPresubmit || showPostsubmit)) {
showPostsubmit = true;
}
// If unfiltered, set showPre- and Post-submit to true for accurate UI.
if (unfiltered) {
showPostsubmit = true;
showPresubmit = true;
}
Filter typeFilter = FilterUtil.getTestTypeFilter(showPresubmit, showPostsubmit, unfiltered);
String testPlan = request.getParameter("plan");
Key testPlanKey = KeyFactory.createKey(TestPlanEntity.KIND, testPlan);
Filter testPlanRunFilter = FilterUtil.getTimeFilter(
testPlanKey, TestPlanRunEntity.KIND, startTime, endTime, typeFilter);
Map<String, Object> parameterMap = request.getParameterMap();
Filter userDeviceFilter = FilterUtil.getUserDeviceFilter(parameterMap);
List<TestPlanRunMetadata> testPlanRuns = new ArrayList<>();
if (userDeviceFilter == null) {
Query testPlanRunQuery = new Query(TestPlanRunEntity.KIND)
.setAncestor(testPlanKey)
.setFilter(testPlanRunFilter)
.addSort(Entity.KEY_RESERVED_PROPERTY, dir);
for (Entity testPlanRunEntity :
datastore.prepare(testPlanRunQuery)
.asIterable(FetchOptions.Builder.withLimit(MAX_RUNS_PER_PAGE))) {
TestPlanRunEntity testPlanRun = TestPlanRunEntity.fromEntity(testPlanRunEntity);
if (testPlanRun == null) {
logger.log(
Level.WARNING, "Invalid test plan run: " + testPlanRunEntity.getKey());
continue;
}
TestPlanRunMetadata metadata = new TestPlanRunMetadata(testPlanRun);
testPlanRuns.add(metadata);
Query deviceInfoQuery =
new Query(DeviceInfoEntity.KIND).setAncestor(testPlanRun.key);
for (Entity deviceInfoEntity : datastore.prepare(deviceInfoQuery).asIterable()) {
DeviceInfoEntity deviceInfo = DeviceInfoEntity.fromEntity(deviceInfoEntity);
metadata.addDevice(deviceInfo);
}
}
} else {
List<Key> gets = FilterUtil.getMatchingKeys(testPlanKey, TestPlanRunEntity.KIND,
testPlanRunFilter, userDeviceFilter, dir, MAX_RUNS_PER_PAGE);
Map<Key, Entity> entityMap = datastore.get(gets);
for (Key key : gets) {
if (!entityMap.containsKey(key)) {
continue;
}
TestPlanRunEntity testPlanRun = TestPlanRunEntity.fromEntity(entityMap.get(key));
if (testPlanRun == null) {
continue;
}
TestPlanRunMetadata metadata = new TestPlanRunMetadata(testPlanRun);
testPlanRuns.add(metadata);
Query deviceInfoQuery =
new Query(DeviceInfoEntity.KIND).setAncestor(testPlanRun.key);
for (Entity deviceInfoEntity : datastore.prepare(deviceInfoQuery).asIterable()) {
DeviceInfoEntity deviceInfo = DeviceInfoEntity.fromEntity(deviceInfoEntity);
metadata.addDevice(deviceInfo);
}
}
}
Collections.sort(testPlanRuns);
if (testPlanRuns.size() > 0) {
TestPlanRunMetadata firstRun = testPlanRuns.get(0);
endTime = firstRun.testPlanRun.startTimestamp;
TestPlanRunMetadata lastRun = testPlanRuns.get(testPlanRuns.size() - 1);
startTime = lastRun.testPlanRun.startTimestamp;
}
List<JsonObject> testPlanRunObjects = new ArrayList<>();
for (TestPlanRunMetadata metadata : testPlanRuns) {
testPlanRunObjects.add(metadata.toJson());
}
FilterUtil.setAttributes(request, parameterMap);
request.setAttribute("plan", request.getParameter("plan"));
request.setAttribute("hasNewer", new Gson().toJson(DatastoreHelper.hasNewer(
testPlanKey, TestPlanRunEntity.KIND, endTime)));
request.setAttribute("hasOlder", new Gson().toJson(DatastoreHelper.hasOlder(
testPlanKey, TestPlanRunEntity.KIND, startTime)));
request.setAttribute("planRuns", new Gson().toJson(testPlanRunObjects));
request.setAttribute("unfiltered", unfiltered);
request.setAttribute("showPresubmit", showPresubmit);
request.setAttribute("showPostsubmit", showPostsubmit);
request.setAttribute("startTime", new Gson().toJson(startTime));
request.setAttribute("endTime", new Gson().toJson(endTime));
request.setAttribute("branches", new Gson().toJson(DatastoreHelper.getAllBranches()));
request.setAttribute("devices", new Gson().toJson(DatastoreHelper.getAllBuildFlavors()));
response.setStatus(HttpServletResponse.SC_OK);
RequestDispatcher dispatcher = request.getRequestDispatcher(PLAN_RELEASE_JSP);
try {
dispatcher.forward(request, response);
} catch (ServletException e) {
logger.log(Level.SEVERE, "Servlet Excpetion caught : ", e);
}
}
}