diff --git a/common/src/main/java/org/wso2/testgrid/common/TestGridConstants.java b/common/src/main/java/org/wso2/testgrid/common/TestGridConstants.java
index 5a5f8c787..96ffdb5b8 100644
--- a/common/src/main/java/org/wso2/testgrid/common/TestGridConstants.java
+++ b/common/src/main/java/org/wso2/testgrid/common/TestGridConstants.java
@@ -71,6 +71,7 @@ public class TestGridConstants {
public static final String TEST_PLANS_URI = "test-plans";
public static final String HTML_LINE_SEPARATOR = " ";
public static final String TESTGRID_EMAIL_REPORT_NAME = "EmailReport.html";
+ public static final String TESTGRID_SUMMARIZED_EMAIL_REPORT_NAME = "SummarizedEmailReport.html";
public static final String SHELL_SUFFIX = ".sh";
public static final String PRE_STRING = "pre-scenario-steps";
diff --git a/common/src/main/java/org/wso2/testgrid/common/util/FileUtil.java b/common/src/main/java/org/wso2/testgrid/common/util/FileUtil.java
index 748b899b6..c21046894 100644
--- a/common/src/main/java/org/wso2/testgrid/common/util/FileUtil.java
+++ b/common/src/main/java/org/wso2/testgrid/common/util/FileUtil.java
@@ -19,15 +19,19 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.wso2.testgrid.common.TestPlan;
import org.wso2.testgrid.common.exception.TestGridException;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
@@ -38,12 +42,18 @@
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
+import static org.wso2.testgrid.common.TestGridConstants.PRODUCT_TEST_PLANS_DIR;
+
/**
* Utility class for handling file operations.
*
@@ -162,4 +172,83 @@ public static void compress(String sourceDir, String destination) throws IOExcep
}
}
+ /**
+ * Writes a given string to a given file to persistent media.
+ *
+ * @param filePath absolute path of the file to be written
+ * @param string string to be written
+ * @throws TestGridException thrown on {@link FileNotFoundException} or {@link UnsupportedEncodingException}
+ */
+ public static void writeToFile(String filePath, String string) throws TestGridException {
+ createFileIfNotExists(filePath); // Create file if not exists
+ try (PrintWriter writer = new PrintWriter(filePath, StandardCharsets.UTF_8.name())) {
+ writer.write(string);
+ } catch (FileNotFoundException e) {
+ throw new TestGridException(String.format(Locale.ENGLISH, "File %s not found", filePath), e);
+ } catch (UnsupportedEncodingException e) {
+ throw new TestGridException(
+ String.format(Locale.ENGLISH, "Unsupported encoding %s", StandardCharsets.UTF_8.name()), e);
+ }
+ }
+
+ /**
+ * Creates a file with the given name.
+ *
+ * @param filePath absolute path of the file
+ * @throws TestGridException thrown when IO exception on creating a file
+ */
+ private static void createFileIfNotExists(String filePath) throws TestGridException {
+ File file = new File(filePath);
+ if (!file.exists()) {
+ // Create directories if not exists
+ Path parent = Paths.get(filePath).getParent();
+
+ if (parent != null) {
+ boolean status = new File(parent.toAbsolutePath().toString()).mkdirs();
+
+ if (status) {
+ // Touch file
+ try {
+ new FileOutputStream(file).close();
+ } catch (IOException e) {
+ throw new TestGridException(String.format(Locale.ENGLISH,
+ "IO Exception occurred when creating file %s", file), e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get test plan ids by reading testgrid yaml files contains in the testgrid home.
+ *
+ * @param workspace path of the current workspace
+ * @throws TestGridException thrown when IO exception on reading testgrid yaml files.
+ */
+ public static List getTestPlanIdByReadingTGYaml(String workspace) throws TestGridException {
+ List testPlanIds = new ArrayList<>();
+ Path source = Paths.get(workspace, PRODUCT_TEST_PLANS_DIR);
+ if (!Files.exists(source)) {
+ logger.error("Test-plans dir does not exist: " + source);
+ return Collections.emptyList();
+ }
+ try (Stream stream = Files.list(source).filter(Files::isRegularFile)) {
+ List paths = stream.sorted().collect(Collectors.toList());
+ for (Path path : paths) {
+ if (!path.toFile().exists()) {
+ throw new IOException(
+ "Test Plan File doesn't exist. File path is " + path.toAbsolutePath().toString());
+ }
+ logger.info("A test plan file found at " + path.toAbsolutePath().toString());
+ TestPlan testPlanYaml = org.wso2.testgrid.common.util.FileUtil
+ .readYamlFile(path.toAbsolutePath().toString(), TestPlan.class);
+ testPlanIds.add(testPlanYaml.getId());
+ }
+ return testPlanIds;
+ } catch (IOException e) {
+ throw new TestGridException("Error occurred while reading the test-plan yamls in workspace " + workspace,
+ e);
+ }
+
+ }
}
diff --git a/core/src/main/java/org/wso2/testgrid/core/command/GenerateEmailCommand.java b/core/src/main/java/org/wso2/testgrid/core/command/GenerateEmailCommand.java
index eb7d0aef2..ed7a9167f 100644
--- a/core/src/main/java/org/wso2/testgrid/core/command/GenerateEmailCommand.java
+++ b/core/src/main/java/org/wso2/testgrid/core/command/GenerateEmailCommand.java
@@ -56,8 +56,14 @@ public void execute() throws CommandExecutionException {
Product product = getProduct(productName);
try {
TestReportEngine testReportEngine = new TestReportEngine();
- final Optional path = testReportEngine.generateEmailReport(product, workspace);
- path.ifPresent(p -> logger.info("Written the email report body contents to: " + p));
+ // Generating the summary report
+ final Optional summarizedReportPath = testReportEngine.generateSummarizedEmailReport(product,
+ workspace);
+ summarizedReportPath.ifPresent(p -> logger.info("Written the summarized email " +
+ "report body contents to: " + p));
+
+ final Optional reportPath = testReportEngine.generateEmailReport(product, workspace);
+ reportPath.ifPresent(p -> logger.info("Written the email report body contents to: " + p));
} catch (ReportingException e) {
throw new CommandExecutionException(StringUtil
.concatStrings("Error occurred when generating email report for {" +
diff --git a/dao/src/main/java/org/wso2/testgrid/dao/dto/TestCaseFailureResultDTO.java b/dao/src/main/java/org/wso2/testgrid/dao/dto/TestCaseFailureResultDTO.java
new file mode 100644
index 000000000..0e223b1ef
--- /dev/null
+++ b/dao/src/main/java/org/wso2/testgrid/dao/dto/TestCaseFailureResultDTO.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you 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 org.wso2.testgrid.dao.dto;
+
+/**
+ * Defines a model object of test case failure results.
+ *
+ * @since 1.0.0
+ */
+public class TestCaseFailureResultDTO {
+
+ private String name;
+ private String failureMessage;
+ private String infraParameters;
+
+ public TestCaseFailureResultDTO(String testname, String failureMessage, String infraParameters) {
+ this.name = testname;
+ this.failureMessage = failureMessage;
+ this.infraParameters = infraParameters;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getFailureMessage() {
+ return failureMessage;
+ }
+
+ public void setFailureMessage(String failureMessage) {
+ this.failureMessage = failureMessage;
+ }
+
+ public String getInfraParameters() {
+ return infraParameters;
+ }
+
+ public void setInfraParameters(String infraParameters) {
+ this.infraParameters = infraParameters;
+ }
+}
diff --git a/dao/src/main/java/org/wso2/testgrid/dao/repository/TestPlanRepository.java b/dao/src/main/java/org/wso2/testgrid/dao/repository/TestPlanRepository.java
index 7e8866400..214abe420 100644
--- a/dao/src/main/java/org/wso2/testgrid/dao/repository/TestPlanRepository.java
+++ b/dao/src/main/java/org/wso2/testgrid/dao/repository/TestPlanRepository.java
@@ -24,9 +24,14 @@
import org.wso2.testgrid.dao.EntityManagerHelper;
import org.wso2.testgrid.dao.SortOrder;
import org.wso2.testgrid.dao.TestGridDAOException;
+import org.wso2.testgrid.dao.dto.TestCaseFailureResultDTO;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
@@ -290,4 +295,120 @@ public List getTestPlanOlderThan(String duration, String timeUnit) {
.getResultList();
return EntityManagerHelper.refreshResultList(entityManager, resultList);
}
+
+ /**
+ * This method returns test failure summary for given test plan ids. (i.e for a given build job).
+ *
+ * @param testPlanIds test plan ids
+ * @return a List of {@link TestCaseFailureResultDTO} representing the test case failure results for a given build
+ */
+ public List getTestFailureSummaryByTPId(List testPlanIds)
+ throws TestGridDAOException {
+ StringBuilder sql = new StringBuilder("select failed_tc.test_name as name, failed_tc.failure_message as "
+ + "failureMessage, tp.infra_parameters as infraParametrs from test_plan tp join (select tc"
+ + ".test_name, tc.failure_message, ts.TESTPLAN_id from test_case tc inner join test_scenario ts on "
+ + "ts.id=tc.TESTSCENARIO_id and tc.status = 'FAIL' and ts.TESTPLAN_id in (");
+ for (int i = 0; i < testPlanIds.size() - 1; i++) {
+ sql.append("?, ");
+ }
+ sql.append("?)) failed_tc on tp.id = failed_tc.TESTPLAN_id;");
+ Query query = entityManager.createNativeQuery(sql.toString());
+ int index = 1;
+ for (String s : testPlanIds) {
+ query.setParameter(index++, s);
+ }
+ return getResultList(query, TestCaseFailureResultDTO.class);
+ }
+
+ /**
+ * This method returns the test execution summary for given test plan ids(i.e for a given build job).
+ *
+ * @param testPlanIds test plan ids of a specific build job
+ * @return a List of {@link String} representing statuses of given test plans
+ */
+ public List getTestPlanStatuses(List testPlanIds) {
+ StringBuilder sql = new StringBuilder("select status from test_plan where id in (");
+ for (int i = 0; i < testPlanIds.size() - 1; i++) {
+ sql.append("?, ");
+ }
+ sql.append("?);");
+ Query query = entityManager.createNativeQuery(sql.toString());
+ int index = 1;
+ for (String s : testPlanIds) {
+ query.setParameter(index++, s);
+ }
+ @SuppressWarnings("unchecked")
+ List statuses = (List) query.getResultList();
+ return statuses;
+ }
+
+ /**
+ * This method returns the history of test execution summary for given product.
+ *
+ * @param productId id of the product
+ * @param from starting point of the considering time range
+ * @param to end point of the considering time range
+ * @return a List of {@link TestPlan} representing executed test plans of a given product for a given time range
+ */
+ public List getTestExecutionHistory(String productId, String from, String to) {
+ String sql = "select tp.* from test_plan tp inner join (Select distinct infra_parameters from test_plan where "
+ + "DEPLOYMENTPATTERN_id in (select id from deployment_pattern where PRODUCT_id=?)) as rn on "
+ + "tp.infra_parameters=rn.infra_parameters and tp.DEPLOYMENTPATTERN_id "
+ + "in (select id from deployment_pattern where PRODUCT_id=?) and modified_timestamp between ? and ?;";
+
+ @SuppressWarnings("unchecked")
+ List resultList = (List) entityManager.createNativeQuery(sql, TestPlan.class)
+ .setParameter(1, productId)
+ .setParameter(2, productId)
+ .setParameter(3, from)
+ .setParameter(4, to)
+ .getResultList();
+ return EntityManagerHelper.refreshResultList(entityManager, resultList);
+ }
+
+ /**
+ * This method is responsible to map list of objects to a given class.
+ *
+ * @param type Mapping class
+ * @param records lst of objects that are mapping to instance of the given class
+ * @return a List of mapped objects
+ */
+ public static List mapObject(Class type, List