package org.jboss.arquillian.drone.webdriver.binary.handler; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.arquillian.spacelift.Spacelift; import org.arquillian.spacelift.process.CommandBuilder; import org.arquillian.spacelift.task.os.CommandTool; import org.jboss.arquillian.drone.webdriver.binary.BinaryFilesUtils; import org.jboss.arquillian.drone.webdriver.binary.downloading.Downloader; import org.jboss.arquillian.drone.webdriver.binary.downloading.source.LocalBinarySource; import org.jboss.arquillian.drone.webdriver.binary.process.BinaryInteraction; import org.jboss.arquillian.drone.webdriver.utils.Constants; import org.jboss.arquillian.drone.webdriver.utils.PlatformUtils; import org.jboss.arquillian.drone.webdriver.utils.Validate; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.openqa.selenium.remote.DesiredCapabilities; import static org.assertj.core.api.Assertions.assertThat; import static org.jboss.arquillian.drone.webdriver.utils.Constants.ARQUILLIAN_DRONE_CACHE_DIRECTORY; import static org.jboss.arquillian.drone.webdriver.utils.Constants.DRONE_TARGET_DIRECTORY; /** * */ public class BinaryHandlerTestCase { private static final String originalCacheDirectory = ARQUILLIAN_DRONE_CACHE_DIRECTORY; private static final String originalTargetDirectory = DRONE_TARGET_DIRECTORY; private static String TEST_DRONE_TARGET_DIRECTORY = "target" + File.separator + "drone-test" + File.separator; private static String TEST_DRONE_CACHE_DIRECTORY = TEST_DRONE_TARGET_DIRECTORY + "cache" + File.separator; @BeforeClass public static void setTestCacheDirectory() throws NoSuchFieldException, IllegalAccessException { setTargetDirectory(TEST_DRONE_TARGET_DIRECTORY); setCacheDirectory(TEST_DRONE_CACHE_DIRECTORY); } @AfterClass public static void setOriginalCacheDirectory() throws NoSuchFieldException, IllegalAccessException { setTargetDirectory(originalTargetDirectory); setCacheDirectory(originalCacheDirectory); } private static void setCacheDirectory(String dirToSet) throws NoSuchFieldException, IllegalAccessException { setConstantProperty("ARQUILLIAN_DRONE_CACHE_DIRECTORY", dirToSet); } private static void setTargetDirectory(String dirToSet) throws NoSuchFieldException, IllegalAccessException { setConstantProperty("DRONE_TARGET_DIRECTORY", dirToSet); } private static void setConstantProperty(String propertyVariable, String value) throws NoSuchFieldException, IllegalAccessException { Field constantField = Constants.class.getField(propertyVariable); constantField.setAccessible(true); // remove final modifier from field Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(constantField, constantField.getModifiers() & ~Modifier.FINAL); constantField.set(null, value); } @Before public void cleanupBefore() throws IOException { cleanUp(); } @After public void cleanupAfter() throws IOException { cleanUp(); } private void cleanUp() throws IOException { File targetDroneDir = new File(TEST_DRONE_TARGET_DIRECTORY); if (targetDroneDir.exists()) { FileUtils.deleteDirectory(targetDroneDir); } System.setProperty(LocalBinaryHandler.LOCAL_SOURCE_SYSTEM_BINARY_PROPERTY, ""); System.setProperty(LocalBinaryHandler.LOCAL_SOURCE_BINARY_PROPERTY, ""); } @Test public void verifyWithoutAnyCapabilitySet() throws Exception { // the latest release should be downloaded and prepared verifyIsDownloadedExtractedSetExecutableSetInSystemProperty( new DesiredCapabilities(), getDownloadedPath(LocalBinarySource.LATEST_VERSION, LocalBinarySource.LATEST_FILE.getName()), getExtractedPath(LocalBinarySource.LATEST_FILE), LocalBinarySource.ECHO_LATEST_SCRIPT, true); } @Test public void verifyWithVersionCapabilitySet() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); // set version property to 1.0.0.Final capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_VERSION_PROPERTY, LocalBinarySource.FIRST_VERSION); // the 1.0.0.Final release should be downloaded and prepared verifyIsDownloadedExtractedSetExecutableSetInSystemProperty( capabilities, getDownloadedPath(LocalBinarySource.FIRST_VERSION, LocalBinarySource.FIRST_FILE.getName()), getExtractedPath(LocalBinarySource.FIRST_FILE), LocalBinarySource.ECHO_FIRST_SCRIPT, false); } @Test public void verifyWithUrlCapabilitySet() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); // set url the file should be downloaded from - without specifying version capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_URL_PROPERTY, LocalBinarySource.FIRST_FILE.toURI().toString()); // the 1.0.0.Final release should be downloaded to target/drone/downloaded directory verifyIsDownloadedExtractedSetExecutableSetInSystemProperty( capabilities, Downloader.DRONE_TARGET_DOWNLOADED_DIRECTORY + LocalBinarySource.FIRST_FILE.getName(), getExtractedPath(LocalBinarySource.FIRST_FILE), LocalBinarySource.ECHO_FIRST_SCRIPT, false); } @Test public void verifyWithUrlAndVersionCapabilitySet() throws Exception { String myCoolVersion = "my-cool-version"; DesiredCapabilities capabilities = new DesiredCapabilities(); // set url the file should be downloaded from and also my own version capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_VERSION_PROPERTY, myCoolVersion); capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_URL_PROPERTY, LocalBinarySource.FIRST_FILE.toURI().toString()); // the 1.0.0.Final release should be downloaded to target/drone/test/my-cool-version verifyIsDownloadedExtractedSetExecutableSetInSystemProperty( capabilities, getDownloadedPath(myCoolVersion, LocalBinarySource.FIRST_FILE.getName()), getExtractedPath(LocalBinarySource.FIRST_FILE), LocalBinarySource.ECHO_FIRST_SCRIPT, false); } @Test public void verifyWithDownloadBinariesSetFalse() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); // set download feature to off capabilities.setCapability( AbstractBinaryHandler.DOWNLOAD_BINARIES_PROPERTY, "false"); // nothing should be downloaded LocalBinaryHandler dummyGitHubHandler = new LocalBinaryHandler(capabilities); String resultingFile = dummyGitHubHandler.checkAndSetBinary(true); assertThat(resultingFile).isNull(); } @Test public void verifyWithSystemPropertySetToLatest() throws Exception { String latest = new LocalBinaryHandler(new DesiredCapabilities()).checkAndSetBinary(true); DesiredCapabilities capabilities = new DesiredCapabilities(); // these settings shouldn't have any impact capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_PROPERTY, LocalBinarySource.FIRST_FILE.getAbsolutePath()); capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_VERSION_PROPERTY, LocalBinarySource.FIRST_VERSION); // verify that the original one is used String binary = new LocalBinaryHandler(capabilities).checkAndSetBinary(true); assertThat(binary).isEqualTo(latest); } @Test public void verifyWithPropertySetInSystemToFirst() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); // the 1.0.0.Final should be downloaded capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_VERSION_PROPERTY, LocalBinarySource.FIRST_VERSION); // only download extract and set as executable - don't set into system property File first = new LocalBinaryHandler(capabilities).downloadAndPrepare(); System.setProperty(LocalBinaryHandler.LOCAL_SOURCE_BINARY_PROPERTY, first.getAbsolutePath()); // this shouldn't have any impact capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_VERSION_PROPERTY, LocalBinarySource.LATEST_VERSION); // verify that the original one is used String binary = new LocalBinaryHandler(capabilities).checkAndSetBinary(true); assertThat(binary).isEqualTo(first.getAbsolutePath()); } @Test public void verifyWithPropertySetToZip() throws Exception { DesiredCapabilities capabilities = new DesiredCapabilities(); // set binary to zip - test should throw an exception capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_PROPERTY, LocalBinarySource.FIRST_FILE.getAbsolutePath()); // this shouldn't have any impact capabilities.setCapability( LocalBinaryHandler.LOCAL_SOURCE_BINARY_VERSION_PROPERTY, LocalBinarySource.FIRST_VERSION); try { new LocalBinaryHandler(capabilities).checkAndSetBinary(true); if (!PlatformUtils.isWindows()) { Assert.fail("This test should have failed on all platforms but Windows"); } } catch (IllegalArgumentException iae) { if (PlatformUtils.isWindows()) { Assert.fail("This test should have not failed on Windows"); } } } private void verifyIsDownloadedExtractedSetExecutableSetInSystemProperty(DesiredCapabilities capabilities, String downloaded, String extracted, String echo, boolean latest) throws Exception { LocalBinaryHandler localBinaryHandler = new LocalBinaryHandler(capabilities); File resultingFile = new File(localBinaryHandler.checkAndSetBinary(true)); // verify downloaded file - should be only one File zip = new File(downloaded); assertThat(zip).exists().isFile(); assertThat(zip.getParentFile().listFiles()).hasSize(1); LocalBinarySource.assertThatCorrectFileWasDownloaded(latest, zip); assertThat(resultingFile).isEqualTo(new File(extracted)); assertThat(resultingFile.getParentFile().listFiles()).hasSize(1); Validate.isExecutable(resultingFile.getAbsolutePath(), "The file has to be an executable file, " + resultingFile); assertThat(System.getProperty(LocalBinaryHandler.LOCAL_SOURCE_SYSTEM_BINARY_PROPERTY)).isEqualTo(extracted); if (!PlatformUtils.isWindows()) { runScriptAndCheck(extracted, echo); } } private void runScriptAndCheck(String script, String expected) { PrintStream stdOut = System.out; ByteArrayOutputStream outContent = new ByteArrayOutputStream(); System.setOut(new PrintStream(outContent)); Spacelift .task(CommandTool.class) .command(new CommandBuilder(script)) .runAsDaemon() .interaction(new BinaryInteraction() .outputPrefix("[Local Source] ") .printToOut(".*") .build()) .execute().awaitAtMost(5, TimeUnit.SECONDS); System.setOut(stdOut); assertThat(outContent.toString().trim()).isEqualTo("[Local Source] " + expected); } private String getDownloadedPath(String version, String fileName) { return TEST_DRONE_CACHE_DIRECTORY + File.separator + LocalBinaryHandler.LOCAL_SOURCE_CACHE_SUBDIR + File.separator + version + File.separator + fileName; } private String getExtractedPath(File originalFile) { return Constants.DRONE_TARGET_DIRECTORY + BinaryFilesUtils.getMd5hash(originalFile) + File.separator + LocalBinarySource.FILE_NAME; } }