summaryrefslogtreecommitdiff
path: root/src/main/java/com/android/vts/job/VtsCoverageAlertJobServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/android/vts/job/VtsCoverageAlertJobServlet.java')
-rw-r--r--src/main/java/com/android/vts/job/VtsCoverageAlertJobServlet.java328
1 files changed, 0 insertions, 328 deletions
diff --git a/src/main/java/com/android/vts/job/VtsCoverageAlertJobServlet.java b/src/main/java/com/android/vts/job/VtsCoverageAlertJobServlet.java
deleted file mode 100644
index b5453b7..0000000
--- a/src/main/java/com/android/vts/job/VtsCoverageAlertJobServlet.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * 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.job;
-
-import static com.googlecode.objectify.ObjectifyService.ofy;
-
-import com.android.vts.entity.CodeCoverageEntity;
-import com.android.vts.entity.DeviceInfoEntity;
-import com.android.vts.entity.TestCoverageStatusEntity;
-import com.android.vts.entity.TestRunEntity;
-import com.android.vts.util.EmailHelper;
-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.EntityNotFoundException;
-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.taskqueue.Queue;
-import com.google.appengine.api.taskqueue.QueueFactory;
-import com.google.appengine.api.taskqueue.TaskOptions;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * Coverage notification job.
- */
-public class VtsCoverageAlertJobServlet extends BaseJobServlet {
-
- private static final String COVERAGE_ALERT_URL = "/task/vts_coverage_job";
- protected static final Logger logger =
- Logger.getLogger(VtsCoverageAlertJobServlet.class.getName());
- protected static final double CHANGE_ALERT_THRESHOLD = 0.05;
- protected static final double GOOD_THRESHOLD = 0.7;
- protected static final double BAD_THRESHOLD = 0.3;
-
- protected static final DecimalFormat FORMATTER;
-
- /** Initialize the decimal formatter. */
- static {
- FORMATTER = new DecimalFormat("#.#");
- FORMATTER.setRoundingMode(RoundingMode.HALF_UP);
- }
-
- /**
- * Gets a new coverage status and adds notification emails to the messages list.
- *
- * Send an email to notify subscribers in the event that a test goes up or down by more than 5%,
- * becomes higher or lower than 70%, or becomes higher or lower than 30%.
- *
- * @param status The TestCoverageStatusEntity object for the test.
- * @param testRunKey The key for TestRunEntity whose data to process and reflect in the state.
- * @param link The string URL linking to the test's status table.
- * @param emailAddresses The list of email addresses to send notifications to.
- * @param messages The email Message queue.
- * @returns TestCoverageStatusEntity or null if no update is available.
- */
- public static TestCoverageStatusEntity getTestCoverageStatus(
- TestCoverageStatusEntity status,
- Key testRunKey,
- String link,
- List<String> emailAddresses,
- List<Message> messages)
- throws IOException {
- DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
-
- String testName = status.getTestName();
-
- double previousPct;
- double coveragePct;
- if (status == null || status.getTotalLineCount() <= 0 || status.getCoveredLineCount() < 0) {
- previousPct = 0;
- } else {
- previousPct = ((double) status.getCoveredLineCount()) / status.getTotalLineCount();
- }
-
- Entity testRun;
- try {
- testRun = datastore.get(testRunKey);
- } catch (EntityNotFoundException e) {
- logger.log(Level.WARNING, "Test run not found: " + testRunKey);
- return null;
- }
-
- TestRunEntity testRunEntity = TestRunEntity.fromEntity(testRun);
- if (testRunEntity == null || !testRunEntity.getHasCodeCoverage()) {
- return null;
- }
- CodeCoverageEntity codeCoverageEntity = testRunEntity.getCodeCoverageEntity();
-
- if (codeCoverageEntity.getTotalLineCount() <= 0
- || codeCoverageEntity.getCoveredLineCount() < 0) {
- coveragePct = 0;
- } else {
- coveragePct =
- ((double) codeCoverageEntity.getCoveredLineCount())
- / codeCoverageEntity.getTotalLineCount();
- }
-
- Set<String> buildIdList = new HashSet<>();
- Query deviceQuery = new Query(DeviceInfoEntity.KIND).setAncestor(testRun.getKey());
- List<DeviceInfoEntity> devices = new ArrayList<>();
- for (Entity device : datastore.prepare(deviceQuery).asIterable()) {
- DeviceInfoEntity deviceEntity = DeviceInfoEntity.fromEntity(device);
- if (deviceEntity == null) {
- continue;
- }
- devices.add(deviceEntity);
- buildIdList.add(deviceEntity.getBuildId());
- }
- String deviceBuild = StringUtils.join(buildIdList, ", ");
- String footer = EmailHelper.getEmailFooter(testRunEntity, devices, link);
-
- String subject = null;
- String body = null;
- String subjectSuffix = " @ " + deviceBuild;
- if (coveragePct >= GOOD_THRESHOLD && previousPct < GOOD_THRESHOLD) {
- // Coverage entered the good zone
- subject =
- "Congratulations! "
- + testName
- + " has exceeded "
- + FORMATTER.format(GOOD_THRESHOLD * 100)
- + "% coverage"
- + subjectSuffix;
- body =
- "Hello,<br><br>The "
- + testName
- + " has achieved "
- + FORMATTER.format(coveragePct * 100)
- + "% code coverage on device build ID(s): "
- + deviceBuild
- + "."
- + footer;
- } else if (coveragePct < GOOD_THRESHOLD && previousPct >= GOOD_THRESHOLD) {
- // Coverage dropped out of the good zone
- subject =
- "Warning! "
- + testName
- + " has dropped below "
- + FORMATTER.format(GOOD_THRESHOLD * 100)
- + "% coverage"
- + subjectSuffix;
- ;
- body =
- "Hello,<br><br>The test "
- + testName
- + " has dropped to "
- + FORMATTER.format(coveragePct * 100)
- + "% code coverage on device build ID(s): "
- + deviceBuild
- + "."
- + footer;
- } else if (coveragePct <= BAD_THRESHOLD && previousPct > BAD_THRESHOLD) {
- // Coverage entered into the bad zone
- subject =
- "Warning! "
- + testName
- + " has dropped below "
- + FORMATTER.format(BAD_THRESHOLD * 100)
- + "% coverage"
- + subjectSuffix;
- body =
- "Hello,<br><br>The test "
- + testName
- + " has dropped to "
- + FORMATTER.format(coveragePct * 100)
- + "% code coverage on device build ID(s): "
- + deviceBuild
- + "."
- + footer;
- } else if (coveragePct > BAD_THRESHOLD && previousPct <= BAD_THRESHOLD) {
- // Coverage emerged from the bad zone
- subject =
- "Congratulations! "
- + testName
- + " has exceeded "
- + FORMATTER.format(BAD_THRESHOLD * 100)
- + "% coverage"
- + subjectSuffix;
- body =
- "Hello,<br><br>The test "
- + testName
- + " has achived "
- + FORMATTER.format(coveragePct * 100)
- + "% code coverage on device build ID(s): "
- + deviceBuild
- + "."
- + footer;
- } else if (coveragePct - previousPct < -CHANGE_ALERT_THRESHOLD) {
- // Send a coverage drop alert
- subject =
- "Warning! "
- + testName
- + "'s code coverage has decreased by more than "
- + FORMATTER.format(CHANGE_ALERT_THRESHOLD * 100)
- + "%"
- + subjectSuffix;
- body =
- "Hello,<br><br>The test "
- + testName
- + " has dropped from "
- + FORMATTER.format(previousPct * 100)
- + "% code coverage to "
- + FORMATTER.format(coveragePct * 100)
- + "% code coverage on device build ID(s): "
- + deviceBuild
- + "."
- + footer;
- } else if (coveragePct - previousPct > CHANGE_ALERT_THRESHOLD) {
- // Send a coverage improvement alert
- subject =
- testName
- + "'s code coverage has increased by more than "
- + FORMATTER.format(CHANGE_ALERT_THRESHOLD * 100)
- + "%"
- + subjectSuffix;
- body =
- "Hello,<br><br>The test "
- + testName
- + " has increased from "
- + FORMATTER.format(previousPct * 100)
- + "% code coverage to "
- + FORMATTER.format(coveragePct * 100)
- + "% code coverage on device build ID(s): "
- + deviceBuild
- + "."
- + footer;
- }
- if (subject != null && body != null) {
- try {
- messages.add(EmailHelper.composeEmail(emailAddresses, subject, body));
- } catch (MessagingException | UnsupportedEncodingException e) {
- logger.log(Level.WARNING, "Error composing email : ", e);
- }
- }
- return new TestCoverageStatusEntity(
- testName,
- testRunEntity.getStartTimestamp(),
- codeCoverageEntity.getCoveredLineCount(),
- codeCoverageEntity.getTotalLineCount(),
- devices.size() > 0 ? devices.get(0).getId() : 0);
- }
-
- /**
- * Add a task to process coverage data
- *
- * @param testRunKey The key of the test run whose data process.
- */
- public static void addTask(Key testRunKey) {
- Queue queue = QueueFactory.getDefaultQueue();
- String keyString = KeyFactory.keyToString(testRunKey);
- queue.add(
- TaskOptions.Builder.withUrl(COVERAGE_ALERT_URL)
- .param("runKey", keyString)
- .method(TaskOptions.Method.POST));
- }
-
- @Override
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws IOException {
- String runKeyString = request.getParameter("runKey");
-
- Key testRunKey;
- try {
- testRunKey = KeyFactory.stringToKey(runKeyString);
- } catch (IllegalArgumentException e) {
- logger.log(Level.WARNING, "Invalid key specified: " + runKeyString);
- return;
- }
- String testName = testRunKey.getParent().getName();
-
- TestCoverageStatusEntity status = ofy().load().type(TestCoverageStatusEntity.class).id(testName)
- .now();
- if (status == null) {
- status = new TestCoverageStatusEntity(testName, 0, -1, -1, 0);
- }
-
- StringBuffer fullUrl = request.getRequestURL();
- String baseUrl = fullUrl.substring(0, fullUrl.indexOf(request.getRequestURI()));
- String link = baseUrl + "/show_tree?testName=" + testName;
- TestCoverageStatusEntity newStatus;
- List<Message> messageQueue = new ArrayList<>();
- try {
- List<String> emails = EmailHelper.getSubscriberEmails(testRunKey.getParent());
- newStatus = getTestCoverageStatus(status, testRunKey, link, emails, messageQueue);
- } catch (IOException e) {
- logger.log(Level.SEVERE, e.toString());
- return;
- }
-
- if (newStatus == null) {
- return;
- } else {
- if (status == null || status.getUpdatedTimestamp() < newStatus.getUpdatedTimestamp()) {
- newStatus.save();
- EmailHelper.sendAll(messageQueue);
- }
- }
- }
-}