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 static com.googlecode.objectify.ObjectifyService.ofy; 20 21 import com.google.appengine.api.datastore.Entity; 22 import com.googlecode.objectify.Key; 23 import com.googlecode.objectify.annotation.Cache; 24 import com.googlecode.objectify.annotation.Id; 25 import com.googlecode.objectify.annotation.Index; 26 import java.util.Collection; 27 import java.util.Date; 28 import java.util.List; 29 import java.util.Map; 30 import java.util.Set; 31 import java.util.logging.Level; 32 import java.util.logging.Logger; 33 import java.util.stream.Collectors; 34 import lombok.EqualsAndHashCode; 35 import lombok.Getter; 36 import lombok.NoArgsConstructor; 37 import lombok.Setter; 38 39 @com.googlecode.objectify.annotation.Entity(name = "TestCoverageStatus") 40 @EqualsAndHashCode(of = "testName") 41 @Cache 42 @NoArgsConstructor 43 /** Entity describing test coverage status. */ 44 public class TestCoverageStatusEntity implements DashboardEntity { 45 46 protected static final Logger logger = 47 Logger.getLogger(TestCoverageStatusEntity.class.getName()); 48 49 public static final String KIND = "TestCoverageStatus"; 50 51 // Property keys 52 public static final String TOTAL_LINE_COUNT = "totalLineCount"; 53 public static final String COVERED_LINE_COUNT = "coveredLineCount"; 54 public static final String UPDATED_TIMESTAMP = "updatedTimestamp"; 55 public static final String DEVICE_INFO_ID = "deviceInfoId"; 56 57 /** TestCoverageStatusEntity name field */ 58 @Id @Getter @Setter String testName; 59 60 /** TestCoverageStatusEntity coveredLineCount field */ 61 @Index @Getter @Setter long coveredLineCount; 62 63 /** TestCoverageStatusEntity totalLineCount field */ 64 @Index @Getter @Setter long totalLineCount; 65 66 /** TestCoverageStatusEntity updatedTimestamp field */ 67 @Index @Getter @Setter long updatedTimestamp; 68 69 /** TestCoverageStatusEntity DeviceInfo Entity ID reference field */ 70 @Index @Getter @Setter long deviceInfoId; 71 72 /** TestCoverageStatusEntity updatedCoveredLineCount field */ 73 @Index @Getter @Setter long updatedCoveredLineCount; 74 75 /** TestCoverageStatusEntity updatedTotalLineCount field */ 76 @Index @Getter @Setter long updatedTotalLineCount; 77 78 /** TestCoverageStatusEntity updatedDate field */ 79 @Index @Getter @Setter Date updatedDate; 80 81 /** 82 * Create a TestCoverageStatusEntity object with status metadata. 83 * 84 * @param testName The name of the test. 85 * @param timestamp The timestamp indicating the most recent test run event in the test state. 86 * @param coveredLineCount The number of lines covered. 87 * @param totalLineCount The total number of lines. 88 */ TestCoverageStatusEntity( String testName, long timestamp, long coveredLineCount, long totalLineCount, long deviceInfoId)89 public TestCoverageStatusEntity( 90 String testName, 91 long timestamp, 92 long coveredLineCount, 93 long totalLineCount, 94 long deviceInfoId) { 95 this.testName = testName; 96 this.updatedTimestamp = timestamp; 97 this.coveredLineCount = coveredLineCount; 98 this.totalLineCount = totalLineCount; 99 this.deviceInfoId = deviceInfoId; 100 } 101 102 /** find TestCoverageStatus entity by ID */ findById(String testName)103 public static TestCoverageStatusEntity findById(String testName) { 104 return ofy().load().type(TestCoverageStatusEntity.class).id(testName).now(); 105 } 106 107 /** Get all TestCoverageStatusEntity List */ getTestCoverageStatusMap()108 public static Map<String, TestCoverageStatusEntity> getTestCoverageStatusMap() { 109 List<TestCoverageStatusEntity> testCoverageStatusEntityList = getAllTestCoverage(); 110 111 Map<String, TestCoverageStatusEntity> testCoverageStatusMap = 112 testCoverageStatusEntityList.stream() 113 .collect(Collectors.toMap(t -> t.getTestName(), t -> t)); 114 return testCoverageStatusMap; 115 } 116 117 /** Get all DeviceInfoEntity List by TestCoverageStatusEntities' key list */ getDeviceInfoEntityKeyList( List<TestCoverageStatusEntity> testCoverageStatusEntityList)118 public static List<Key<DeviceInfoEntity>> getDeviceInfoEntityKeyList( 119 List<TestCoverageStatusEntity> testCoverageStatusEntityList) { 120 return testCoverageStatusEntityList 121 .stream() 122 .map( 123 testCoverageStatusEntity -> { 124 com.googlecode.objectify.Key testKey = 125 com.googlecode.objectify.Key.create( 126 TestEntity.class, 127 testCoverageStatusEntity.getTestName()); 128 com.googlecode.objectify.Key testRunKey = 129 com.googlecode.objectify.Key.create( 130 testKey, 131 TestRunEntity.class, 132 testCoverageStatusEntity.getUpdatedTimestamp()); 133 return com.googlecode.objectify.Key.create( 134 testRunKey, 135 DeviceInfoEntity.class, 136 testCoverageStatusEntity.getDeviceInfoId()); 137 }) 138 .collect(Collectors.toList()); 139 } 140 141 /** Get all TestCoverageStatusEntity List */ getAllTestCoverage()142 public static List<TestCoverageStatusEntity> getAllTestCoverage() { 143 return ofy().load().type(TestCoverageStatusEntity.class).list(); 144 } 145 146 /** Get all TestCoverageStatusEntities' Branch List */ getBranchSet( List<TestCoverageStatusEntity> testCoverageStatusEntityList)147 public static Set<String> getBranchSet( 148 List<TestCoverageStatusEntity> testCoverageStatusEntityList) { 149 List<com.googlecode.objectify.Key<DeviceInfoEntity>> deviceInfoEntityKeyList = 150 getDeviceInfoEntityKeyList(testCoverageStatusEntityList); 151 152 Collection<DeviceInfoEntity> deviceInfoEntityList = 153 ofy().load().keys(() -> deviceInfoEntityKeyList.iterator()).values(); 154 155 Set<String> branchSet = 156 deviceInfoEntityList 157 .stream() 158 .map(deviceInfoEntity -> deviceInfoEntity.getBranch()) 159 .collect(Collectors.toSet()); 160 return branchSet; 161 } 162 163 /** Get all TestCoverageStatusEntities' Device List */ getDeviceSet( List<TestCoverageStatusEntity> testCoverageStatusEntityList)164 public static Set<String> getDeviceSet( 165 List<TestCoverageStatusEntity> testCoverageStatusEntityList) { 166 List<com.googlecode.objectify.Key<DeviceInfoEntity>> deviceInfoEntityKeyList = 167 getDeviceInfoEntityKeyList(testCoverageStatusEntityList); 168 169 Collection<DeviceInfoEntity> deviceInfoEntityList = 170 ofy().load().keys(() -> deviceInfoEntityKeyList.iterator()).values(); 171 172 Set<String> deviceSet = 173 deviceInfoEntityList 174 .stream() 175 .map(deviceInfoEntity -> deviceInfoEntity.getBuildFlavor()) 176 .collect(Collectors.toSet()); 177 return deviceSet; 178 } 179 180 /** TestRunEntity function to get the related TestRunEntity from id value */ getTestRunEntity()181 public TestRunEntity getTestRunEntity() { 182 com.googlecode.objectify.Key testKey = 183 com.googlecode.objectify.Key.create(TestEntity.class, this.testName); 184 return ofy().load() 185 .type(TestRunEntity.class) 186 .parent(testKey) 187 .id(this.updatedTimestamp) 188 .now(); 189 } 190 191 /** Saving function for the instance of this class */ 192 @Override save()193 public Key<TestCoverageStatusEntity> save() { 194 this.updatedDate = new Date(); 195 return ofy().save().entity(this).now(); 196 } 197 toEntity()198 public Entity toEntity() { 199 Entity testEntity = new Entity(KIND, this.testName); 200 testEntity.setProperty(UPDATED_TIMESTAMP, this.updatedTimestamp); 201 testEntity.setProperty(COVERED_LINE_COUNT, this.coveredLineCount); 202 testEntity.setProperty(TOTAL_LINE_COUNT, this.totalLineCount); 203 return testEntity; 204 } 205 206 /** 207 * Convert an Entity object to a TestCoverageStatusEntity. 208 * 209 * @param e The entity to process. 210 * @return TestCoverageStatusEntity object with the properties from e processed, or null if 211 * incompatible. 212 */ 213 @SuppressWarnings("unchecked") fromEntity(Entity e)214 public static TestCoverageStatusEntity fromEntity(Entity e) { 215 if (!e.getKind().equals(KIND) 216 || e.getKey().getName() == null 217 || !e.hasProperty(UPDATED_TIMESTAMP) 218 || !e.hasProperty(COVERED_LINE_COUNT) 219 || !e.hasProperty(TOTAL_LINE_COUNT) 220 || !e.hasProperty(DEVICE_INFO_ID)) { 221 logger.log(Level.WARNING, "Missing test attributes in entity: " + e.toString()); 222 return null; 223 } 224 String testName = e.getKey().getName(); 225 long timestamp = 0; 226 long coveredLineCount = -1; 227 long totalLineCount = -1; 228 long deviceInfoId = 0; 229 try { 230 timestamp = (long) e.getProperty(UPDATED_TIMESTAMP); 231 coveredLineCount = (Long) e.getProperty(COVERED_LINE_COUNT); 232 totalLineCount = (Long) e.getProperty(TOTAL_LINE_COUNT); 233 deviceInfoId = (Long) e.getProperty(DEVICE_INFO_ID); 234 } catch (ClassCastException exception) { 235 // Invalid contents or null values 236 logger.log(Level.WARNING, "Error parsing test entity.", exception); 237 return null; 238 } 239 return new TestCoverageStatusEntity( 240 testName, timestamp, coveredLineCount, totalLineCount, deviceInfoId); 241 } 242 } 243