Home | History | Annotate | Download | only in api
      1 /*
      2  * Copyright (c) 2017 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.api;
     18 
     19 import com.android.vts.entity.TestCaseRunEntity;
     20 import com.android.vts.entity.TestEntity;
     21 import com.android.vts.entity.TestRunEntity;
     22 import com.android.vts.util.FilterUtil;
     23 import com.android.vts.util.TestRunDetails;
     24 import com.google.appengine.api.datastore.DatastoreService;
     25 import com.google.appengine.api.datastore.DatastoreServiceFactory;
     26 import com.google.appengine.api.datastore.Entity;
     27 import com.google.appengine.api.datastore.EntityNotFoundException;
     28 import com.google.appengine.api.datastore.FetchOptions;
     29 import com.google.appengine.api.datastore.Key;
     30 import com.google.appengine.api.datastore.KeyFactory;
     31 import com.google.appengine.api.datastore.Query;
     32 import com.google.gson.Gson;
     33 import java.io.IOException;
     34 import java.io.PrintWriter;
     35 import java.util.ArrayList;
     36 import java.util.List;
     37 import java.util.Map;
     38 import java.util.logging.Logger;
     39 import javax.servlet.http.HttpServlet;
     40 import javax.servlet.http.HttpServletRequest;
     41 import javax.servlet.http.HttpServletResponse;
     42 
     43 /** Servlet for handling requests to fetch test case results. */
     44 public class TestRunRestServlet extends HttpServlet {
     45     private static final String LATEST = "latest";
     46     protected static final Logger logger = Logger.getLogger(TestRunRestServlet.class.getName());
     47 
     48     /**
     49      * Get the test case results for the specified run of the specified test.
     50      *
     51      * @param test The test whose test cases to get.
     52      * @param timeString The string representation of the test run timestamp (in microseconds).
     53      * @return A TestRunDetails object with the test case details for the specified run.
     54      */
     55     private static TestRunDetails getTestRunDetails(String test, String timeString) {
     56         DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
     57         long timestamp;
     58         try {
     59             timestamp = Long.parseLong(timeString);
     60             if (timestamp <= 0) throw new NumberFormatException();
     61             timestamp = timestamp > 0 ? timestamp : null;
     62         } catch (NumberFormatException e) {
     63             return null;
     64         }
     65 
     66         Key testKey = KeyFactory.createKey(TestEntity.KIND, test);
     67         Key testRunKey = KeyFactory.createKey(testKey, TestRunEntity.KIND, timestamp);
     68         TestRunEntity testRunEntity;
     69         try {
     70             Entity testRun = datastore.get(testRunKey);
     71             testRunEntity = TestRunEntity.fromEntity(testRun);
     72             if (testRunEntity == null) {
     73                 throw new EntityNotFoundException(testRunKey);
     74             }
     75         } catch (EntityNotFoundException e) {
     76             return null;
     77         }
     78         TestRunDetails details = new TestRunDetails();
     79         List<Key> gets = new ArrayList<>();
     80         for (long testCaseId : testRunEntity.testCaseIds) {
     81             gets.add(KeyFactory.createKey(TestCaseRunEntity.KIND, testCaseId));
     82         }
     83         Map<Key, Entity> entityMap = datastore.get(gets);
     84         for (Key key : entityMap.keySet()) {
     85             TestCaseRunEntity testCaseRun = TestCaseRunEntity.fromEntity(entityMap.get(key));
     86             if (testCaseRun == null) {
     87                 continue;
     88             }
     89             details.addTestCase(testCaseRun);
     90         }
     91         return details;
     92     }
     93 
     94     /**
     95      * Get the test case results for the latest run of the specified test.
     96      *
     97      * @param test The test whose test cases to get.
     98      * @return A TestRunDetails object with the test case details for the latest run.
     99      */
    100     private static TestRunDetails getLatestTestRunDetails(String test) {
    101         DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    102         Key testKey = KeyFactory.createKey(TestEntity.KIND, test);
    103         Query.Filter typeFilter = FilterUtil.getTestTypeFilter(false, true, false);
    104         Query testRunQuery =
    105                 new Query(TestRunEntity.KIND)
    106                         .setAncestor(testKey)
    107                         .setFilter(typeFilter)
    108                         .addSort(Entity.KEY_RESERVED_PROPERTY, Query.SortDirection.DESCENDING);
    109         TestRunEntity testRun = null;
    110         for (Entity testRunEntity :
    111                 datastore.prepare(testRunQuery).asIterable(FetchOptions.Builder.withLimit(1))) {
    112             testRun = TestRunEntity.fromEntity(testRunEntity);
    113         }
    114         if (testRun == null) return null;
    115         TestRunDetails details = new TestRunDetails();
    116 
    117         List<Key> gets = new ArrayList<>();
    118         for (long testCaseId : testRun.testCaseIds) {
    119             gets.add(KeyFactory.createKey(TestCaseRunEntity.KIND, testCaseId));
    120         }
    121         Map<Key, Entity> entityMap = datastore.get(gets);
    122         for (Key key : entityMap.keySet()) {
    123             TestCaseRunEntity testCaseRun = TestCaseRunEntity.fromEntity(entityMap.get(key));
    124             if (testCaseRun == null) {
    125                 continue;
    126             }
    127             details.addTestCase(testCaseRun);
    128         }
    129         return details;
    130     }
    131 
    132     /**
    133      * Get the test case details for a test run.
    134      *
    135      * Expected format: (1) /api/test_run?test=[test name]&timestamp=[timestamp] to the details
    136      * for a specific run, or (2) /api/test_run?test=[test name]&timestamp=latest -- the details for
    137      * the latest test run.
    138      */
    139     @Override
    140     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    141         String test = request.getParameter("test");
    142         String timeString = request.getParameter("timestamp");
    143         TestRunDetails details = null;
    144 
    145         if (timeString != null && timeString.equals(LATEST)) {
    146             details = getLatestTestRunDetails(test);
    147         } else if (timeString != null) {
    148             details = getTestRunDetails(test, timeString);
    149         }
    150 
    151         if (details == null) {
    152             response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
    153         } else {
    154             response.setStatus(HttpServletResponse.SC_OK);
    155             response.setContentType("application/json");
    156             PrintWriter writer = response.getWriter();
    157             writer.print(new Gson().toJson(details.toJson()));
    158             writer.flush();
    159         }
    160     }
    161 }
    162