package org.netbeans.gradle.project.tasks; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import org.jtrim.cancel.Cancellation; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.DisableOnDebug; import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.netbeans.gradle.project.NbGradleProject; import org.netbeans.gradle.project.api.config.PropertyReference; import org.netbeans.gradle.project.api.entry.SampleProjectRule; import org.netbeans.gradle.project.properties.standard.CustomVariable; import org.netbeans.gradle.project.properties.standard.CustomVariables; import org.netbeans.gradle.project.properties.standard.MemCustomVariables; import org.netbeans.gradle.project.tasks.vars.StandardTaskVariable; import org.netbeans.gradle.project.util.NbFileUtils; import org.netbeans.spi.project.ActionProvider; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.loaders.DataObject; import org.openide.util.Lookup; import org.openide.util.lookup.Lookups; import static org.junit.Assert.*; public class RunGradleTaskTest { @ClassRule public static final SampleProjectRule PROJECT_REF = SampleProjectRule.getStandardRule("run-test-proj.zip"); @Rule public final TestRule timeout = new DisableOnDebug(Timeout.seconds(90)); @SuppressWarnings("SleepWhileInLoop") private static void waitForRun(Path buildDir) throws InterruptedException { Path doneFile = buildDir.resolve("done.txt"); long sleepTime = 5; while (!Files.exists(doneFile)) { Thread.sleep(sleepTime); sleepTime = Math.min(2 * sleepTime, 200); } } private static void runAndWait(NbGradleProject project) throws InterruptedException { ActionProvider actionProvider = project.getLookup().lookup(ActionProvider.class); actionProvider.invokeAction(ActionProvider.COMMAND_RUN, Lookup.EMPTY); waitForRun(buildDir(project)); } private static Path buildDir(NbGradleProject project) { return project.getProjectDirectoryAsPath().resolve("build"); } @SuppressWarnings("SleepWhileInLoop") private static void deleteDirectoryLenient(Path dir) throws Exception { long timeoutMs = 3000; long sleepMs = 100; int tryCount = (int)(timeoutMs / sleepMs) - 1; for (int i = 0; i < tryCount; i++) { try { NbFileUtils.deleteDirectory(Cancellation.UNCANCELABLE_TOKEN, dir); return; } catch (IOException ex) { } Thread.sleep(sleepMs); } NbFileUtils.deleteDirectory(Cancellation.UNCANCELABLE_TOKEN, dir); } private static NbGradleProject setupRunProject(String... projectPath) throws Throwable { NbGradleProject project = PROJECT_REF.loadAndWaitProject(projectPath); // FIXME: Currently, there is no way to properly determine if a task has completely // terminated from tests. So, it is possible that a previous test is not // completely terminated and keeps some file open in the build directory. // So, we try a few times to remove the build directory. deleteDirectoryLenient(buildDir(project)); return project; } private static NbGradleProject testRun(String... projectPath) throws Throwable { NbGradleProject project = setupRunProject(projectPath); runAndWait(project); return project; } private static void verifyContent( NbGradleProject project, String outputFileName, String expectedContent) throws IOException { Path outputFile = buildDir(project).resolve(outputFileName); String content = new String(Files.readAllBytes(outputFile), StandardCharsets.UTF_8); assertEquals("content", expectedContent, content); } @Test public void testManualRun() throws Throwable { NbGradleProject project = testRun("run-test-proj", "manual-run"); verifyContent(project, "test-out.txt", "Hello manual-run"); } @Test public void testAutomaticRun() throws Throwable { NbGradleProject project = testRun("run-test-proj", "auto-run"); verifyContent(project, "output-auto.txt", "Auto-Test-Content"); } private static String toQuotedArg(Object arg) { return '"' + arg.toString() .replace("\\", "\\\\") .replace("\"", "\\\"") + '"'; } @Test public void testAutomaticRunWithCustomArgs() throws Throwable { NbGradleProject project = setupRunProject("run-test-proj", "auto-run"); Path buildDir = buildDir(project); final String testContent = "NB-TEST-CONTENT-563465"; Path outputPath = buildDir.resolve("nb-test-output.txt"); StringBuilder args = new StringBuilder(128); args.append(toQuotedArg(outputPath)); args.append(' '); args.append(testContent); PropertyReference<CustomVariables> customVariables = project.getCommonProperties().customVariables(); CustomVariables prevValue = customVariables.getActiveValue(); try { customVariables.setValue(new MemCustomVariables(Arrays.asList( new CustomVariable(StandardTaskVariable.CMD_LINE_ARGS.getVariableName(), args.toString()) ))); runAndWait(project); } finally { customVariables.setValue(prevValue); } String writtenContent = new String(Files.readAllBytes(outputPath), StandardCharsets.UTF_8); assertEquals("content", testContent, writtenContent); } @Test public void testRunSingle() throws Throwable { NbGradleProject project = setupRunProject("run-test-proj", "auto-run"); FileObject rootDir = FileUtil.toFileObject(project.currentModel().getValue().getSettingsDir().toFile()); FileObject mainClass = rootDir.getFileObject("common-src/testpckg/App2.java"); DataObject mainClassData = DataObject.find(mainClass); ActionProvider actionProvider = project.getLookup().lookup(ActionProvider.class); actionProvider.invokeAction(ActionProvider.COMMAND_RUN_SINGLE, Lookups.fixed(mainClassData)); waitForRun(buildDir(project)); verifyContent(project, "output-auto.txt", "APP2-Auto-Test-Content"); } }