diff options
author | Young Gyu Park <younggyu@google.com> | 2018-10-29 20:43:40 +0900 |
---|---|---|
committer | Young Gyu Park <younggyu@google.com> | 2018-11-05 13:27:19 +0900 |
commit | f83e88ab69e184ba628bb711973e01af494de9b3 (patch) | |
tree | c8229d2b9eef41918339933638451fd732f64f18 | |
parent | cac480c7cea8ba7b14a9479e3bbe6d62d8c665e1 (diff) | |
download | dashboard-f83e88ab69e184ba628bb711973e01af494de9b3.tar.gz |
Adding HalApiEntity and implementing interface logic for the consistent
data insertion on datastore.
Test: go/vts-web-staging
Bug: 117130291
Change-Id: Ie078a36833b312d0ab09f9f4403ee5173fee8f1b
26 files changed, 870 insertions, 620 deletions
diff --git a/src/main/java/com/android/vts/entity/ApiCoverageEntity.java b/src/main/java/com/android/vts/entity/ApiCoverageEntity.java index 0a41743..9c74032 100644 --- a/src/main/java/com/android/vts/entity/ApiCoverageEntity.java +++ b/src/main/java/com/android/vts/entity/ApiCoverageEntity.java @@ -35,167 +35,125 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -/** - * Entity Class for ApiCoverageEntity - */ +/** Entity Class for ApiCoverageEntity */ @Cache @Entity(name = "ApiCoverage") @EqualsAndHashCode(of = "id") @NoArgsConstructor @JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonIgnoreProperties({"id", "parent"}) -public class ApiCoverageEntity { - - /** - * ApiCoverageEntity id field - */ - @Id - @Getter - @Setter - String id; - - @Parent - @Getter - Key<?> parent; - - /** - * HAL package name. e.g. android.hardware.foo. - */ - @Index - @Getter - @Setter - String halPackageName; - - /** - * HAL (major) version. e.g. 1. - */ - @Index - @Getter - @Setter - int halMajorVersion; - - /** - * HAL (minor) version. e.g. 0. - */ - @Index - @Getter - @Setter - int halMinorVersion; - - /** - * HAL interface name. e.g. IFoo. - */ - @Index - @Getter - @Setter - String halInterfaceName; - - /** - * List of HAL API - */ - @Getter - @Setter - List<String> halApi; - - /** - * List of HAL covered API - */ - @Getter - @Setter - List<String> coveredHalApi; - - /** - * When this record was created or updated - */ - @Index - Date updated; - - /** - * Constructor function for ApiCoverageEntity Class - */ - public ApiCoverageEntity(com.google.appengine.api.datastore.Key testRunKey, String halPackageName, - int halVersionMajor, int halVersionMinor, String halInterfaceName, List<String> halApi, - List<String> coveredHalApi) { - - this.parent = getParentKey(testRunKey); - - this.halPackageName = halPackageName; - this.halMajorVersion = halVersionMajor; - this.halMinorVersion = halVersionMinor; - this.halInterfaceName = halInterfaceName; - this.halApi = halApi; - this.coveredHalApi = coveredHalApi; - } - - /** - * Constructor function for ApiCoverageEntity Class with objectify Key. - */ - public ApiCoverageEntity(Key testRunKey, String halPackageName, - int halVersionMajor, int halVersionMinor, String halInterfaceName, - List<String> halApi, List<String> coveredHalApi) { - this.parent = testRunKey; - - this.halPackageName = halPackageName; - this.halMajorVersion = halVersionMajor; - this.halMinorVersion = halVersionMinor; - this.halInterfaceName = halInterfaceName; - this.halApi = halApi; - this.coveredHalApi = coveredHalApi; - } - - /** - * Get objectify Key from datastore Key type - */ - private Key getParentKey(com.google.appengine.api.datastore.Key testRunKey) { - Key testParentKey = Key.create(TestEntity.class, testRunKey.getParent().getName()); - return Key.create(testParentKey, TestRunEntity.class, testRunKey.getId()); - } - - /** - * Get UrlSafeKey from ApiCoverageEntity Information - */ - public String getUrlSafeKey() { - Key uuidKey = Key.create(this.parent, ApiCoverageEntity.class, this.id); - return uuidKey.toUrlSafe(); - } - - /** - * Saving function for the instance of this class - */ - public Key<ApiCoverageEntity> save() { - this.id = UUID.randomUUID().toString(); - this.updated = new Date(); - return ofy().save().entity(this).now(); - } - - /** - * Get List of ApiCoverageEntity by HAL interface name - */ - public static ApiCoverageEntity getByUrlSafeKey(String urlSafeKey) { - return ofy().load() - .type(ApiCoverageEntity.class) - .filterKey(com.google.cloud.datastore.Key.fromUrlSafe(urlSafeKey)) - .first() - .now(); - } - - /** - * Get List of ApiCoverageEntity by HAL interface name - */ - public static List<ApiCoverageEntity> getByInterfaceNameList(String halInterfaceName) { - return ofy().load() - .type(ApiCoverageEntity.class) - .filter("halInterfaceName", halInterfaceName) - .list(); - } - - /** - * Get List of ApiCoverageEntity by HAL package name - */ - public static List<ApiCoverageEntity> getByPackageNameList(String packageName) { - return ofy().load() - .type(ApiCoverageEntity.class) - .filter("halPackageName", packageName) - .list(); - } +public class ApiCoverageEntity implements DashboardEntity { + + /** ApiCoverageEntity id field */ + @Id @Getter @Setter String id; + + @Parent @Getter Key<?> parent; + + /** HAL package name. e.g. android.hardware.foo. */ + @Index @Getter @Setter String halPackageName; + + /** HAL (major) version. e.g. 1. */ + @Index @Getter @Setter int halMajorVersion; + + /** HAL (minor) version. e.g. 0. */ + @Index @Getter @Setter int halMinorVersion; + + /** HAL interface name. e.g. IFoo. */ + @Index @Getter @Setter String halInterfaceName; + + /** List of HAL API */ + @Getter @Setter List<String> halApi; + + /** List of HAL covered API */ + @Getter @Setter List<String> coveredHalApi; + + /** When this record was created or updated */ + @Index Date updated; + + /** Constructor function for ApiCoverageEntity Class */ + public ApiCoverageEntity( + com.google.appengine.api.datastore.Key testRunKey, + String halPackageName, + int halVersionMajor, + int halVersionMinor, + String halInterfaceName, + List<String> halApi, + List<String> coveredHalApi) { + this.id = UUID.randomUUID().toString(); + this.parent = getParentKey(testRunKey); + + this.halPackageName = halPackageName; + this.halMajorVersion = halVersionMajor; + this.halMinorVersion = halVersionMinor; + this.halInterfaceName = halInterfaceName; + this.halApi = halApi; + this.coveredHalApi = coveredHalApi; + this.updated = new Date(); + } + + /** Constructor function for ApiCoverageEntity Class with objectify Key. */ + public ApiCoverageEntity( + Key testRunKey, + String halPackageName, + int halVersionMajor, + int halVersionMinor, + String halInterfaceName, + List<String> halApi, + List<String> coveredHalApi) { + this.id = UUID.randomUUID().toString(); + this.parent = testRunKey; + + this.halPackageName = halPackageName; + this.halMajorVersion = halVersionMajor; + this.halMinorVersion = halVersionMinor; + this.halInterfaceName = halInterfaceName; + this.halApi = halApi; + this.coveredHalApi = coveredHalApi; + this.updated = new Date(); + } + + /** Get objectify Key from datastore Key type */ + private Key getParentKey(com.google.appengine.api.datastore.Key testRunKey) { + Key testParentKey = Key.create(TestEntity.class, testRunKey.getParent().getName()); + return Key.create(testParentKey, TestRunEntity.class, testRunKey.getId()); + } + + /** Get UrlSafeKey from ApiCoverageEntity Information */ + public String getUrlSafeKey() { + Key uuidKey = Key.create(this.parent, ApiCoverageEntity.class, this.id); + return uuidKey.toUrlSafe(); + } + + /** Saving function for the instance of this class */ + @Override + public Key<ApiCoverageEntity> save() { + this.id = UUID.randomUUID().toString(); + this.updated = new Date(); + return ofy().save().entity(this).now(); + } + + /** Get List of ApiCoverageEntity by HAL interface name */ + public static ApiCoverageEntity getByUrlSafeKey(String urlSafeKey) { + return ofy().load() + .type(ApiCoverageEntity.class) + .filterKey(com.google.cloud.datastore.Key.fromUrlSafe(urlSafeKey)) + .first() + .now(); + } + + /** Get List of ApiCoverageEntity by HAL interface name */ + public static List<ApiCoverageEntity> getByInterfaceNameList(String halInterfaceName) { + return ofy().load() + .type(ApiCoverageEntity.class) + .filter("halInterfaceName", halInterfaceName) + .list(); + } + + /** Get List of ApiCoverageEntity by HAL package name */ + public static List<ApiCoverageEntity> getByPackageNameList(String packageName) { + return ofy().load() + .type(ApiCoverageEntity.class) + .filter("halPackageName", packageName) + .list(); + } } diff --git a/src/main/java/com/android/vts/entity/ApiCoverageExcludedEntity.java b/src/main/java/com/android/vts/entity/ApiCoverageExcludedEntity.java index 834f8cc..61bd6a7 100644 --- a/src/main/java/com/android/vts/entity/ApiCoverageExcludedEntity.java +++ b/src/main/java/com/android/vts/entity/ApiCoverageExcludedEntity.java @@ -28,11 +28,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.util.Collection; import java.util.Date; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; import static com.googlecode.objectify.ObjectifyService.ofy; @@ -46,10 +43,7 @@ import static com.googlecode.objectify.ObjectifyService.ofy; @NoArgsConstructor @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) @JsonIgnoreProperties({"id", "parent"}) -public class ApiCoverageExcludedEntity { - - // The maximum number of entity list size to insert datastore - private static final int maxNumEntitySize = 500; +public class ApiCoverageExcludedEntity implements DashboardEntity { /** ApiCoverageEntity id field */ @Id @Getter @Setter private String id; @@ -82,11 +76,12 @@ public class ApiCoverageExcludedEntity { String interfaceName, String apiName, String comment) { - + this.id = this.getObjectifyId(); this.packageName = packageName; this.interfaceName = interfaceName; this.apiName = apiName; this.comment = comment; + this.updated = new Date(); this.setVersions(version); } @@ -125,44 +120,14 @@ public class ApiCoverageExcludedEntity { } /** Saving function for the instance of this class */ + @Override public Key<ApiCoverageExcludedEntity> save() { - this.id = this.getObjectifyId(); - this.updated = new Date(); return ofy().save().entity(this).now(); } - /** Spliting a list based on a given size */ - public static <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int size) { - final AtomicInteger counter = new AtomicInteger(0); - return inputList - .stream() - .collect(Collectors.groupingBy(s -> counter.getAndIncrement() / size)) - .values(); - } - - /** Saving function with parameter of this entity List */ - public static void saveAll(List<ApiCoverageExcludedEntity> apiCoverageExcludedEntityList) { - List<ApiCoverageExcludedEntity> entityWithIdList = - apiCoverageExcludedEntityList - .stream() - .map( - entity -> { - entity.setId(entity.getObjectifyId()); - entity.setUpdated(new Date()); - return entity; - }) - .collect(Collectors.toList()); - - partitionBasedOnSize(entityWithIdList, maxNumEntitySize) - .stream() - .forEach( - entityList -> { - ofy().save().entities(entityList).now(); - }); - } - /** Get All Key List of ApiCoverageExcludedEntity */ public static List<Key<ApiCoverageExcludedEntity>> getAllKeyList() { return ofy().load().type(ApiCoverageExcludedEntity.class).keys().list(); } + } diff --git a/src/main/java/com/android/vts/entity/BranchEntity.java b/src/main/java/com/android/vts/entity/BranchEntity.java index fa3f7a5..1c9ea52 100644 --- a/src/main/java/com/android/vts/entity/BranchEntity.java +++ b/src/main/java/com/android/vts/entity/BranchEntity.java @@ -41,8 +41,6 @@ public class BranchEntity implements DashboardEntity { public static final String KIND = "Branch"; // The entity kind. - public Key key; // The key for the entity in the database. - @Id private String name; /** @@ -51,7 +49,11 @@ public class BranchEntity implements DashboardEntity { * @param branchName The name of the branch. */ public BranchEntity(String branchName) { - this.key = KeyFactory.createKey(KIND, branchName); + this.name = branchName; + } + + public Key getKey() { + return KeyFactory.createKey(KIND, this.name); } /** find by branch name */ @@ -86,9 +88,10 @@ public class BranchEntity implements DashboardEntity { } } + /** Saving function for the instance of this class */ @Override - public Entity toEntity() { - return new Entity(this.key); + public com.googlecode.objectify.Key<BranchEntity> save() { + return ofy().save().entity(this).now(); } /** diff --git a/src/main/java/com/android/vts/entity/BuildTargetEntity.java b/src/main/java/com/android/vts/entity/BuildTargetEntity.java index b204d0c..4180213 100644 --- a/src/main/java/com/android/vts/entity/BuildTargetEntity.java +++ b/src/main/java/com/android/vts/entity/BuildTargetEntity.java @@ -41,8 +41,6 @@ public class BuildTargetEntity implements DashboardEntity { public static final String KIND = "BuildTarget"; // The entity kind. - public Key key; // The key for the entity in the database. - @Id private String name; /** @@ -51,12 +49,16 @@ public class BuildTargetEntity implements DashboardEntity { * @param targetName The name of the build target. */ public BuildTargetEntity(String targetName) { - this.key = KeyFactory.createKey(KIND, targetName); + this.name = targetName; } + public Key getKey() { + return KeyFactory.createKey(KIND, this.name); + } + /** Saving function for the instance of this class */ @Override - public Entity toEntity() { - return new Entity(this.key); + public com.googlecode.objectify.Key<BuildTargetEntity> save() { + return ofy().save().entity(this).now(); } /** find by Build Target Name */ diff --git a/src/main/java/com/android/vts/entity/CodeCoverageEntity.java b/src/main/java/com/android/vts/entity/CodeCoverageEntity.java index 63034ef..2a46b1f 100644 --- a/src/main/java/com/android/vts/entity/CodeCoverageEntity.java +++ b/src/main/java/com/android/vts/entity/CodeCoverageEntity.java @@ -16,13 +16,10 @@ package com.android.vts.entity; -import com.android.vts.util.UrlUtil; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.appengine.api.datastore.KeyFactory; -import com.google.gson.Gson; -import com.google.gson.JsonElement; import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Cache; @@ -35,10 +32,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.util.ArrayList; import java.util.Date; -import java.util.List; -import java.util.logging.Level; import java.util.logging.Logger; import static com.googlecode.objectify.ObjectifyService.ofy; @@ -50,7 +44,7 @@ import static com.googlecode.objectify.ObjectifyService.ofy; @NoArgsConstructor @JsonAutoDetect(fieldVisibility = Visibility.ANY) @JsonIgnoreProperties({"id", "parent"}) -public class CodeCoverageEntity { +public class CodeCoverageEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(CodeCoverageEntity.class.getName()); public static final String KIND = "CodeCoverage"; @@ -59,7 +53,7 @@ public class CodeCoverageEntity { public static final String TOTAL_LINE_COUNT = "totalLineCount"; /** CodeCoverageEntity id field */ - @Id @Getter @Setter long id; + @Id @Getter @Setter Long id; @Parent @Getter Key<?> parent; @@ -82,6 +76,20 @@ public class CodeCoverageEntity { this.totalLineCount = totalLineCount; } + /** Constructor function for ApiCoverageEntity Class */ + public CodeCoverageEntity( + long id, + com.google.appengine.api.datastore.Key testRunKey, + long coveredLineCount, + long totalLineCount) { + this.id = id; + + this.parent = getParentKey(testRunKey); + + this.coveredLineCount = coveredLineCount; + this.totalLineCount = totalLineCount; + } + /** Constructor function for ApiCoverageEntity Class with objectify key*/ public CodeCoverageEntity(Key testRunKey, long coveredLineCount, long totalLineCount) { this.parent = testRunKey; @@ -102,6 +110,7 @@ public class CodeCoverageEntity { } /** Saving function for the instance of this class */ + @Override public Key<CodeCoverageEntity> save() { this.id = this.getParent().getId(); this.updated = new Date(); diff --git a/src/main/java/com/android/vts/entity/CodeCoverageFileEntity.java b/src/main/java/com/android/vts/entity/CodeCoverageFileEntity.java index cb6d06c..fe4e8a0 100644 --- a/src/main/java/com/android/vts/entity/CodeCoverageFileEntity.java +++ b/src/main/java/com/android/vts/entity/CodeCoverageFileEntity.java @@ -37,11 +37,10 @@ import static com.googlecode.objectify.ObjectifyService.ofy; @Entity(name = "CodeCoverageFile") @EqualsAndHashCode(of = "id") @NoArgsConstructor -public class CodeCoverageFileEntity { +public class CodeCoverageFileEntity implements DashboardEntity { /** CodeCoverageFileEntity testName field */ - @Id - @Getter @Setter long id; + @Id @Getter @Setter Long id; @Parent @Getter @Setter private Key<?> coverageParent; @@ -94,8 +93,9 @@ public class CodeCoverageFileEntity { } /** Saving function for the instance of this class */ - public void save() { + @Override + public Key<CodeCoverageFileEntity> save() { this.isIgnored = false; - ofy().save().entity(this).now(); + return ofy().save().entity(this).now(); } } diff --git a/src/main/java/com/android/vts/entity/CoverageEntity.java b/src/main/java/com/android/vts/entity/CoverageEntity.java index 82b6690..50d2f4e 100644 --- a/src/main/java/com/android/vts/entity/CoverageEntity.java +++ b/src/main/java/com/android/vts/entity/CoverageEntity.java @@ -21,14 +21,11 @@ import static com.googlecode.objectify.ObjectifyService.ofy; import com.android.vts.proto.VtsReportMessage.CoverageReportMessage; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; -import com.google.cloud.datastore.PathElement; -import com.googlecode.objectify.LoadResult; import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.Parent; -import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; @@ -48,231 +45,268 @@ import lombok.Setter; @Data @NoArgsConstructor /** Object describing coverage data gathered for a file. */ -public class CoverageEntity implements Serializable { - - protected static final Logger logger = Logger.getLogger(CoverageEntity.class.getName()); - - public static final String KIND = "Coverage"; - - public static String GERRIT_URI; - - // Property keys - public static final String GROUP = "group"; - public static final String COVERED_LINE_COUNT = "coveredCount"; - public static final String TOTAL_LINE_COUNT = "totalCount"; - public static final String FILE_PATH = "filePath"; - public static final String PROJECT_NAME = "projectName"; - public static final String PROJECT_VERSION = "projectVersion"; - public static final String LINE_COVERAGE = "lineCoverage"; - - @Ignore - @Getter - @Setter - private Key parentKey; - - @Id - @Getter - @Setter - private Long id; - - @Parent - @Getter - @Setter - private com.googlecode.objectify.Key<?> testParent; - - @Index - @Getter - @Setter - private String group; - - @Getter - @Setter - private long coveredCount; - - @Getter - @Setter - private long totalCount; - - @Index - @Getter - @Setter - private String filePath; - - @Getter - @Setter - private String projectName; - - @Getter - @Setter - private String projectVersion; - - @Getter - @Setter - private List<Long> lineCoverage; - - /** - * CoverageEntity isIgnored field - */ - @Index - @Getter - @Setter - Boolean isIgnored; - - /** - * Create a CoverageEntity object for a file. - * - * @param parentKey The key to the parent TestRunEntity object in the database. - * @param group The group within the test run describing the coverage. - * @param coveredLineCount The total number of covered lines in the file. - * @param totalLineCount The total number of uncovered executable lines in the file. - * @param filePath The path to the file. - * @param projectName The name of the git project. - * @param projectVersion The commit hash of the project at the time the test was executed. - * @param lineCoverage List of coverage counts per executable line in the file. - */ - public CoverageEntity(Key parentKey, String group, long coveredLineCount, long totalLineCount, - String filePath, String projectName, String projectVersion, List<Long> lineCoverage) { - this.parentKey = parentKey; - this.group = group; - this.coveredCount = coveredLineCount; - this.totalCount = totalLineCount; - this.filePath = filePath; - this.projectName = projectName; - this.projectVersion = projectVersion; - this.lineCoverage = lineCoverage; - } - - /** - * find coverage entity by ID - */ - public static CoverageEntity findById(String testName, String testRunId, String id) { - com.googlecode.objectify.Key testKey = com.googlecode.objectify.Key - .create(TestEntity.class, testName); - com.googlecode.objectify.Key testRunKey = com.googlecode.objectify.Key - .create(testKey, TestRunEntity.class, Long.parseLong(testRunId)); - return ofy().load().type(CoverageEntity.class).parent(testRunKey).id(Long.parseLong(id)).now(); - } - - public static void setPropertyValues(Properties newSystemConfigProp) { - GERRIT_URI = newSystemConfigProp.getProperty("gerrit.uri"); - } - - /** - * Saving function for the instance of this class - */ - public void save() { - ofy().save().entity(this).now(); - } - - /** - * Get percentage from calculating coveredCount and totalCount values - */ - public Double getPercentage() { - return Math.round(coveredCount * 10000d / totalCount) / 100d; - } - - /** - * Get Gerrit Url function from the attributes of this class - */ - public String getGerritUrl() throws UnsupportedEncodingException { - String gerritPath = GERRIT_URI + "/projects/" + - URLEncoder.encode(projectName, "UTF-8") + "/commits/" + - URLEncoder.encode(projectVersion, "UTF-8") + "/files/" + - URLEncoder.encode(filePath, "UTF-8") + "/content"; - return gerritPath; - } - - /* Comparator for sorting the list by isIgnored field */ - public static Comparator<CoverageEntity> isIgnoredComparator = new Comparator<CoverageEntity>() { - - public int compare(CoverageEntity coverageEntity1, CoverageEntity coverageEntity2) { - Boolean isIgnored1 = - Objects.isNull(coverageEntity1.getIsIgnored()) ? false : coverageEntity1.getIsIgnored(); - Boolean isIgnored2 = - Objects.isNull(coverageEntity2.getIsIgnored()) ? false : coverageEntity2.getIsIgnored(); - - // ascending order - return isIgnored1.compareTo(isIgnored2); +public class CoverageEntity implements DashboardEntity { + + protected static final Logger logger = Logger.getLogger(CoverageEntity.class.getName()); + + public static final String KIND = "Coverage"; + + public static String GERRIT_URI; + + // Property keys + public static final String GROUP = "group"; + public static final String COVERED_LINE_COUNT = "coveredCount"; + public static final String TOTAL_LINE_COUNT = "totalCount"; + public static final String FILE_PATH = "filePath"; + public static final String PROJECT_NAME = "projectName"; + public static final String PROJECT_VERSION = "projectVersion"; + public static final String LINE_COVERAGE = "lineCoverage"; + + @Ignore @Getter @Setter private Key parentKey; + + @Id @Getter @Setter private Long id; + + @Parent @Getter @Setter private com.googlecode.objectify.Key<?> testParent; + + @Index @Getter @Setter private String group; + + @Getter @Setter private long coveredCount; + + @Getter @Setter private long totalCount; + + @Index @Getter @Setter private String filePath; + + @Getter @Setter private String projectName; + + @Getter @Setter private String projectVersion; + + @Getter @Setter private List<Long> lineCoverage; + + /** CoverageEntity isIgnored field */ + @Index @Getter @Setter Boolean isIgnored; + + /** + * Create a CoverageEntity object for a file. + * + * @param parentKey The key to the parent TestRunEntity object in the database. + * @param group The group within the test run describing the coverage. + * @param coveredLineCount The total number of covered lines in the file. + * @param totalLineCount The total number of uncovered executable lines in the file. + * @param filePath The path to the file. + * @param projectName The name of the git project. + * @param projectVersion The commit hash of the project at the time the test was executed. + * @param lineCoverage List of coverage counts per executable line in the file. + */ + public CoverageEntity( + Key parentKey, + String group, + long coveredLineCount, + long totalLineCount, + String filePath, + String projectName, + String projectVersion, + List<Long> lineCoverage) { + this.parentKey = parentKey; + this.group = group; + this.coveredCount = coveredLineCount; + this.totalCount = totalLineCount; + this.filePath = filePath; + this.projectName = projectName; + this.projectVersion = projectVersion; + this.lineCoverage = lineCoverage; } - }; - - public Entity toEntity() { - Entity coverageEntity = new Entity(KIND, parentKey); - coverageEntity.setProperty(GROUP, group); - coverageEntity.setUnindexedProperty(COVERED_LINE_COUNT, coveredCount); - coverageEntity.setUnindexedProperty(TOTAL_LINE_COUNT, totalCount); - coverageEntity.setProperty(FILE_PATH, filePath); - coverageEntity.setUnindexedProperty(PROJECT_NAME, projectName); - coverageEntity.setUnindexedProperty(PROJECT_VERSION, projectVersion); - if (lineCoverage != null && lineCoverage.size() > 0) { - coverageEntity.setUnindexedProperty(LINE_COVERAGE, lineCoverage); + + /** + * Create a CoverageEntity object for a file. + * + * @param testParent The objectify key to the parent TestRunEntity object in the database. + * @param group The group within the test run describing the coverage. + * @param coveredLineCount The total number of covered lines in the file. + * @param totalLineCount The total number of uncovered executable lines in the file. + * @param filePath The path to the file. + * @param projectName The name of the git project. + * @param projectVersion The commit hash of the project at the time the test was executed. + * @param lineCoverage List of coverage counts per executable line in the file. + */ + public CoverageEntity( + com.googlecode.objectify.Key testParent, + String group, + long coveredLineCount, + long totalLineCount, + String filePath, + String projectName, + String projectVersion, + List<Long> lineCoverage) { + this.testParent = testParent; + this.group = group; + this.coveredCount = coveredLineCount; + this.totalCount = totalLineCount; + this.filePath = filePath; + this.projectName = projectName; + this.projectVersion = projectVersion; + this.lineCoverage = lineCoverage; + } + + /** find coverage entity by ID */ + public static CoverageEntity findById(String testName, String testRunId, String id) { + com.googlecode.objectify.Key testKey = + com.googlecode.objectify.Key.create(TestEntity.class, testName); + com.googlecode.objectify.Key testRunKey = + com.googlecode.objectify.Key.create( + testKey, TestRunEntity.class, Long.parseLong(testRunId)); + return ofy().load() + .type(CoverageEntity.class) + .parent(testRunKey) + .id(Long.parseLong(id)) + .now(); + } + + public static void setPropertyValues(Properties newSystemConfigProp) { + GERRIT_URI = newSystemConfigProp.getProperty("gerrit.uri"); + } + + /** Saving function for the instance of this class */ + @Override + public com.googlecode.objectify.Key<CoverageEntity> save() { + return ofy().save().entity(this).now(); + } + + /** Get percentage from calculating coveredCount and totalCount values */ + public Double getPercentage() { + return Math.round(coveredCount * 10000d / totalCount) / 100d; } - return coverageEntity; - } - - /** - * Convert an Entity object to a CoverageEntity. - * - * @param e The entity to process. - * @return CoverageEntity object with the properties from e, or null if incompatible. - */ - @SuppressWarnings("unchecked") - public static CoverageEntity fromEntity(Entity e) { - if (!e.getKind().equals(KIND) || !e.hasProperty(GROUP) || !e.hasProperty(COVERED_LINE_COUNT) - || !e.hasProperty(TOTAL_LINE_COUNT) || !e.hasProperty(FILE_PATH) - || !e.hasProperty(PROJECT_NAME) || !e.hasProperty(PROJECT_VERSION)) { - logger.log(Level.WARNING, "Missing coverage attributes in entity: " + e.toString()); - return null; + + /** Get Gerrit Url function from the attributes of this class */ + public String getGerritUrl() throws UnsupportedEncodingException { + String gerritPath = + GERRIT_URI + + "/projects/" + + URLEncoder.encode(projectName, "UTF-8") + + "/commits/" + + URLEncoder.encode(projectVersion, "UTF-8") + + "/files/" + + URLEncoder.encode(filePath, "UTF-8") + + "/content"; + return gerritPath; } - try { - String group = (String) e.getProperty(GROUP); - long coveredLineCount = (long) e.getProperty(COVERED_LINE_COUNT); - long totalLineCount = (long) e.getProperty(TOTAL_LINE_COUNT); - String filePath = (String) e.getProperty(FILE_PATH); - String projectName = (String) e.getProperty(PROJECT_NAME); - String projectVersion = (String) e.getProperty(PROJECT_VERSION); - List<Long> lineCoverage; - if (e.hasProperty(LINE_COVERAGE)) { - lineCoverage = (List<Long>) e.getProperty(LINE_COVERAGE); - } else { - lineCoverage = new ArrayList<>(); - } - return new CoverageEntity(e.getKey().getParent(), group, coveredLineCount, - totalLineCount, filePath, projectName, projectVersion, lineCoverage); - } catch (ClassCastException exception) { - // Invalid contents or null values - logger.log(Level.WARNING, "Error parsing coverage entity.", exception); + + /* Comparator for sorting the list by isIgnored field */ + public static Comparator<CoverageEntity> isIgnoredComparator = + new Comparator<CoverageEntity>() { + + public int compare(CoverageEntity coverageEntity1, CoverageEntity coverageEntity2) { + Boolean isIgnored1 = + Objects.isNull(coverageEntity1.getIsIgnored()) + ? false + : coverageEntity1.getIsIgnored(); + Boolean isIgnored2 = + Objects.isNull(coverageEntity2.getIsIgnored()) + ? false + : coverageEntity2.getIsIgnored(); + + // ascending order + return isIgnored1.compareTo(isIgnored2); + } + }; + + public Entity toEntity() { + Entity coverageEntity = new Entity(KIND, parentKey); + coverageEntity.setProperty(GROUP, group); + coverageEntity.setUnindexedProperty(COVERED_LINE_COUNT, coveredCount); + coverageEntity.setUnindexedProperty(TOTAL_LINE_COUNT, totalCount); + coverageEntity.setProperty(FILE_PATH, filePath); + coverageEntity.setUnindexedProperty(PROJECT_NAME, projectName); + coverageEntity.setUnindexedProperty(PROJECT_VERSION, projectVersion); + if (lineCoverage != null && lineCoverage.size() > 0) { + coverageEntity.setUnindexedProperty(LINE_COVERAGE, lineCoverage); + } + return coverageEntity; } - return null; - } - - /** - * Convert a coverage report to a CoverageEntity. - * - * @param parentKey The ancestor key for the coverage entity. - * @param group The group to display the coverage report with. - * @param coverage The coverage report containing coverage data. - * @return The CoverageEntity for the coverage report message, or null if not compatible. - */ - public static CoverageEntity fromCoverageReport( - Key parentKey, String group, CoverageReportMessage coverage) { - if (!coverage.hasFilePath() || !coverage.hasProjectName() || !coverage.hasRevision() - || !coverage.hasTotalLineCount() || !coverage.hasCoveredLineCount()) { - return null; // invalid coverage report; + + /** + * Convert an Entity object to a CoverageEntity. + * + * @param e The entity to process. + * @return CoverageEntity object with the properties from e, or null if incompatible. + */ + @SuppressWarnings("unchecked") + public static CoverageEntity fromEntity(Entity e) { + if (!e.getKind().equals(KIND) + || !e.hasProperty(GROUP) + || !e.hasProperty(COVERED_LINE_COUNT) + || !e.hasProperty(TOTAL_LINE_COUNT) + || !e.hasProperty(FILE_PATH) + || !e.hasProperty(PROJECT_NAME) + || !e.hasProperty(PROJECT_VERSION)) { + logger.log(Level.WARNING, "Missing coverage attributes in entity: " + e.toString()); + return null; + } + try { + String group = (String) e.getProperty(GROUP); + long coveredLineCount = (long) e.getProperty(COVERED_LINE_COUNT); + long totalLineCount = (long) e.getProperty(TOTAL_LINE_COUNT); + String filePath = (String) e.getProperty(FILE_PATH); + String projectName = (String) e.getProperty(PROJECT_NAME); + String projectVersion = (String) e.getProperty(PROJECT_VERSION); + List<Long> lineCoverage; + if (e.hasProperty(LINE_COVERAGE)) { + lineCoverage = (List<Long>) e.getProperty(LINE_COVERAGE); + } else { + lineCoverage = new ArrayList<>(); + } + return new CoverageEntity( + e.getKey().getParent(), + group, + coveredLineCount, + totalLineCount, + filePath, + projectName, + projectVersion, + lineCoverage); + } catch (ClassCastException exception) { + // Invalid contents or null values + logger.log(Level.WARNING, "Error parsing coverage entity.", exception); + } + return null; } - long coveredLineCount = coverage.getCoveredLineCount(); - long totalLineCount = coverage.getTotalLineCount(); - String filePath = coverage.getFilePath().toStringUtf8(); - String projectName = coverage.getProjectName().toStringUtf8(); - String projectVersion = coverage.getRevision().toStringUtf8(); - List<Long> lineCoverage = null; - if (coverage.getLineCoverageVectorCount() > 0) { - lineCoverage = new ArrayList<>(); - for (long count : coverage.getLineCoverageVectorList()) { - lineCoverage.add(count); - } + + /** + * Convert a coverage report to a CoverageEntity. + * + * @param parentKey The ancestor key for the coverage entity. + * @param group The group to display the coverage report with. + * @param coverage The coverage report containing coverage data. + * @return The CoverageEntity for the coverage report message, or null if not compatible. + */ + public static CoverageEntity fromCoverageReport( + com.googlecode.objectify.Key parentKey, String group, CoverageReportMessage coverage) { + if (!coverage.hasFilePath() + || !coverage.hasProjectName() + || !coverage.hasRevision() + || !coverage.hasTotalLineCount() + || !coverage.hasCoveredLineCount()) { + return null; // invalid coverage report; + } + long coveredLineCount = coverage.getCoveredLineCount(); + long totalLineCount = coverage.getTotalLineCount(); + String filePath = coverage.getFilePath().toStringUtf8(); + String projectName = coverage.getProjectName().toStringUtf8(); + String projectVersion = coverage.getRevision().toStringUtf8(); + List<Long> lineCoverage = null; + if (coverage.getLineCoverageVectorCount() > 0) { + lineCoverage = new ArrayList<>(); + for (long count : coverage.getLineCoverageVectorList()) { + lineCoverage.add(count); + } + } + return new CoverageEntity( + parentKey, + group, + coveredLineCount, + totalLineCount, + filePath, + projectName, + projectVersion, + lineCoverage); } - return new CoverageEntity(parentKey, group, coveredLineCount, totalLineCount, filePath, - projectName, projectVersion, lineCoverage); - } } diff --git a/src/main/java/com/android/vts/entity/DashboardEntity.java b/src/main/java/com/android/vts/entity/DashboardEntity.java index 402a1e5..a42c1eb 100644 --- a/src/main/java/com/android/vts/entity/DashboardEntity.java +++ b/src/main/java/com/android/vts/entity/DashboardEntity.java @@ -16,14 +16,41 @@ package com.android.vts.entity; -import com.google.appengine.api.datastore.Entity; +import com.google.common.collect.Lists; +import com.googlecode.objectify.Key; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static com.googlecode.objectify.ObjectifyService.ofy; /** Interface for interacting with VTS Dashboard entities in Cloud Datastore. */ -public interface DashboardEntity { +public interface DashboardEntity extends Serializable { /** - * Serialize the DashboardEntity to an Entity object. + * Save the Entity to the datastore. * - * @return Entity object representing the properties defined in the DashboardEntity. + * @return The saved entity's key value. */ - public Entity toEntity(); + <T> Key<T> save(); + + /** Save List of entity through objectify entities method. */ + static <T> Map<Key<T>, T> saveAll(List<T> entityList, int maxEntitySize) { + return ofy().transact( + () -> { + List<List<T>> partitionedList = + Lists.partition(entityList, maxEntitySize); + return partitionedList + .stream() + .map( + subEntityList -> + ofy().save().entities(subEntityList).now()) + .flatMap(m -> m.entrySet().stream()) + .collect( + Collectors.toMap( + entry -> entry.getKey(), + entry -> entry.getValue())); + }); + } } diff --git a/src/main/java/com/android/vts/entity/DeviceInfoEntity.java b/src/main/java/com/android/vts/entity/DeviceInfoEntity.java index d0c3d00..2b98355 100644 --- a/src/main/java/com/android/vts/entity/DeviceInfoEntity.java +++ b/src/main/java/com/android/vts/entity/DeviceInfoEntity.java @@ -27,7 +27,6 @@ import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.Parent; -import java.io.Serializable; import java.util.List; import java.util.Objects; import java.util.logging.Level; @@ -44,7 +43,7 @@ import static com.googlecode.objectify.ObjectifyService.ofy; @Data @NoArgsConstructor /** Class describing a device used for a test run. */ -public class DeviceInfoEntity implements Serializable { +public class DeviceInfoEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(DeviceInfoEntity.class.getName()); /** This is the instance of App Engine memcache service java library */ @@ -64,8 +63,7 @@ public class DeviceInfoEntity implements Serializable { private Key parentKey; /** ID field using start timestamp */ - @Id - private long id; + @Id private Long id; /** parent field based on Test and TestRun key */ @Parent @@ -87,15 +85,6 @@ public class DeviceInfoEntity implements Serializable { private String abiName; - /* - public final String branch; - public final String product; - public final String buildFlavor; - public final String buildId; - public final String abiBitness; - public final String abiName; - */ - /** * Create a DeviceInfoEntity object. * @@ -215,8 +204,8 @@ public class DeviceInfoEntity implements Serializable { } /** Saving function for the instance of this class */ - public void save() { - ofy().save().entity(this).now(); + public com.googlecode.objectify.Key<DeviceInfoEntity> save() { + return ofy().save().entity(this).now(); } public Entity toEntity() { @@ -270,12 +259,12 @@ public class DeviceInfoEntity implements Serializable { /** * Convert a device info message to a DeviceInfoEntity. * - * @param parentKey The ancestor key for the device entity. + * @param parent The ancestor key for the device entity. * @param device The device info report describing the target Android device. * @return The DeviceInfoEntity for the target device, or null if incompatible */ public static DeviceInfoEntity fromDeviceInfoMessage( - Key parentKey, AndroidDeviceInfoMessage device) { + com.googlecode.objectify.Key parent, AndroidDeviceInfoMessage device) { if (!device.hasBuildAlias() || !device.hasBuildFlavor() || !device.hasProductVariant() || !device.hasBuildId()) { return null; @@ -287,7 +276,7 @@ public class DeviceInfoEntity implements Serializable { String abiBitness = device.getAbiBitness().toStringUtf8(); String abiName = device.getAbiName().toStringUtf8(); return new DeviceInfoEntity( - parentKey, branch, product, buildFlavor, buildId, abiBitness, abiName); + parent, branch, product, buildFlavor, buildId, abiBitness, abiName); } @Override @@ -312,10 +301,11 @@ public class DeviceInfoEntity implements Serializable { /** * Create a copy of the device info under a near parent. + * * @param parentKey The new parent key. * @return A copy of the DeviceInfoEntity with the specified parent. */ - public DeviceInfoEntity copyWithParent(Key parentKey) { + public DeviceInfoEntity copyWithParent(com.googlecode.objectify.Key parentKey) { return new DeviceInfoEntity(parentKey, this.branch, this.product, this.buildFlavor, this.buildId, this.abiBitness, this.abiName); } diff --git a/src/main/java/com/android/vts/entity/HalApiEntity.java b/src/main/java/com/android/vts/entity/HalApiEntity.java new file mode 100644 index 0000000..7fb0e6b --- /dev/null +++ b/src/main/java/com/android/vts/entity/HalApiEntity.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you + * may not use this file except in compliance with the License. You may + * obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.vts.entity; + +import static com.googlecode.objectify.ObjectifyService.ofy; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.googlecode.objectify.Key; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Entity; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Index; +import com.googlecode.objectify.annotation.Parent; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** Entity Class for HalApiEntity */ +@Cache +@Entity(name = "HalApiEntity") +@EqualsAndHashCode(of = "id") +@NoArgsConstructor +@JsonAutoDetect(fieldVisibility = Visibility.ANY) +@JsonIgnoreProperties({"id", "parent"}) +public class HalApiEntity implements DashboardEntity { + + /** HalApiEntity id field */ + @Id @Getter @Setter String id; + + @Parent @Getter Key<?> parent; + + /** HAL Api Release Level. e.g. */ + @Index @Getter @Setter String halApiReleaseLevel; + + /** HAL package name. e.g. android.hardware.foo. */ + @Index @Getter @Setter String halPackageName; + + /** HAL (major) version. e.g. 1. */ + @Index @Getter @Setter int halVersionMajor; + + /** HAL (minor) version. e.g. 0. */ + @Index @Getter @Setter int halVersionMinor; + + /** HAL interface name. e.g. IFoo. */ + @Index @Getter @Setter String halInterfaceName; + + /** List of HAL API */ + @Getter @Setter List<String> halApi; + + /** List of HAL covered API */ + @Getter @Setter List<String> coveredHalApi; + + /** When this record was created or updated */ + @Index Date updated; + + /** Constructor function for HalApiEntity Class */ + public HalApiEntity( + com.googlecode.objectify.Key testRunKey, + String halApiReleaseLevel, + String halPackageName, + int halVersionMajor, + int halVersionMinor, + String halInterfaceName, + List<String> halApi, + List<String> coveredHalApi) { + + this.id = UUID.randomUUID().toString(); + this.parent = testRunKey; + + this.halApiReleaseLevel = halApiReleaseLevel; + this.halPackageName = halPackageName; + this.halVersionMajor = halVersionMajor; + this.halVersionMinor = halVersionMinor; + this.halInterfaceName = halInterfaceName; + this.halApi = halApi; + this.coveredHalApi = coveredHalApi; + } + + /** Saving function for the instance of this class */ + @Override + public Key<HalApiEntity> save() { + return ofy().save().entity(this).now(); + } +} diff --git a/src/main/java/com/android/vts/entity/ProfilingPointEntity.java b/src/main/java/com/android/vts/entity/ProfilingPointEntity.java index 741a5a7..ac2994c 100644 --- a/src/main/java/com/android/vts/entity/ProfilingPointEntity.java +++ b/src/main/java/com/android/vts/entity/ProfilingPointEntity.java @@ -25,21 +25,20 @@ import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; -import java.io.Serializable; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; + +import static com.googlecode.objectify.ObjectifyService.ofy; @com.googlecode.objectify.annotation.Entity(name = "ProfilingPoint") @Cache @Data @NoArgsConstructor /** Entity describing a profiling point. */ -public class ProfilingPointEntity implements Serializable { +public class ProfilingPointEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(ProfilingPointEntity.class.getName()); protected static final String DELIMITER = "#"; @@ -141,6 +140,12 @@ public class ProfilingPointEntity implements Serializable { return KeyFactory.createKey(KIND, testName + DELIMITER + profilingPointName); } + /** Saving function for the instance of this class */ + @Override + public com.googlecode.objectify.Key<ProfilingPointEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity profilingPoint = new Entity(key); profilingPoint.setIndexedProperty(TEST_NAME, this.testName); diff --git a/src/main/java/com/android/vts/entity/ProfilingPointRunEntity.java b/src/main/java/com/android/vts/entity/ProfilingPointRunEntity.java index 2010971..48df727 100644 --- a/src/main/java/com/android/vts/entity/ProfilingPointRunEntity.java +++ b/src/main/java/com/android/vts/entity/ProfilingPointRunEntity.java @@ -27,22 +27,21 @@ import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Parent; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; + +import static com.googlecode.objectify.ObjectifyService.ofy; @com.googlecode.objectify.annotation.Entity(name = "ProfilingPointRun") @Cache @Data @NoArgsConstructor /** Entity describing a profiling point execution. */ -public class ProfilingPointRunEntity implements Serializable { +public class ProfilingPointRunEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(ProfilingPointRunEntity.class.getName()); @@ -94,7 +93,7 @@ public class ProfilingPointRunEntity implements Serializable { /** * Create a ProfilingPointRunEntity object. * - * @param parentKey The Key object for the parent TestRunEntity in the database. + * @param parentKey The Key object for the parent TestRunEntity in datastore. * @param name The name of the profiling point. * @param type The (number) type of the profiling point data. * @param regressionMode The (number) mode to use for detecting regression. @@ -125,6 +124,41 @@ public class ProfilingPointRunEntity implements Serializable { this.options = options; } + + /** + * Create a ProfilingPointRunEntity object. + * + * @param parent The objectify Key for the parent TestRunEntity in datastore. + * @param name The name of the profiling point. + * @param type The (number) type of the profiling point data. + * @param regressionMode The (number) mode to use for detecting regression. + * @param labels List of data labels, or null if the data is unlabeled. + * @param values List of data values. + * @param xLabel The x axis label. + * @param yLabel The y axis label. + * @param options The list of key=value options for the profiling point run. + */ + public ProfilingPointRunEntity( + com.googlecode.objectify.Key parent, + String name, + int type, + int regressionMode, + List<String> labels, + List<Long> values, + String xLabel, + String yLabel, + List<String> options) { + this.parent = parent; + this.name = name; + this.type = type; + this.regressionMode = regressionMode; + this.labels = labels == null ? null : new ArrayList<>(labels); + this.values = new ArrayList<>(values); + this.xLabel = xLabel; + this.yLabel = yLabel; + this.options = options; + } + /** * Get VtsProfilingType from int value. * @@ -143,6 +177,12 @@ public class ProfilingPointRunEntity implements Serializable { return VtsProfilingRegressionMode.forNumber(regressionMode); } + /** Saving function for the instance of this class */ + @Override + public com.googlecode.objectify.Key<ProfilingPointRunEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity profilingRun = new Entity(this.key); profilingRun.setUnindexedProperty(TYPE, this.type); @@ -207,12 +247,12 @@ public class ProfilingPointRunEntity implements Serializable { /** * Convert a coverage report to a CoverageEntity. * - * @param parentKey The ancestor key for the coverage entity. + * @param parent The ancestor objectify key for the coverage entity. * @param profilingReport The profiling report containing profiling data. * @return The ProfilingPointRunEntity for the profiling report message, or null if incompatible */ public static ProfilingPointRunEntity fromProfilingReport( - Key parentKey, ProfilingReportMessage profilingReport) { + com.googlecode.objectify.Key parent, ProfilingReportMessage profilingReport) { if (!profilingReport.hasName() || !profilingReport.hasType() || profilingReport.getType() == VtsProfilingType.UNKNOWN_VTS_PROFILING_TYPE @@ -265,7 +305,7 @@ public class ProfilingPointRunEntity implements Serializable { } } return new ProfilingPointRunEntity( - parentKey, + parent, name, type.getNumber(), regressionMode.getNumber(), diff --git a/src/main/java/com/android/vts/entity/ProfilingPointSummaryEntity.java b/src/main/java/com/android/vts/entity/ProfilingPointSummaryEntity.java index f426707..e4a1911 100644 --- a/src/main/java/com/android/vts/entity/ProfilingPointSummaryEntity.java +++ b/src/main/java/com/android/vts/entity/ProfilingPointSummaryEntity.java @@ -25,7 +25,6 @@ import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; -import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -33,16 +32,16 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; + +import static com.googlecode.objectify.ObjectifyService.ofy; @com.googlecode.objectify.annotation.Entity(name = "ProfilingPointSummary") @Cache @Data @NoArgsConstructor /** Entity describing a profiling point summary. */ -public class ProfilingPointSummaryEntity implements Serializable { +public class ProfilingPointSummaryEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(ProfilingPointSummaryEntity.class.getName()); protected static final String DELIMITER = "#"; @@ -237,6 +236,12 @@ public class ProfilingPointSummaryEntity implements Serializable { } } + /** Saving function for the instance of this class */ + @Override + public com.googlecode.objectify.Key<ProfilingPointSummaryEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity profilingSummary; profilingSummary = new Entity(this.key); diff --git a/src/main/java/com/android/vts/entity/RoleEntity.java b/src/main/java/com/android/vts/entity/RoleEntity.java index d001cfa..508a9ca 100644 --- a/src/main/java/com/android/vts/entity/RoleEntity.java +++ b/src/main/java/com/android/vts/entity/RoleEntity.java @@ -6,49 +6,38 @@ import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; -import com.googlecode.objectify.annotation.Index; -import com.googlecode.objectify.annotation.Load; -import java.io.Serializable; -import java.util.ArrayList; import java.util.Date; -import java.util.List; -import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; - @Cache @Entity @EqualsAndHashCode(of = "role") @NoArgsConstructor -public class RoleEntity implements Serializable { - - private static final long serialVersionUID = 1L; - - @Id - private String role; - - /** When this record was created or updated */ - @Getter - Date updated; - - /** Construction function for UserEntity Class */ - public RoleEntity(String roleName) { - this.role = roleName; - } - - /** Get role by email */ - public static RoleEntity getRole(String role) { - return ofy().load() - .type(RoleEntity.class) - .id(role) - .now(); - } - - /** Saving function for the instance of this class */ - public void save() { - this.updated = new Date(); - ofy().save().entity(this).now(); - } -}
\ No newline at end of file +public class RoleEntity implements DashboardEntity { + + private static final long serialVersionUID = 1L; + + @Id private String role; + + /** When this record was created or updated */ + @Getter Date updated; + + /** Construction function for UserEntity Class */ + public RoleEntity(String roleName) { + this.role = roleName; + } + + /** Get role by email */ + public static RoleEntity getRole(String role) { + return ofy().load().type(RoleEntity.class).id(role).now(); + } + + /** Saving function for the instance of this class */ + @Override + public Key<RoleEntity> save() { + this.updated = new Date(); + return ofy().save().entity(this).now(); + } +} diff --git a/src/main/java/com/android/vts/entity/TestAcknowledgmentEntity.java b/src/main/java/com/android/vts/entity/TestAcknowledgmentEntity.java index 66b56b8..a594f85 100644 --- a/src/main/java/com/android/vts/entity/TestAcknowledgmentEntity.java +++ b/src/main/java/com/android/vts/entity/TestAcknowledgmentEntity.java @@ -26,6 +26,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.google.gson.reflect.TypeToken; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Id; +import com.googlecode.objectify.annotation.Ignore; +import com.googlecode.objectify.annotation.Index; +import lombok.Data; + import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashSet; @@ -35,6 +41,11 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import static com.googlecode.objectify.ObjectifyService.ofy; + +@com.googlecode.objectify.annotation.Entity(name = "TestAcknowledgment") +@Cache +@Data /** Entity describing a test failure acknowledgment. */ public class TestAcknowledgmentEntity implements DashboardEntity { protected static final Logger logger = @@ -44,21 +55,27 @@ public class TestAcknowledgmentEntity implements DashboardEntity { public static final String KEY = "key"; public static final String TEST_KEY = "testKey"; public static final String TEST_NAME = "testName"; - public static final String USER = "user"; + public static final String USER_OBJ = "userObj"; public static final String CREATED = "created"; public static final String BRANCHES = "branches"; public static final String DEVICES = "devices"; public static final String TEST_CASE_NAMES = "testCaseNames"; public static final String NOTE = "note"; - private final Key key; - private final long created; - public final Key test; - public final User user; - public final Set<String> branches; - public final Set<String> devices; - public final Set<String> testCaseNames; - public final String note; + @Ignore private final Key key; + @Ignore public final Key test; + @Ignore public final User userObj; + + @Id private Long id; + + private com.googlecode.objectify.Key testKey; + private Set<String> branches; + private Set<String> devices; + private Set<String> testCaseNames; + private String note; + private String user; + + @Index private final long created; /** * Create a AcknowledgmentEntity object. @@ -66,11 +83,11 @@ public class TestAcknowledgmentEntity implements DashboardEntity { * @param key The key of the AcknowledgmentEntity in the database. * @param created The timestamp when the entity was created (in microseconds). * @param test The key of the test. - * @param user The user who created or last modified the entity. + * @param userObj The user who created or last modified the entity. * @param branches The list of branch names for which the acknowledgment applies (or null if * all). - * @param devices The list of device build flavors for which the acknowledgment applies (or - * null if all). + * @param devices The list of device build flavors for which the acknowledgment applies (or null + * if all). * @param testCaseNames The list of test case names known to fail (or null if all). * @param note A text blob with details about the failure (or null if all). */ @@ -78,13 +95,13 @@ public class TestAcknowledgmentEntity implements DashboardEntity { Key key, long created, Key test, - User user, + User userObj, List<String> branches, List<String> devices, List<String> testCaseNames, Text note) { this.test = test; - this.user = user; + this.userObj = userObj; if (branches != null) this.branches = new HashSet(branches); else this.branches = new HashSet<>(); @@ -105,32 +122,37 @@ public class TestAcknowledgmentEntity implements DashboardEntity { * Create a AcknowledgmentEntity object. * * @param test The key of the test. - * @param user The user who created or last modified the entity. + * @param userObj The user who created or last modified the entity. * @param branches The list of branch names for which the acknowledgment applies (or null if * all). - * @param devices The list of device build flavors for which the acknowledgment applies (or - * null if all). + * @param devices The list of device build flavors for which the acknowledgment applies (or null + * if all). * @param testCaseNames The list of test case names known to fail (or null if all). * @param note A text blob with details about the failure (or null if all). */ public TestAcknowledgmentEntity( Key test, - User user, + User userObj, List<String> branches, List<String> devices, List<String> testCaseNames, Text note) { - this(null, -1, test, user, branches, devices, testCaseNames, note); + this(null, -1, test, userObj, branches, devices, testCaseNames, note); } + /** Saving function for the instance of this class */ @Override + public com.googlecode.objectify.Key<TestAcknowledgmentEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity ackEntity; if (this.key == null) ackEntity = new Entity(KIND); else ackEntity = new Entity(key); ackEntity.setProperty(TEST_KEY, this.test); - ackEntity.setProperty(USER, this.user); + ackEntity.setProperty(USER_OBJ, this.userObj); long created = this.created; if (created < 0) created = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis()); @@ -159,7 +181,7 @@ public class TestAcknowledgmentEntity implements DashboardEntity { public static TestAcknowledgmentEntity fromEntity(Entity e) { if (!e.getKind().equals(KIND) || !e.hasProperty(TEST_KEY) - || !e.hasProperty(USER) + || !e.hasProperty(USER_OBJ) || !e.hasProperty(CREATED)) { logger.log( Level.WARNING, "Missing attributes in acknowledgment entity: " + e.toString()); @@ -167,7 +189,7 @@ public class TestAcknowledgmentEntity implements DashboardEntity { } try { Key test = (Key) e.getProperty(TEST_KEY); - User user = (User) e.getProperty(USER); + User user = (User) e.getProperty(USER_OBJ); long created = (long) e.getProperty(CREATED); List<String> branches; @@ -247,7 +269,7 @@ public class TestAcknowledgmentEntity implements DashboardEntity { JsonObject json = new JsonObject(); json.add(KEY, new JsonPrimitive(KeyFactory.keyToString(this.key))); json.add(TEST_NAME, new JsonPrimitive(this.test.getName())); - json.add(USER, new JsonPrimitive(this.user.getEmail())); + json.add(USER_OBJ, new JsonPrimitive(this.userObj.getEmail())); json.add(CREATED, new JsonPrimitive(this.created)); List<JsonElement> branches = new ArrayList<>(); diff --git a/src/main/java/com/android/vts/entity/TestCaseRunEntity.java b/src/main/java/com/android/vts/entity/TestCaseRunEntity.java index 6d3ba83..30776d4 100644 --- a/src/main/java/com/android/vts/entity/TestCaseRunEntity.java +++ b/src/main/java/com/android/vts/entity/TestCaseRunEntity.java @@ -24,17 +24,17 @@ import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.OnLoad; import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import static com.googlecode.objectify.ObjectifyService.ofy; @com.googlecode.objectify.annotation.Entity(name = "TestCaseRun") @Cache @Data +@Slf4j /** Entity describing the execution of a test case. */ public class TestCaseRunEntity implements DashboardEntity { - protected static final Logger logger = Logger.getLogger(TestCaseRunEntity.class.getName()); public static final String KIND = "TestCaseRun"; @@ -89,7 +89,8 @@ public class TestCaseRunEntity implements DashboardEntity { * Create a TestCaseRunEntity. */ public TestCaseRunEntity() { - this.id = -1L; + this.results = new ArrayList<>(); + this.testCaseNames = new ArrayList<>(); this.testCases = new ArrayList<>(); this.systraceUrl = null; } @@ -100,6 +101,8 @@ public class TestCaseRunEntity implements DashboardEntity { */ public TestCaseRunEntity(long id) { this.id = id; + this.results = new ArrayList<>(); + this.testCaseNames = new ArrayList<>(); this.testCases = new ArrayList<>(); this.systraceUrl = null; } @@ -147,13 +150,21 @@ public class TestCaseRunEntity implements DashboardEntity { * @return true if added, false otherwise. */ public boolean addTestCase(String name, int result) { - if (isFull()) + if (this.isFull()) { return false; - this.testCases.add(new TestCase(this.id, this.testCases.size(), name, result)); - return true; + } else { + this.testCaseNames.add(name); + this.results.add(result); + return true; + } } + /** Saving function for the instance of this class */ @Override + public com.googlecode.objectify.Key<TestCaseRunEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity testCaseRunEntity; if (this.id >= 0) { @@ -188,7 +199,7 @@ public class TestCaseRunEntity implements DashboardEntity { @SuppressWarnings("unchecked") public static TestCaseRunEntity fromEntity(Entity e) { if (!e.getKind().equals(KIND)) { - logger.log(Level.WARNING, "Wrong kind: " + e.getKey()); + log.warn("Wrong kind: " + e.getKey()); return null; } try { @@ -213,7 +224,7 @@ public class TestCaseRunEntity implements DashboardEntity { return testCaseRun; } catch (ClassCastException exception) { // Invalid cast - logger.log(Level.WARNING, "Error parsing test case run entity.", exception); + log.warn("Error parsing test case run entity.", exception); } return null; } diff --git a/src/main/java/com/android/vts/entity/TestCoverageStatusEntity.java b/src/main/java/com/android/vts/entity/TestCoverageStatusEntity.java index cc630c3..1156cc7 100644 --- a/src/main/java/com/android/vts/entity/TestCoverageStatusEntity.java +++ b/src/main/java/com/android/vts/entity/TestCoverageStatusEntity.java @@ -23,7 +23,6 @@ import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Index; -import java.io.Serializable; import java.util.Collection; import java.util.Date; import java.util.List; @@ -42,7 +41,7 @@ import lombok.Setter; @Cache @NoArgsConstructor /** Entity describing test coverage status. */ -public class TestCoverageStatusEntity implements Serializable { +public class TestCoverageStatusEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(TestCoverageStatusEntity.class.getName()); @@ -190,9 +189,10 @@ public class TestCoverageStatusEntity implements Serializable { } /** Saving function for the instance of this class */ - public void save() { + @Override + public Key<TestCoverageStatusEntity> save() { this.updatedDate = new Date(); - ofy().save().entity(this).now(); + return ofy().save().entity(this).now(); } public Entity toEntity() { diff --git a/src/main/java/com/android/vts/entity/TestEntity.java b/src/main/java/com/android/vts/entity/TestEntity.java index e48d759..4df7fb0 100644 --- a/src/main/java/com/android/vts/entity/TestEntity.java +++ b/src/main/java/com/android/vts/entity/TestEntity.java @@ -24,7 +24,6 @@ import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Index; -import java.io.Serializable; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -34,12 +33,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -@Entity(name="Test") +@Entity(name = "Test") @Cache @Data @NoArgsConstructor /** Entity describing test metadata. */ -public class TestEntity implements Serializable { +public class TestEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(TestEntity.class.getName()); public static final String KIND = "Test"; @@ -75,6 +74,12 @@ public class TestEntity implements Serializable { this(testName, false); } + /** Saving function for the instance of this class */ + @Override + public com.googlecode.objectify.Key<TestEntity> save() { + return ofy().save().entity(this).now(); + } + public com.google.appengine.api.datastore.Entity toEntity() { com.google.appengine.api.datastore.Entity testEntity = new com.google.appengine.api.datastore.Entity(this.getOldKey()); testEntity.setProperty(HAS_PROFILING_DATA, this.hasProfilingData); @@ -82,6 +87,19 @@ public class TestEntity implements Serializable { } /** + * Get objectify TestRun Entity's key. + * + * @param startTimestamp test start timestamp + */ + public com.googlecode.objectify.Key getTestRunKey(long startTimestamp) { + com.googlecode.objectify.Key testKey = + com.googlecode.objectify.Key.create(TestEntity.class, this.getTestName()); + com.googlecode.objectify.Key testRunKey = + com.googlecode.objectify.Key.create(testKey, TestRunEntity.class, startTimestamp); + return testRunKey; + } + + /** * Get key info from appengine based library. */ public Key getOldKey() { @@ -130,10 +148,4 @@ public class TestEntity implements Serializable { } return new TestEntity(testName, hasProfilingData); } - - /** Saving function for the instance of this class */ - public void save() { - ofy().save().entity(this).now(); - } - } diff --git a/src/main/java/com/android/vts/entity/TestPlanEntity.java b/src/main/java/com/android/vts/entity/TestPlanEntity.java index 805c3cd..590db46 100644 --- a/src/main/java/com/android/vts/entity/TestPlanEntity.java +++ b/src/main/java/com/android/vts/entity/TestPlanEntity.java @@ -19,21 +19,20 @@ package com.android.vts.entity; import static com.googlecode.objectify.ObjectifyService.ofy; import com.google.appengine.api.datastore.Entity; +import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; -import java.io.Serializable; -import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; import lombok.Data; import lombok.NoArgsConstructor; -@com.googlecode.objectify.annotation.Entity(name="TestPlan") +@com.googlecode.objectify.annotation.Entity(name = "TestPlan") @Cache @Data @NoArgsConstructor /** Entity describing test plan metadata. */ -public class TestPlanEntity implements Serializable { +public class TestPlanEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(TestPlanEntity.class.getName()); public static final String KIND = "TestPlan"; @@ -58,6 +57,11 @@ public class TestPlanEntity implements Serializable { return planEntity; } + public Key getKey() { + Key key = Key.create(TestPlanEntity.class, this.testPlanName); + return key; + } + /** * Convert an Entity object to a TestEntity. * @@ -76,7 +80,8 @@ public class TestPlanEntity implements Serializable { } /** Saving function for the instance of this class */ - public void save() { - ofy().save().entity(this).now(); + @Override + public com.googlecode.objectify.Key<TestPlanEntity> save() { + return ofy().save().entity(this).now(); } } diff --git a/src/main/java/com/android/vts/entity/TestPlanRunEntity.java b/src/main/java/com/android/vts/entity/TestPlanRunEntity.java index 7dbb0dc..de2e505 100644 --- a/src/main/java/com/android/vts/entity/TestPlanRunEntity.java +++ b/src/main/java/com/android/vts/entity/TestPlanRunEntity.java @@ -18,7 +18,6 @@ package com.android.vts.entity; import static com.googlecode.objectify.ObjectifyService.ofy; -import com.android.vts.entity.TestRunEntity.TestRunType; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.KeyFactory; @@ -32,25 +31,21 @@ import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.Parent; -import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.Objects; -import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import lombok.Data; -import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; @com.googlecode.objectify.annotation.Entity(name = "TestPlanRun") @Cache @Data @NoArgsConstructor /** Entity describing test plan run information. */ -public class TestPlanRunEntity implements Serializable { +public class TestPlanRunEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(TestPlanRunEntity.class.getName()); @@ -76,7 +71,7 @@ public class TestPlanRunEntity implements Serializable { @Id private Long id; - @Parent private com.googlecode.objectify.Key<TestPlanEntity> testParent; + @Parent private com.googlecode.objectify.Key<TestPlanEntity> parent; @Index private String testPlanName; @@ -98,7 +93,7 @@ public class TestPlanRunEntity implements Serializable { @Ignore private List<Key> oldTestRuns; - private List<com.googlecode.objectify.Key<?>> testRuns; + private List<com.googlecode.objectify.Key<TestRunEntity>> testRuns; /** When this record was created or updated */ @Index Date updated; @@ -106,7 +101,7 @@ public class TestPlanRunEntity implements Serializable { /** * Create a TestPlanRunEntity object describing a test plan run. * - * @param parentKey The key for the parent entity in the database. + * @param testPlanKey The key for the parent entity in the database. * @param type The test run type (e.g. presubmit, postsubmit, other) * @param startTimestamp The time in microseconds when the test plan run started. * @param endTimestamp The time in microseconds when the test plan run ended. @@ -116,7 +111,7 @@ public class TestPlanRunEntity implements Serializable { * @param testRuns A list of keys to the TestRunEntity objects for the plan run run. */ public TestPlanRunEntity( - Key parentKey, + Key testPlanKey, String testPlanName, long type, long startTimestamp, @@ -127,7 +122,8 @@ public class TestPlanRunEntity implements Serializable { long totalApiCount, long coveredApiCount, List<Key> testRuns) { - this.key = KeyFactory.createKey(parentKey, KIND, startTimestamp); + this.id = startTimestamp; + this.key = KeyFactory.createKey(testPlanKey, KIND, startTimestamp); this.testPlanName = testPlanName; this.type = type; this.startTimestamp = startTimestamp; @@ -152,6 +148,44 @@ public class TestPlanRunEntity implements Serializable { .collect(Collectors.toList()); } + /** + * Create a TestPlanRunEntity object describing a test plan run. + * + * @param testPlanKey The key for the parent entity in the database. + * @param type The test run type (e.g. presubmit, postsubmit, other) + * @param startTimestamp The time in microseconds when the test plan run started. + * @param endTimestamp The time in microseconds when the test plan run ended. + * @param testBuildId The build ID of the VTS test build. + * @param passCount The number of passing test cases in the run. + * @param failCount The number of failing test cases in the run. + * @param testRuns A list of keys to the TestRunEntity objects for the plan run run. + */ + public TestPlanRunEntity( + com.googlecode.objectify.Key<TestPlanEntity> testPlanKey, + String testPlanName, + long type, + long startTimestamp, + long endTimestamp, + String testBuildId, + long passCount, + long failCount, + long totalApiCount, + long coveredApiCount, + List<com.googlecode.objectify.Key<TestRunEntity>> testRuns) { + this.id = startTimestamp; + this.parent = testPlanKey; + this.testPlanName = testPlanName; + this.type = type; + this.startTimestamp = startTimestamp; + this.endTimestamp = endTimestamp; + this.testBuildId = testBuildId; + this.passCount = passCount; + this.failCount = failCount; + this.totalApiCount = totalApiCount; + this.coveredApiCount = coveredApiCount; + this.testRuns = testRuns; + } + public Entity toEntity() { Entity planRun = new Entity(this.key); planRun.setProperty(TEST_PLAN_NAME, this.testPlanName); @@ -168,6 +202,7 @@ public class TestPlanRunEntity implements Serializable { } /** Saving function for the instance of this class */ + @Override public com.googlecode.objectify.Key<TestPlanRunEntity> save() { this.updated = new Date(); return ofy().save().entity(this).now(); @@ -175,12 +210,7 @@ public class TestPlanRunEntity implements Serializable { /** Get UrlSafeKey from this class */ public String getUrlSafeKey() { - com.googlecode.objectify.Key testPlanKey = - com.googlecode.objectify.Key.create(TestPlanEntity.class, this.testPlanName); - com.googlecode.objectify.Key idKey = - com.googlecode.objectify.Key.create( - testPlanKey, TestPlanRunEntity.class, this.startTimestamp); - return idKey.toUrlSafe(); + return this.getOfyKey().toUrlSafe(); } /** Add a task to calculate the total number of coverage API */ @@ -191,7 +221,7 @@ public class TestPlanRunEntity implements Serializable { Queue queue = QueueFactory.getQueue(QUEUE_NAME); queue.add( TaskOptions.Builder.withUrl(COVERAGE_API_URL) - .param("urlSafeKey", String.valueOf(this.getUrlSafeKey())) + .param("urlSafeKey", this.getUrlSafeKey()) .method(TaskOptions.Method.POST)); } } @@ -205,6 +235,12 @@ public class TestPlanRunEntity implements Serializable { return KeyFactory.createKey(parentKey, KIND, startTimestamp); } + /** Get key info from objecitfy library. */ + public com.googlecode.objectify.Key getOfyKey() { + return com.googlecode.objectify.Key.create( + this.parent, TestPlanRunEntity.class, this.startTimestamp); + } + /** * Convert an Entity object to a TestPlanRunEntity. * diff --git a/src/main/java/com/android/vts/entity/TestRunEntity.java b/src/main/java/com/android/vts/entity/TestRunEntity.java index bdd0ac8..0d5f1ec 100644 --- a/src/main/java/com/android/vts/entity/TestRunEntity.java +++ b/src/main/java/com/android/vts/entity/TestRunEntity.java @@ -35,9 +35,7 @@ import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; import com.googlecode.objectify.annotation.OnLoad; import com.googlecode.objectify.annotation.Parent; -import java.io.Serializable; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; @@ -45,20 +43,17 @@ import java.util.Optional; import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.stream.Collectors; import java.util.stream.Stream; -import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.apache.commons.lang3.math.NumberUtils; -import org.json.JSONArray; @com.googlecode.objectify.annotation.Entity(name = "TestRun") @Cache @NoArgsConstructor /** Entity describing test run information. */ -public class TestRunEntity implements Serializable { +public class TestRunEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(TestRunEntity.class.getName()); /** Enum for classifying test run types. */ @@ -168,7 +163,7 @@ public class TestRunEntity implements Serializable { @Index @Getter @Setter private boolean hasCodeCoverage; - private com.googlecode.objectify.Key<CodeCoverageEntity> codeCoverageEntityKey; + @Ignore private com.googlecode.objectify.Key<CodeCoverageEntity> codeCoverageEntityKey; @Index @Getter @Setter private long coveredLineCount; @@ -202,6 +197,7 @@ public class TestRunEntity implements Serializable { boolean hasCodeCoverage, List<Long> testCaseIds, List<String> logLinks) { + this.id = startTimestamp; this.key = KeyFactory.createKey(parentKey, KIND, startTimestamp); this.type = type; this.startTimestamp = startTimestamp; @@ -212,9 +208,11 @@ public class TestRunEntity implements Serializable { this.failCount = failCount; this.hasCodeCoverage = hasCodeCoverage; this.testName = parentKey.getName(); - this.codeCoverageEntityKey = getCodeCoverageEntityKey(); this.testCaseIds = testCaseIds; this.logLinks = logLinks; + + this.testRunParent = com.googlecode.objectify.Key.create(TestEntity.class, testName); + this.codeCoverageEntityKey = getCodeCoverageEntityKey(); } /** @@ -247,6 +245,7 @@ public class TestRunEntity implements Serializable { } /** Saving function for the instance of this class */ + @Override public com.googlecode.objectify.Key<TestRunEntity> save() { return ofy().save().entity(this).now(); } @@ -289,7 +288,7 @@ public class TestRunEntity implements Serializable { } /** Get ApiCoverageEntity Key from the parent key */ - private com.googlecode.objectify.Key getOfyKey() { + public com.googlecode.objectify.Key getOfyKey() { com.googlecode.objectify.Key testKey = com.googlecode.objectify.Key.create( TestEntity.class, this.testName); diff --git a/src/main/java/com/android/vts/entity/TestStatusEntity.java b/src/main/java/com/android/vts/entity/TestStatusEntity.java index ec5ee36..b703c64 100644 --- a/src/main/java/com/android/vts/entity/TestStatusEntity.java +++ b/src/main/java/com/android/vts/entity/TestStatusEntity.java @@ -22,7 +22,6 @@ import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.Index; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; @@ -30,12 +29,14 @@ import java.util.logging.Logger; import lombok.Data; import lombok.NoArgsConstructor; +import static com.googlecode.objectify.ObjectifyService.ofy; + @com.googlecode.objectify.annotation.Entity(name = "TestStatus") @Cache @Data @NoArgsConstructor /** Entity describing test status. */ -public class TestStatusEntity implements Serializable { +public class TestStatusEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(TestStatusEntity.class.getName()); public static final String KIND = "TestStatus"; @@ -125,6 +126,12 @@ public class TestStatusEntity implements Serializable { this(testName, 0, -1, -1, new ArrayList<TestCaseReference>()); } + /** Saving function for the instance of this class */ + @Override + public com.googlecode.objectify.Key<TestStatusEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity testEntity = new Entity(KIND, this.testName); if (this.updatedTimestamp >= 0 && this.passCount >= 0 && this.failCount >= 0) { diff --git a/src/main/java/com/android/vts/entity/TestSuiteFileEntity.java b/src/main/java/com/android/vts/entity/TestSuiteFileEntity.java index 2331e42..c68f2ec 100644 --- a/src/main/java/com/android/vts/entity/TestSuiteFileEntity.java +++ b/src/main/java/com/android/vts/entity/TestSuiteFileEntity.java @@ -16,6 +16,7 @@ package com.android.vts.entity; +import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Cache; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; @@ -25,11 +26,9 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Date; -import java.util.List; import static com.googlecode.objectify.ObjectifyService.ofy; @@ -38,7 +37,7 @@ import static com.googlecode.objectify.ObjectifyService.ofy; @Entity @EqualsAndHashCode(of = "id") @NoArgsConstructor -public class TestSuiteFileEntity { +public class TestSuiteFileEntity implements DashboardEntity { /** Test Suite full file path field */ @Id @Getter @Setter String filePath; @@ -71,8 +70,9 @@ public class TestSuiteFileEntity { } /** Saving function for the instance of this class */ - public void save() { + @Override + public Key<TestSuiteFileEntity> save() { this.updated = new Date(); - ofy().save().entity(this).now(); + return ofy().save().entity(this).now(); } } diff --git a/src/main/java/com/android/vts/entity/TestSuiteResultEntity.java b/src/main/java/com/android/vts/entity/TestSuiteResultEntity.java index 2e12f54..95ba5c8 100644 --- a/src/main/java/com/android/vts/entity/TestSuiteResultEntity.java +++ b/src/main/java/com/android/vts/entity/TestSuiteResultEntity.java @@ -38,18 +38,13 @@ import org.apache.http.client.utils.URIUtils; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.message.BasicNameValuePair; -import javax.servlet.ServletContext; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; import java.math.BigDecimal; -import java.math.RoundingMode; import java.net.URI; import java.net.URISyntaxException; -import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -126,7 +121,7 @@ class TestTypeIndex { @Entity @EqualsAndHashCode(of = "id") @NoArgsConstructor -public class TestSuiteResultEntity { +public class TestSuiteResultEntity implements DashboardEntity { private static final Logger logger = Logger.getLogger(TestSuiteResultEntity.class.getName()); @@ -316,6 +311,12 @@ public class TestSuiteResultEntity { } } + /** Saving function for the instance of this class */ + @Override + public Key<TestSuiteResultEntity> save() { + return ofy().save().entity(this).now(); + } + public static void setPropertyValues(Properties newSystemConfigProp) { systemConfigProp = newSystemConfigProp; bugTrackingSystemProp = getBugTrackingSystemProp(newSystemConfigProp); diff --git a/src/main/java/com/android/vts/entity/UserEntity.java b/src/main/java/com/android/vts/entity/UserEntity.java index a686efb..43b5edd 100644 --- a/src/main/java/com/android/vts/entity/UserEntity.java +++ b/src/main/java/com/android/vts/entity/UserEntity.java @@ -38,7 +38,7 @@ import static com.googlecode.objectify.ObjectifyService.ofy; @Entity @EqualsAndHashCode(of = "email") @NoArgsConstructor -public class UserEntity { +public class UserEntity implements DashboardEntity { /** User email field */ @Id @Getter @Setter String email; @@ -79,9 +79,10 @@ public class UserEntity { } /** Saving function for the instance of this class */ - public void save() { + @Override + public Key<UserEntity> save() { this.updated = new Date(); - ofy().save().entity(this).now(); + return ofy().save().entity(this).now(); } /** Get admin user list by admin email */ diff --git a/src/main/java/com/android/vts/entity/UserFavoriteEntity.java b/src/main/java/com/android/vts/entity/UserFavoriteEntity.java index 132d9b4..2548042 100644 --- a/src/main/java/com/android/vts/entity/UserFavoriteEntity.java +++ b/src/main/java/com/android/vts/entity/UserFavoriteEntity.java @@ -19,9 +19,22 @@ package com.android.vts.entity; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.users.User; +import com.googlecode.objectify.annotation.Cache; +import com.googlecode.objectify.annotation.Ignore; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + import java.util.logging.Level; import java.util.logging.Logger; +import static com.googlecode.objectify.ObjectifyService.ofy; + +@Cache +@com.googlecode.objectify.annotation.Entity(name = "UserFavorite") +@EqualsAndHashCode(of = "email") +@NoArgsConstructor /** Entity describing subscriptions between a user and a test. */ public class UserFavoriteEntity implements DashboardEntity { protected static final Logger logger = Logger.getLogger(UserFavoriteEntity.class.getName()); @@ -33,10 +46,17 @@ public class UserFavoriteEntity implements DashboardEntity { public static final String TEST_KEY = "testKey"; public static final String MUTE_NOTIFICATIONS = "muteNotifications"; - private final Key key; - public final User user; - public final Key testKey; - public boolean muteNotifications; + @Ignore private Key key = null; + + @Ignore public User user = null; + + @Ignore public Key testKey = null; + + @Getter @Setter private com.googlecode.objectify.Key<TestEntity> test; + + @Getter @Setter private String userEmail; + + @Getter @Setter public boolean muteNotifications; /** * Create a user favorite relationship. @@ -64,7 +84,12 @@ public class UserFavoriteEntity implements DashboardEntity { this(null, user, testKey, muteNotifications); } + /** Saving function for the instance of this class */ @Override + public com.googlecode.objectify.Key<UserFavoriteEntity> save() { + return ofy().save().entity(this).now(); + } + public Entity toEntity() { Entity favoriteEntity; if (this.key != null) { |