diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/utils/TestUtils.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/utils/TestUtils.java index f89e17e63024..8a19467c9802 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/utils/TestUtils.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/utils/TestUtils.java @@ -175,29 +175,26 @@ public static void generateTesterinaReports(Project project, TestReport testRepo } } - Path reportZipPath = Paths.get(System.getProperty(BALLERINA_HOME)).resolve(BALLERINA_HOME_LIB). - resolve(TesterinaConstants.TOOLS_DIR_NAME).resolve(TesterinaConstants.COVERAGE_DIR). - resolve(REPORT_ZIP_NAME); // Dump the Testerina html report only if '--test-report' flag is provided if (project.buildOptions().testReport()) { + Path reportZipPath = getReportToolsPath(); if (Files.exists(reportZipPath)) { String content; try { try (FileInputStream fileInputStream = new FileInputStream(reportZipPath.toFile())) { - CodeCoverageUtils.unzipReportResources(fileInputStream, - reportDir.toFile()); + CodeCoverageUtils.unzipReportResources(fileInputStream, reportDir.toFile()); } content = Files.readString(reportDir.resolve(RESULTS_HTML_FILE)); content = content.replace(REPORT_DATA_PLACEHOLDER, json); } catch (IOException e) { - throw createLauncherException("error occurred while preparing test report: " + e.toString()); + throw createLauncherException("error occurred while preparing test report: " + e); } File htmlFile = new File(reportDir.resolve(RESULTS_HTML_FILE).toString()); try (FileOutputStream fileOutputStream = new FileOutputStream(htmlFile)) { try (Writer writer = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8)) { writer.write(new String(content.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)); out.println("\tView the test report at: " + - FILE_PROTOCOL + Paths.get(htmlFile.getPath()).toAbsolutePath().normalize().toString()); + FILE_PROTOCOL + Paths.get(htmlFile.getPath()).toAbsolutePath().normalize()); } } } else { @@ -210,6 +207,17 @@ public static void generateTesterinaReports(Project project, TestReport testRepo } } + /** + * Get the path of the report tools template from Ballerina home. + * + * @return path of the report tools template + */ + public static Path getReportToolsPath() { + return Paths.get(System.getProperty(BALLERINA_HOME)).resolve(BALLERINA_HOME_LIB). + resolve(TesterinaConstants.TOOLS_DIR_NAME).resolve(TesterinaConstants.COVERAGE_DIR). + resolve(REPORT_ZIP_NAME); + } + /** * Loads the ModuleStatus object by reading a given Json. * @@ -235,7 +243,7 @@ public static void writeToTestSuiteJson(Map testSuiteMap, Pat try { Files.createDirectories(testsCachePath); } catch (IOException e) { - throw LauncherUtils.createLauncherException("couldn't create test cache directories : " + e.toString()); + throw LauncherUtils.createLauncherException("couldn't create test cache directories : " + e); } } @@ -247,10 +255,10 @@ public static void writeToTestSuiteJson(Map testSuiteMap, Pat String json = gson.toJson(testSuiteMap); writer.write(new String(json.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)); } catch (IOException e) { - throw LauncherUtils.createLauncherException("couldn't write data to test suite file : " + e.toString()); + throw LauncherUtils.createLauncherException("couldn't write data to test suite file : " + e); } } catch (IOException e) { - throw LauncherUtils.createLauncherException("couldn't write data to test suite file : " + e.toString()); + throw LauncherUtils.createLauncherException("couldn't write data to test suite file : " + e); } } diff --git a/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/TestCommandTest.java b/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/TestCommandTest.java index af01dac0283b..b480aaa2a262 100644 --- a/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/TestCommandTest.java +++ b/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/TestCommandTest.java @@ -19,6 +19,7 @@ package io.ballerina.cli.cmd; import io.ballerina.cli.launcher.BLauncherException; +import io.ballerina.cli.utils.TestUtils; import io.ballerina.projects.ProjectEnvironmentBuilder; import io.ballerina.projects.environment.Environment; import io.ballerina.projects.environment.EnvironmentBuilder; @@ -27,6 +28,8 @@ import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.ballerinalang.test.BCompileUtil; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -223,7 +226,7 @@ public void testTestCommandPreservingBinJarInTargetDir() throws IOException { .resolve("foo-winery-0.1.0-testable.jar").toFile().exists()); } - @Test + @Test(description = "Test a ballerina project with an invalid argument for --coverage-format") public void testUnsupportedCoverageFormat() throws IOException { Path projectPath = this.testResources.resolve("validProjectWithTests"); TestCommand testCommand = new TestCommand( @@ -236,7 +239,7 @@ public void testUnsupportedCoverageFormat() throws IOException { "supported.")); } - @Test () + @Test (description = "Test a ballerina project with a custom value for --target-dir") public void testCustomTargetDirWithTestCmd() { Path projectPath = this.testResources.resolve("validProjectWithTests"); Path customTargetDir = projectPath.resolve("customTargetDir3"); @@ -260,6 +263,31 @@ public void testCustomTargetDirWithTestCmd() { ".json"))); } + @Test(description = "Test a ballerina project with --test-report") + public void testTestWithReport() { + Path projectPath = this.testResources.resolve("validProjectWithTests"); + TestCommand testCommand = new TestCommand( + projectPath, printStream, printStream, false, true, false, null); + new CommandLine(testCommand).parseArgs(); + try (MockedStatic testUtilsMockedStatic = Mockito.mockStatic( + TestUtils.class, Mockito.CALLS_REAL_METHODS)) { + testUtilsMockedStatic.when(TestUtils::getReportToolsPath) + .thenReturn(projectPath.resolve("resources").resolve("coverage").resolve("report.zip")); + testCommand.execute(); + } + Path reportDir = projectPath.resolve("target").resolve("report"); + + Assert.assertTrue(Files.exists(reportDir)); + Assert.assertTrue(Files.exists(reportDir.resolve("favicon.ico"))); + Assert.assertTrue(Files.exists(reportDir.resolve("index.html"))); + Assert.assertTrue(Files.exists(reportDir.resolve("test_results.json"))); + Assert.assertTrue(Files.exists(reportDir.resolve("manifest.json"))); + Assert.assertTrue(Files.exists(reportDir.resolve("static").resolve("css").resolve("2.d5162072.chunk.css"))); + Assert.assertTrue(Files.exists(reportDir.resolve("static").resolve("css").resolve("main.15691da7.chunk.css"))); + Assert.assertTrue(Files.exists(reportDir.resolve("static").resolve("js").resolve("2.bc541f30.chunk.js"))); + Assert.assertTrue(Files.exists(reportDir.resolve("static").resolve("js").resolve("main.ea323a3b.chunk.js"))); + } + @Test(description = "tests bal test command with sticky flag") public void testBalTestWithStickyFlag() throws IOException { // Cache package pkg_a 1.0.0 @@ -408,5 +436,4 @@ public void testGraalVMIncompatibleProject() throws IOException { Assert.assertTrue(buildLog.contains("WARNING: Package is not compatible with GraalVM.")); } } - } diff --git a/cli/ballerina-cli/src/test/resources/test-resources/validProjectWithTests/resources/coverage/report.zip b/cli/ballerina-cli/src/test/resources/test-resources/validProjectWithTests/resources/coverage/report.zip new file mode 100644 index 000000000000..9f304a882e86 Binary files /dev/null and b/cli/ballerina-cli/src/test/resources/test-resources/validProjectWithTests/resources/coverage/report.zip differ diff --git a/misc/testerina/modules/testerina-runtime/src/main/java/org/ballerinalang/test/runtime/util/CodeCoverageUtils.java b/misc/testerina/modules/testerina-runtime/src/main/java/org/ballerinalang/test/runtime/util/CodeCoverageUtils.java index 5721cde5662b..b83e5990e092 100644 --- a/misc/testerina/modules/testerina-runtime/src/main/java/org/ballerinalang/test/runtime/util/CodeCoverageUtils.java +++ b/misc/testerina/modules/testerina-runtime/src/main/java/org/ballerinalang/test/runtime/util/CodeCoverageUtils.java @@ -211,18 +211,8 @@ public static void unzipReportResources(InputStream source, File target) throws final ZipInputStream zipStream = new ZipInputStream(source); ZipEntry nextEntry; while ((nextEntry = zipStream.getNextEntry()) != null) { - - File zipFile = new File(REPORT_ZIP_DIRECTORY + nextEntry.getName()); - String canonicalZipPath = zipFile.getCanonicalPath(); - - if (!canonicalZipPath.startsWith(REPORT_ZIP_DIRECTORY)) { - continue; - } - String name = canonicalZipPath.replace(REPORT_ZIP_DIRECTORY, ""); - - // only extract files - if (!nextEntry.getName().endsWith("/")) { - final File nextFile = new File(target, name); + if (!nextEntry.isDirectory()) { + final File nextFile = new File(target, nextEntry.getName()); // create directories final File parent = nextFile.getParentFile(); @@ -234,7 +224,6 @@ public static void unzipReportResources(InputStream source, File target) throws try (OutputStream targetStream = new FileOutputStream(nextFile)) { final int bufferSize = 4 * 1024; final byte[] buffer = new byte[bufferSize]; - int nextCount; while ((nextCount = zipStream.read(buffer)) >= 0) { targetStream.write(buffer, 0, nextCount);