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.TestRunDetails;
23 import com.google.gson.Gson;
24 import java.io.IOException;
25 import java.io.PrintWriter;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Objects;
30 import java.util.logging.Logger;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33 
34 import static com.googlecode.objectify.ObjectifyService.ofy;
35 
36 /** Servlet for handling requests to fetch test case results. */
37 public class TestRunRestServlet extends BaseApiServlet {
38     private static final String LATEST = "latest";
39     protected static final Logger logger = Logger.getLogger(TestRunRestServlet.class.getName());
40 
41     /**
42      * Get the test case results for the specified run of the specified test.
43      *
44      * @param test The test whose test cases to get.
45      * @param timeString The string representation of the test run timestamp (in microseconds).
46      * @return A TestRunDetails object with the test case details for the specified run.
47      */
getTestRunDetails(String test, String timeString)48     private TestRunDetails getTestRunDetails(String test, String timeString) {
49         long timestamp;
50         try {
51             timestamp = Long.parseLong(timeString);
52             if (timestamp <= 0) throw new NumberFormatException();
53             timestamp = timestamp > 0 ? timestamp : null;
54         } catch (NumberFormatException e) {
55             return null;
56         }
57 
58         TestRunEntity testRunEntity = TestRunEntity.getByTestNameId(test, timestamp);
59 
60         return getTestRunDetails(testRunEntity);
61     }
62 
63     /**
64      * Get the test case results for the latest run of the specified test.
65      *
66      * @param testName The test whose test cases to get.
67      * @return A TestRunDetails object with the test case details for the latest run.
68      */
getLatestTestRunDetails(String testName)69     private TestRunDetails getLatestTestRunDetails(String testName) {
70         com.googlecode.objectify.Key testKey =
71                 com.googlecode.objectify.Key.create(
72                         TestEntity.class, testName);
73 
74         TestRunEntity testRun = ofy().load().type(TestRunEntity.class).ancestor(testKey)
75                 .filter("type", 2).orderKey(true).first().now();
76 
77         if (testRun == null) return null;
78 
79         return getTestRunDetails(testRun);
80     }
81 
82     /**
83      * Get TestRunDetails instance from codeCoverageEntity instance.
84      *
85      * @param testRunEntity The TestRunEntity to access testCaseId.
86      * @return A TestRunDetails object with the test case details for the latest run.
87      */
getTestRunDetails(TestRunEntity testRunEntity)88     private TestRunDetails getTestRunDetails(TestRunEntity testRunEntity) {
89         TestRunDetails details = new TestRunDetails();
90         List<com.googlecode.objectify.Key<TestCaseRunEntity>> testCaseKeyList = new ArrayList<>();
91         if ( Objects.isNull(testRunEntity.getTestCaseIds()) ) {
92             return details;
93         } else {
94             for (long testCaseId : testRunEntity.getTestCaseIds()) {
95                 testCaseKeyList.add(
96                         com.googlecode.objectify.Key.create(TestCaseRunEntity.class, testCaseId));
97             }
98             Map<com.googlecode.objectify.Key<TestCaseRunEntity>, TestCaseRunEntity>
99                     testCaseRunEntityKeyMap = ofy().load().keys(() -> testCaseKeyList.iterator());
100             testCaseRunEntityKeyMap.forEach((key, value) -> details.addTestCase(value));
101         }
102         return details;
103     }
104 
105     /**
106      * Get the test case details for a test run.
107      *
108      * Expected format: (1) /api/test_run?test=[test name]&timestamp=[timestamp] to the details
109      * for a specific run, or (2) /api/test_run?test=[test name]&timestamp=latest -- the details for
110      * the latest test run.
111      */
112     @Override
doGet(HttpServletRequest request, HttpServletResponse response)113     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
114         String test = request.getParameter("test");
115         String timeString = request.getParameter("timestamp");
116         TestRunDetails details = null;
117 
118         if (timeString != null && timeString.equals(LATEST)) {
119             details = getLatestTestRunDetails(test);
120         } else if (timeString != null) {
121             details = getTestRunDetails(test, timeString);
122         }
123 
124         if (details == null) {
125             response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
126         } else {
127             response.setStatus(HttpServletResponse.SC_OK);
128             response.setContentType("application/json");
129             PrintWriter writer = response.getWriter();
130             writer.print(new Gson().toJson(details.toJson()));
131             writer.flush();
132         }
133     }
134 }
135