/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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 * * https://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.example.junitlauncher; import org.apache.tools.ant.taskdefs.optional.junitlauncher.TestExecutionContext; import org.apache.tools.ant.taskdefs.optional.junitlauncher.TestResultFormatter; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.TestIdentifier; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.List; /** * Utility listener used in {@link org.apache.tools.ant.taskdefs.optional.junitlauncher.JUnitLauncherTaskTest} * to verify that tests launched through junitlauncher task are executed as expected */ public class Tracker implements TestResultFormatter { private static final String PREFIX_TEST_CLASS_STARTED = "started:test-class:"; private static final String PREFIX_TEST_METHOD_STARTED = "started:test-method:"; private static final String PREFIX_TEST_CLASS_SKIPPED = "skipped:test-class:"; private static final String PREFIX_TEST_METHOD_SKIPPED = "skipped:test-method:"; private PrintWriter writer; private TestExecutionContext context; private OutputStream appendModeFile; @Override public void setDestination(final OutputStream os) { final String propVal = this.context.getProperties().getProperty("junitlauncher.test.tracker.append.file"); if (propVal == null) { this.writer = new PrintWriter(os, true); return; } // ignore the passed outputstream and instead create our own, in append mode final Path appendModeFilePath = Paths.get(propVal); try { this.appendModeFile = Files.newOutputStream(appendModeFilePath, StandardOpenOption.CREATE, StandardOpenOption.APPEND); this.writer = new PrintWriter(this.appendModeFile, true); } catch (IOException e) { throw new RuntimeException(e); } } @Override public void setContext(final TestExecutionContext context) { this.context = context; } @Override public void setUseLegacyReportingName(final boolean useLegacyReportingName) { // do nothing } @Override public void close() throws IOException { this.writer.flush(); if (this.appendModeFile != null) { this.appendModeFile.close(); } } @Override public void executionStarted(final TestIdentifier testIdentifier) { testIdentifier.getSource().ifPresent((s) -> { if (s instanceof MethodSource) { writer.println(PREFIX_TEST_METHOD_STARTED + ((MethodSource) s).getClassName() + "#" + ((MethodSource) s).getMethodName()); return; } if (s instanceof ClassSource) { writer.println(PREFIX_TEST_CLASS_STARTED + ((ClassSource) s).getClassName()); return; } }); } @Override public void executionFinished(final TestIdentifier testIdentifier, final TestExecutionResult testExecutionResult) { testIdentifier.getSource().ifPresent((s) -> { if (s instanceof MethodSource) { writer.println(testExecutionResult.getStatus().name() + ":test-method:" + ((MethodSource) s).getClassName() + "#" + ((MethodSource) s).getMethodName()); return; } if (s instanceof ClassSource) { writer.println(testExecutionResult.getStatus().name() + ":test-class:" + ((ClassSource) s).getClassName()); return; } }); } @Override public void executionSkipped(final TestIdentifier testIdentifier, final String reason) { testIdentifier.getSource().ifPresent((s) -> { if (s instanceof MethodSource) { writer.println(PREFIX_TEST_METHOD_SKIPPED + ((MethodSource) s).getClassName() + "#" + ((MethodSource) s).getMethodName()); return; } if (s instanceof ClassSource) { writer.println(PREFIX_TEST_CLASS_SKIPPED + ((ClassSource) s).getClassName()); return; } }); } public static boolean wasTestRun(final Path trackerFile, final String className) throws IOException { final List lines = readTrackerFile(trackerFile); return lines.contains(PREFIX_TEST_CLASS_STARTED + className); } public static boolean wasTestRun(final Path trackerFile, final String className, final String methodName) throws IOException { final List lines = readTrackerFile(trackerFile); return lines.contains(PREFIX_TEST_METHOD_STARTED + className + "#" + methodName); } public static boolean verifyFailed(final Path trackerFile, final String className, final String methodName) throws IOException { final List lines = readTrackerFile(trackerFile); return lines.contains(TestExecutionResult.Status.FAILED + ":test-method:" + className + "#" + methodName); } public static boolean verifySetupFailed(final Path trackerFile, final String className) throws IOException { final List lines = readTrackerFile(trackerFile); return lines.contains(TestExecutionResult.Status.FAILED + ":test-class:" + className); } public static boolean verifySuccess(final Path trackerFile, final String className, final String methodName) throws IOException { final List lines = readTrackerFile(trackerFile); return lines.contains(TestExecutionResult.Status.SUCCESSFUL + ":test-method:" + className + "#" + methodName); } public static boolean verifySkipped(final Path trackerFile, final String className, final String methodName) throws IOException { final List lines = readTrackerFile(trackerFile); return lines.contains(PREFIX_TEST_METHOD_SKIPPED + className + "#" + methodName); } private static List readTrackerFile(final Path trackerFile) throws IOException { if (!Files.isRegularFile(trackerFile)) { throw new RuntimeException(trackerFile + " is either missing or not a file"); } return Files.readAllLines(trackerFile); } }