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.entity; 18 19 import com.android.vts.proto.VtsReportMessage.CoverageReportMessage; 20 import com.google.appengine.api.datastore.Entity; 21 import com.google.appengine.api.datastore.Key; 22 import java.util.ArrayList; 23 import java.util.List; 24 import java.util.logging.Level; 25 import java.util.logging.Logger; 26 27 /** Object describing coverage data gathered for a file. */ 28 public class CoverageEntity implements DashboardEntity { 29 protected static final Logger logger = Logger.getLogger(CoverageEntity.class.getName()); 30 31 public static final String KIND = "Coverage"; 32 33 // Property keys 34 public static final String GROUP = "group"; 35 public static final String COVERED_LINE_COUNT = "coveredCount"; 36 public static final String TOTAL_LINE_COUNT = "totalCount"; 37 public static final String FILE_PATH = "filePath"; 38 public static final String PROJECT_NAME = "projectName"; 39 public static final String PROJECT_VERSION = "projectVersion"; 40 public static final String LINE_COVERAGE = "lineCoverage"; 41 42 private final Key parentKey; 43 44 public final String group; 45 public final long coveredLineCount; 46 public final long totalLineCount; 47 public final String filePath; 48 public final String projectName; 49 public final String projectVersion; 50 public final List<Long> lineCoverage; 51 52 /** 53 * Create a CoverageEntity object for a file. 54 * 55 * @param parentKey The key to the parent TestRunEntity object in the database. 56 * @param group The group within the test run describing the coverage. 57 * @param coveredLineCount The total number of covered lines in the file. 58 * @param totalLineCount The total number of uncovered executable lines in the file. 59 * @param filePath The path to the file. 60 * @param projectName The name of the git project. 61 * @param projectVersion The commit hash of the project at the time the test was executed. 62 * @param lineCoverage List of coverage counts per executable line in the file. 63 */ 64 public CoverageEntity(Key parentKey, String group, long coveredLineCount, long totalLineCount, 65 String filePath, String projectName, String projectVersion, List<Long> lineCoverage) { 66 this.parentKey = parentKey; 67 this.group = group; 68 this.coveredLineCount = coveredLineCount; 69 this.totalLineCount = totalLineCount; 70 this.filePath = filePath; 71 this.projectName = projectName; 72 this.projectVersion = projectVersion; 73 this.lineCoverage = lineCoverage; 74 } 75 76 @Override 77 public Entity toEntity() { 78 Entity coverageEntity = new Entity(KIND, parentKey); 79 coverageEntity.setProperty(GROUP, group); 80 coverageEntity.setUnindexedProperty(COVERED_LINE_COUNT, coveredLineCount); 81 coverageEntity.setUnindexedProperty(TOTAL_LINE_COUNT, totalLineCount); 82 coverageEntity.setProperty(FILE_PATH, filePath); 83 coverageEntity.setUnindexedProperty(PROJECT_NAME, projectName); 84 coverageEntity.setUnindexedProperty(PROJECT_VERSION, projectVersion); 85 if (lineCoverage != null && lineCoverage.size() > 0) { 86 coverageEntity.setUnindexedProperty(LINE_COVERAGE, lineCoverage); 87 } 88 return coverageEntity; 89 } 90 91 /** 92 * Convert an Entity object to a CoverageEntity. 93 * 94 * @param e The entity to process. 95 * @return CoverageEntity object with the properties from e, or null if incompatible. 96 */ 97 @SuppressWarnings("unchecked") 98 public static CoverageEntity fromEntity(Entity e) { 99 if (!e.getKind().equals(KIND) || !e.hasProperty(GROUP) || !e.hasProperty(COVERED_LINE_COUNT) 100 || !e.hasProperty(TOTAL_LINE_COUNT) || !e.hasProperty(FILE_PATH) 101 || !e.hasProperty(PROJECT_NAME) || !e.hasProperty(PROJECT_VERSION)) { 102 logger.log(Level.WARNING, "Missing coverage attributes in entity: " + e.toString()); 103 return null; 104 } 105 try { 106 String group = (String) e.getProperty(GROUP); 107 long coveredLineCount = (long) e.getProperty(COVERED_LINE_COUNT); 108 long totalLineCount = (long) e.getProperty(TOTAL_LINE_COUNT); 109 String filePath = (String) e.getProperty(FILE_PATH); 110 String projectName = (String) e.getProperty(PROJECT_NAME); 111 String projectVersion = (String) e.getProperty(PROJECT_VERSION); 112 List<Long> lineCoverage; 113 if (e.hasProperty(LINE_COVERAGE)) { 114 lineCoverage = (List<Long>) e.getProperty(LINE_COVERAGE); 115 } else { 116 lineCoverage = new ArrayList<>(); 117 } 118 return new CoverageEntity(e.getKey().getParent(), group, coveredLineCount, 119 totalLineCount, filePath, projectName, projectVersion, lineCoverage); 120 } catch (ClassCastException exception) { 121 // Invalid contents or null values 122 logger.log(Level.WARNING, "Error parsing coverage entity.", exception); 123 } 124 return null; 125 } 126 127 /** 128 * Convert a coverage report to a CoverageEntity. 129 * 130 * @param parentKey The ancestor key for the coverage entity. 131 * @param group The group to display the coverage report with. 132 * @param coverage The coverage report containing coverage data. 133 * @return The CoverageEntity for the coverage report message, or null if not compatible. 134 */ 135 public static CoverageEntity fromCoverageReport( 136 Key parentKey, String group, CoverageReportMessage coverage) { 137 if (!coverage.hasFilePath() || !coverage.hasProjectName() || !coverage.hasRevision() 138 || !coverage.hasTotalLineCount() || !coverage.hasCoveredLineCount()) { 139 return null; // invalid coverage report; 140 } 141 long coveredLineCount = coverage.getCoveredLineCount(); 142 long totalLineCount = coverage.getTotalLineCount(); 143 String filePath = coverage.getFilePath().toStringUtf8(); 144 String projectName = coverage.getProjectName().toStringUtf8(); 145 String projectVersion = coverage.getRevision().toStringUtf8(); 146 List<Long> lineCoverage = null; 147 if (coverage.getLineCoverageVectorCount() > 0) { 148 lineCoverage = new ArrayList<>(); 149 for (int count : coverage.getLineCoverageVectorList()) { 150 lineCoverage.add((long) count); 151 } 152 } 153 return new CoverageEntity(parentKey, group, coveredLineCount, totalLineCount, filePath, 154 projectName, projectVersion, lineCoverage); 155 } 156 } 157