1 /*
2  * Copyright (c) 2018 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.ApiCoverageEntity;
20 import com.android.vts.entity.CoverageEntity;
21 import com.android.vts.entity.TestCoverageStatusEntity;
22 import com.android.vts.entity.TestPlanRunEntity;
23 import com.android.vts.entity.TestRunEntity;
24 import com.google.gson.Gson;
25 import com.googlecode.objectify.Key;
26 
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Objects;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
38 
39 import static com.googlecode.objectify.ObjectifyService.ofy;
40 
41 /** REST endpoint for posting test suite data to the Dashboard. */
42 public class CoverageRestServlet extends BaseApiServlet {
43 
44     private static final Logger logger = Logger.getLogger(CoverageRestServlet.class.getName());
45 
46     @Override
doGet(HttpServletRequest request, HttpServletResponse response)47     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
48         String pathInfo = request.getPathInfo();
49         String json = "";
50         if (Objects.nonNull(pathInfo)) {
51             if (pathInfo.equalsIgnoreCase("/api/data")) {
52                 String key = request.getParameter("key");
53                 json = apiCoverageData(key);
54             } else {
55                 json = "{error: 'true', message: 'unexpected path!!!'}";
56                 logger.log(Level.INFO, "Path Info => " + pathInfo);
57                 logger.log(Level.WARNING, "Unknown path access!");
58             }
59         } else {
60             json = "{error: 'true', message: 'the path info is not existed!!!'}";
61         }
62 
63         response.setStatus(HttpServletResponse.SC_OK);
64         response.setContentType("application/json");
65         response.setCharacterEncoding("UTF-8");
66         response.getWriter().write(json);
67     }
68 
apiCoverageData(String key)69     private String apiCoverageData(String key) {
70         ApiCoverageEntity apiCoverageEntity = ApiCoverageEntity.getByUrlSafeKey(key);
71         String apiCoverageEntityJson = new Gson().toJson(apiCoverageEntity);
72         return apiCoverageEntityJson;
73     }
74 
75     @Override
doPost(HttpServletRequest request, HttpServletResponse response)76     public void doPost(HttpServletRequest request, HttpServletResponse response)
77             throws IOException {
78 
79         String pathInfo = request.getPathInfo();
80         String json = "";
81         if (Objects.nonNull(pathInfo)) {
82             if (pathInfo.equalsIgnoreCase("/api/data")) {
83                 String cmd = request.getParameter("cmd");
84                 String coverageId = request.getParameter("coverageId");
85                 String testName = request.getParameter("testName");
86                 String testRunId = request.getParameter("testRunId");
87                 json = postCoverageData(cmd, coverageId, testName, testRunId);
88             } else if (pathInfo.equalsIgnoreCase("/api/sum")) {
89                 String urlSafeKey = request.getParameter("urlSafeKey");
90                 json = postCoverageDataSum(urlSafeKey);
91             } else {
92                 json = "{error: 'true', message: 'unexpected path!!!'}";
93             }
94         } else {
95             json = "{error: 'true', message: 'the path info is not existed!!!'}";
96         }
97 
98         response.setStatus(HttpServletResponse.SC_OK);
99         response.setContentType("application/json");
100         response.setCharacterEncoding("UTF-8");
101         response.getWriter().write(json);
102     }
103 
postCoverageDataSum(String urlSafeKey)104     private String postCoverageDataSum(String urlSafeKey) {
105         List<List<String>> allHalApiList = new ArrayList();
106         List<List<String>> allCoveredHalApiList = new ArrayList();
107 
108         Key<TestPlanRunEntity> key = Key.create(urlSafeKey);
109         TestPlanRunEntity testPlanRunEntity = ofy().load().key(key).safe();
110 
111         for (Key<TestRunEntity> testRunKey : testPlanRunEntity.getTestRuns()) {
112             List<ApiCoverageEntity> apiCoverageEntityList =
113                     ofy().load().type(ApiCoverageEntity.class).ancestor(testRunKey).list();
114             for (ApiCoverageEntity apiCoverageEntity : apiCoverageEntityList) {
115                 allHalApiList.add(apiCoverageEntity.getHalApi());
116                 allCoveredHalApiList.add(apiCoverageEntity.getCoveredHalApi());
117             }
118         }
119         long totalHalApiNum = allHalApiList.stream().flatMap(Collection::stream).distinct().count();
120         long totalCoveredHalApiNum =
121                 allCoveredHalApiList.stream().flatMap(Collection::stream).distinct().count();
122         if (totalHalApiNum > 0) {
123             testPlanRunEntity.setTotalApiCount(totalHalApiNum);
124             if (totalCoveredHalApiNum > 0) {
125                 testPlanRunEntity.setCoveredApiCount(totalCoveredHalApiNum);
126             }
127             testPlanRunEntity.save();
128         }
129 
130         Map<String, Long> halApiNumMap =
131                 new HashMap<String, Long>() {
132                     {
133                         put("totalHalApiNum", totalHalApiNum);
134                         put("totalCoveredHalApiNum", totalCoveredHalApiNum);
135                     }
136                 };
137         String json = new Gson().toJson(halApiNumMap);
138         return json;
139     }
140 
141     /**
142      * The API to ignore the irrelevant code for calculating ratio
143      *
144      * @param cmd disable or enable command to ignore the code.
145      * @param coverageId the datastore ID for code coverage.
146      * @param testName the test name.
147      * @param testRunId the test run ID from datastore.
148      * @return success json.
149      */
postCoverageData( String cmd, String coverageId, String testName, String testRunId)150     private String postCoverageData(
151             String cmd, String coverageId, String testName, String testRunId) {
152 
153         Boolean isIgnored = false;
154         if (cmd.equals("disable")) {
155             isIgnored = true;
156         }
157         CoverageEntity coverageEntity = CoverageEntity.findById(testName, testRunId, coverageId);
158         coverageEntity.setIsIgnored(isIgnored);
159         coverageEntity.save();
160 
161         TestCoverageStatusEntity testCoverageStatusEntity =
162                 TestCoverageStatusEntity.findById(testName);
163         Long newCoveredLineCount =
164                 cmd.equals("disable")
165                         ? testCoverageStatusEntity.getUpdatedCoveredLineCount()
166                                 - coverageEntity.getCoveredCount()
167                         : testCoverageStatusEntity.getUpdatedCoveredLineCount()
168                                 + coverageEntity.getCoveredCount();
169         Long newTotalLineCount =
170                 cmd.equals("disable")
171                         ? testCoverageStatusEntity.getUpdatedTotalLineCount()
172                                 - coverageEntity.getTotalCount()
173                         : testCoverageStatusEntity.getUpdatedTotalLineCount()
174                                 + coverageEntity.getTotalCount();
175         testCoverageStatusEntity.setUpdatedCoveredLineCount(newCoveredLineCount);
176         testCoverageStatusEntity.setUpdatedTotalLineCount(newTotalLineCount);
177         testCoverageStatusEntity.save();
178 
179         String json = new Gson().toJson("Success!");
180         return json;
181     }
182 }
183