package org.graalvm.component.installer.commands;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import org.graalvm.component.installer.Archive;
import org.graalvm.component.installer.CommonConstants;
import org.graalvm.component.installer.DependencyException;
import org.graalvm.component.installer.FailedOperationException;
import org.graalvm.component.installer.Feedback;
import org.graalvm.component.installer.FileOperations;
import org.graalvm.component.installer.SystemUtils;
import org.graalvm.component.installer.TestBase;
import org.graalvm.component.installer.jar.JarArchive;
import org.graalvm.component.installer.jar.JarMetaLoader;
import org.graalvm.component.installer.model.ComponentInfo;
import org.graalvm.component.installer.model.ComponentRegistry;
import org.graalvm.component.installer.os.DefaultFileOperations;
import org.graalvm.component.installer.os.WindowsFileOperations;
import org.graalvm.component.installer.persist.ComponentPackageLoader;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
public class InstallerTest extends TestBase {
@Rule public ExpectedException exception = ExpectedException.none();
protected JarArchive componentJarFile;
@Rule public TemporaryFolder folder = new TemporaryFolder();
private Path targetPath;
private MockStorage storage;
private ComponentRegistry registry;
private ComponentPackageLoader loader;
private Installer installer;
private ComponentInfo componentInfo;
protected FileOperations fileOps;
private void setupComponentInstall(String relativePath) throws IOException {
File f = dataFile(relativePath).toFile();
JarFile jf = new JarFile(f);
loader = new JarMetaLoader(jf, this);
componentInfo = loader.createComponentInfo();
componentJarFile = new JarArchive(jf);
loader.loadPaths();
installer = new Installer(fb(), fileOps, componentInfo, registry, registry, componentJarFile);
installer.setInstallPath(targetPath);
installer.setLicenseRelativePath(SystemUtils.fromCommonRelative(loader.getLicensePath()));
}
private Feedback fb() {
return withBundle(Installer.class);
}
public InstallerTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() throws IOException {
targetPath = folder.newFolder("inst").toPath();
storage = new MockStorage();
registry = new ComponentRegistry(this, storage);
fileOps = SystemUtils.isWindows() ? new WindowsFileOperations() : new DefaultFileOperations();
fileOps.init(this);
fileOps.setRootPath(targetPath);
}
@After
public void tearDown() throws Exception {
if (componentJarFile != null) {
componentJarFile.close();
}
}
@Test
public void testFailRemoteComponentExisting() throws IOException {
setupComponentInstall("truffleruby2.jar");
ComponentInfo fakeInfo = new ComponentInfo("org.graalvm.ruby", "Fake ruby", "1.0");
storage.installed.add(fakeInfo);
exception.expect(DependencyException.Conflict.class);
exception.expectMessage("VERIFY_ComponentExists");
installer.setFailOnExisting(true);
installer.validateRequirements();
}
@Test
public void testFailOnExistingComponent() throws IOException {
setupComponentInstall("truffleruby2.jar");
ComponentInfo fakeInfo = new ComponentInfo("org.graalvm.ruby", "Fake ruby", "1.1");
storage.installed.add(fakeInfo);
exception.expect(DependencyException.Conflict.class);
exception.expectMessage("VERIFY_ComponentExists");
installer.setFailOnExisting(true);
installer.validateRequirements();
}
@Test
public void testDontFailOnComponentUpdate() throws IOException {
setupComponentInstall("truffleruby2.jar");
ComponentInfo fakeInfo = new ComponentInfo("org.graalvm.ruby", "Fake ruby", "0.99");
storage.installed.add(fakeInfo);
installer.setFailOnExisting(true);
installer.validateRequirements();
}
@Test
public void testSkipExistingComponent() throws IOException {
setupComponentInstall("truffleruby2.jar");
ComponentInfo fakeInfo = new ComponentInfo("org.graalvm.ruby", "Fake ruby", "1.0");
storage.installed.add(fakeInfo);
installer.setFailOnExisting(false);
assertFalse("Must refuse installation", installer.validateAll());
}
@Test
public void testAcceptComponentUpgrade() throws IOException {
setupComponentInstall("truffleruby2.jar");
ComponentInfo fakeInfo = new ComponentInfo("org.graalvm.ruby", "Fake ruby", "0.32");
storage.installed.add(fakeInfo);
installer.setFailOnExisting(false);
assertTrue("Must refuse installation", installer.validateAll());
}
@Test
public void testUninstall() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
ComponentInfo savedInfo = installer.getComponentInfo();
Uninstaller uninstaller = new Uninstaller(fb(), fileOps, savedInfo, registry);
uninstaller.setInstallPath(targetPath);
uninstaller.uninstallContent();
assertFalse("All files should be removed after uninstall",
Files.list(targetPath).findAny().isPresent());
}
@Test
public void testUninstallFailsOnExtraFile() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
ComponentInfo savedInfo = installer.getComponentInfo();
Path langPath = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby"));
Path roPath = langPath.resolve(SystemUtils.fromCommonString("doc/user"));
Path uf = roPath.resolve(SystemUtils.fileName("userFile.txt"));
Files.write(uf, Arrays.asList("This file", "Should vanish"));
exception.expect(DirectoryNotEmptyException.class);
exception.expectMessage("jre/languages/ruby/doc/user".replace(SystemUtils.DELIMITER, File.separator));
Uninstaller uninstaller = new Uninstaller(fb(), fileOps, savedInfo, registry);
uninstaller.setInstallPath(targetPath);
uninstaller.uninstallContent();
fail("Shouldn't be reached");
}
@Test
public void testRecursiveDelete() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
PreRemoveProcess preRemove = new PreRemoveProcess(targetPath, fileOps, this);
Path langPath = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby"));
preRemove.deleteContentsRecursively(langPath);
assertTrue(Files.exists(langPath));
assertFalse("All files should be removed by recursive delete",
Files.list(langPath).findAny().isPresent());
}
@Test
public void testRecursiveDeleteWithReadonlyFiles() throws Exception {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("truffleruby2.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
Path langPath = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby"));
Path roPath = langPath.resolve(SystemUtils.fromCommonString("doc/legal"));
Files.setPosixFilePermissions(roPath, PosixFilePermissions.fromString("r-xr-xr-x"));
PreRemoveProcess preRemove = new PreRemoveProcess(targetPath, fileOps, this);
preRemove.deleteContentsRecursively(langPath);
assertTrue(Files.exists(langPath));
assertFalse("All files should be removed by recursive delete",
Files.list(langPath).findAny().isPresent());
}
@Test
public void testUninstallComponentWithROFiles() throws Exception {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("trufflerubyRO.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
ComponentInfo savedInfo = installer.getComponentInfo();
Uninstaller uninstaller = new Uninstaller(fb(), fileOps, savedInfo, registry);
uninstaller.setInstallPath(targetPath);
uninstaller.uninstallContent();
assertFalse("All files should be removed after uninstall",
Files.list(targetPath).findAny().isPresent());
}
@Test
public void testUninstallComponentWithUserROFiles() throws Exception {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("trufflerubyWork.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
ComponentInfo savedInfo = installer.getComponentInfo();
Path langPath = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby"));
Path roPath = langPath.resolve(SystemUtils.fromCommonString("doc/user"));
Path uf = roPath.resolve(SystemUtils.fileName("userFile.txt"));
Files.write(uf, Arrays.asList("This file", "Should vanish"));
Files.setPosixFilePermissions(uf, PosixFilePermissions.fromString("r--r-----"));
Files.setPosixFilePermissions(roPath, PosixFilePermissions.fromString("r-xr-xr-x"));
Uninstaller uninstaller = new Uninstaller(fb(), fileOps, savedInfo, registry);
uninstaller.setInstallPath(targetPath);
uninstaller.uninstallContent();
assertFalse("All files should be removed after uninstall",
Files.list(targetPath).findAny().isPresent());
}
@Test
public void testSetIgnoreFailedDeletions() throws IOException {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("truffleruby2.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
ComponentInfo savedInfo = installer.getComponentInfo();
Path p = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby/doc/legal"));
Files.setPosixFilePermissions(p, PosixFilePermissions.fromString("r--r--r--"));
Uninstaller uninstaller = new Uninstaller(fb(), fileOps, savedInfo, registry);
uninstaller.setInstallPath(targetPath);
uninstaller.setIgnoreFailedDeletions(true);
uninstaller.uninstall();
}
@Test
public void testFailedDeletionAborts() throws IOException {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("truffleruby2.jar");
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
ComponentInfo savedInfo = installer.getComponentInfo();
Path p = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby/doc/legal"));
Files.setPosixFilePermissions(p, PosixFilePermissions.fromString("r--r--r--"));
Uninstaller uninstaller = new Uninstaller(fb(), fileOps, savedInfo, registry);
uninstaller.setInstallPath(targetPath);
exception.expect(IOException.class);
uninstaller.uninstall();
}
@Test
public void testValidateRequirementsSuccess() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.validateRequirements();
}
@Test
public void testValidateRequirementsGraalVersion() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.getComponentInfo().addRequiredValue(CommonConstants.CAP_GRAALVM_VERSION, "0.33");
exception.expect(DependencyException.class);
exception.expectMessage("VERIFY_UpdateGraalVM");
installer.validateRequirements();
}
@Test
public void testValidateRequirementsGraalVersion2() throws Exception {
setupComponentInstall("truffleruby2.jar");
storage.graalInfo.put(CommonConstants.CAP_GRAALVM_VERSION, "0.30");
exception.expect(DependencyException.class);
exception.expectMessage("VERIFY_UpdateGraalVM");
installer.validateRequirements();
}
@Test
public void testValidateRequirementsDifferentJava() throws Exception {
setupComponentInstall("truffleruby2-11.jar");
exception.expect(DependencyException.class);
exception.expectMessage("VERIFY_Dependency_Failed");
installer.validateRequirements();
}
@Test
public void testValidateRequirementsJavaMatches() throws Exception {
setupComponentInstall("truffleruby2-11.jar");
storage.graalInfo.put(CommonConstants.CAP_JAVA_VERSION, "11");
installer.validateRequirements();
}
@Test
public void testSetIgnoreRequirements() throws Exception {
setupComponentInstall("truffleruby2-11.jar");
storage.graalInfo.put(CommonConstants.CAP_GRAALVM_VERSION, "0.30");
installer.setIgnoreRequirements(true);
installer.validateRequirements();
}
@Test
public void testInstall() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.setSymlinks(loader.loadSymlinks());
installer.setPermissions(loader.loadPermissions());
installer.install();
Path jreRuby = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
Path binRuby = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
assertTrue(Files.exists(jreRuby));
if (!isWindows()) {
assertTrue(Files.exists(binRuby));
}
if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
assertTrue(Files.isExecutable(jreRuby));
assertTrue(Files.isSymbolicLink(binRuby));
}
installer.revertInstall();
assertFalse("No files should be created under dry run",
Files.list(targetPath).findAny().isPresent());
}
@Test
public void testInstallOneRegularFile() throws Exception {
setupComponentInstall("truffleruby2.jar");
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/bin/ruby");
Path resultPath = installer.installOneFile(installer.translateTargetPath(entry), entry);
Path relative = targetPath.relativize(resultPath);
assertEquals(entry.getName(), SystemUtils.toCommonPath(relative));
Path check = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
assertTrue(Files.exists(check));
assertEquals(entry.getSize(), Files.size(check));
installer.revertInstall();
assertFalse(Files.exists(check));
assertFalse(Files.exists(check.getParent()));
assertFalse(Files.exists(check.getParent().getParent()));
}
@Test
public void testInstallExistingFileWillNotRevert() throws Exception {
setupComponentInstall("truffleruby2.jar");
Path existing = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
Files.createDirectories(existing.getParent());
Files.copy(dataFile("ruby"), existing);
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/bin/ruby");
Path resultPath = installer.installOneFile(installer.translateTargetPath(entry), entry);
Path relative = targetPath.relativize(resultPath);
assertEquals(entry.getName(), SystemUtils.toCommonPath(relative));
Path check = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
assertTrue(Files.exists(check));
assertEquals(entry.getSize(), Files.size(check));
installer.revertInstall();
assertTrue(Files.exists(check));
}
@Test
public void testInstallOverwrittemFileWillNotRevert() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.setReplaceDiferentFiles(true);
Path existing = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
Files.createDirectories(existing.getParent());
Files.copy(dataFile("ruby2"), existing);
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/bin/ruby");
Path resultPath = installer.installOneFile(installer.translateTargetPath(entry), entry);
Path relative = targetPath.relativize(resultPath);
assertEquals(entry.getName(), SystemUtils.toCommonPath(relative));
Path check = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
assertTrue(Files.exists(check));
assertEquals(entry.getSize(), Files.size(check));
installer.revertInstall();
assertTrue(Files.exists(check));
}
@Test
public void testInstallOneDirectory() throws Exception {
setupComponentInstall("truffleruby2.jar");
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/bin/");
installer.installOneEntry(entry);
Path check = targetPath.resolve(SystemUtils.fromCommonString("jre/bin"));
assertTrue(Files.exists(check));
assertTrue(Files.isDirectory(check));
installer.revertInstall();
assertFalse(Files.exists(check));
}
@Test
public void testInstallExistingDirectoryWillNotRevert() throws Exception {
setupComponentInstall("truffleruby2.jar");
Path existing = targetPath.resolve(SystemUtils.fromCommonString("jre/bin"));
Files.createDirectories(existing);
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/bin/");
installer.installOneEntry(entry);
Path check = targetPath.resolve(SystemUtils.fromCommonString("jre/bin"));
assertTrue(Files.exists(check));
assertTrue(Files.isDirectory(check));
installer.revertInstall();
assertTrue(Files.exists(check));
}
@Test
public void testProcessPermissions() throws Exception {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("truffleruby3.jar");
installer.unpackFiles();
Path check = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
assertFalse(Files.isExecutable(check));
installer.processPermissions();
assertFalse(Files.isExecutable(check));
installer.setPermissions(loader.loadPermissions());
installer.processPermissions();
assertTrue(Files.isExecutable(check));
assertTrue(Files.isExecutable(targetPath.resolve(
SystemUtils.fromCommonString("jre/languages/ruby/bin/ri"))));
}
@Test
public void testCreateSymlinks() throws Exception {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("truffleruby2.jar");
installer.unpackFiles();
Path check = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
assertFalse(Files.exists(check));
installer.setSymlinks(loader.loadSymlinks());
installer.createSymlinks();
assertTrue(Files.exists(check));
assertTrue(Files.isSymbolicLink(check));
Path target = Files.readSymbolicLink(check);
Path resolved = targetPath.relativize(check.resolveSibling(target).normalize());
assertEquals("jre/bin/ruby", SystemUtils.toCommonPath(resolved));
installer.revertInstall();
assertFalse(Files.exists(check));
}
@Test
public void testCheckFileReplacementSame() throws Exception {
setupComponentInstall("truffleruby2.jar");
Path existingOrig = dataFile("ruby");
Path existing = expandedFolder.newFile("testCheckFileReplacementSame-ruby").toPath();
Files.write(existing, (String.join("\n", Files.readAllLines(existingOrig)) + "\n").getBytes("UTF-8"));
Archive.FileEntry je = componentJarFile.getJarEntry("jre/bin/ruby");
installer.checkFileReplacement(existing, je);
}
@Test
public void testCheckFileReplacementDifferent() throws Exception {
setupComponentInstall("truffleruby2.jar");
Path existing = dataFile("ruby2");
Archive.FileEntry je = componentJarFile.getJarEntry("jre/bin/ruby");
exception.expect(FailedOperationException.class);
exception.expectMessage("INSTALL_ReplacedFileDiffers");
installer.checkFileReplacement(existing, je);
}
@Test
public void testCheckFileReplacementForced() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.setReplaceDiferentFiles(true);
Path existing = dataFile("ruby2");
Archive.FileEntry je = componentJarFile.getJarEntry("jre/bin/ruby");
installer.checkFileReplacement(existing, je);
}
@Test
public void testSetDryRun() throws IOException {
setupComponentInstall("truffleruby2.jar");
installer.setDryRun(true);
installer.setPermissions(loader.loadPermissions());
installer.setSymlinks(loader.loadSymlinks());
installer.install();
assertFalse("No files should be created under dry run",
Files.list(targetPath).findAny().isPresent());
}
@Test
public void testValidateFiles() throws Exception {
setupComponentInstall("truffleruby2.jar");
installer.validateFiles();
installer.setSymlinks(loader.loadSymlinks());
installer.setPermissions(loader.loadPermissions());
installer.validateAll();
}
@Test
public void testValidateOverwriteDirectoryWithFile() throws IOException {
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
Files.createDirectories(offending);
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/bin/ruby");
exception.expect(IOException.class);
exception.expectMessage("INSTALL_OverwriteWithFile");
installer.validateOneEntry(
installer.translateTargetPath(entry), entry);
}
@Test
public void testValidateOverwriteFileWithDirectory() throws IOException {
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby"));
Files.createDirectories(offending.getParent());
Files.createFile(offending);
Archive.FileEntry entry = componentJarFile.getJarEntry("jre/languages/ruby/");
exception.expect(IOException.class);
exception.expectMessage("INSTALL_OverwriteWithDirectory");
installer.validateOneEntry(
installer.translateTargetPath(entry), entry);
}
@Test
public void testRevertInstallFailureFile() throws Exception {
if (isWindows()) {
return;
}
setupComponentInstall("truffleruby2.jar");
Path jreRuby = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
Files.createDirectories(jreRuby.getParent());
installer.install();
assertTrue(Files.exists(jreRuby));
Files.setPosixFilePermissions(
jreRuby.getParent(), PosixFilePermissions.fromString("r-xr-xr-x"));
try {
class FD extends FeedbackAdapter {
List<String> errors = new ArrayList<>();
@Override
public void error(String key, Throwable t, Object... params) {
errors.add(key);
}
}
FD fd = new FD();
delegateFeedback(fd);
installer.revertInstall();
assertTrue(fd.errors.isEmpty());
assertFalse(Files.exists(jreRuby));
} finally {
Files.setPosixFilePermissions(
jreRuby.getParent(), PosixFilePermissions.fromString("rwxrwxrwx"));
}
}
@Test
public void testRevertInstallFailureDir() throws Exception {
if (isWindows()) {
return;
}
setupComponentInstall("truffleruby2.jar");
Path jreLang = targetPath.resolve(SystemUtils.fromCommonString("jre/languages"));
Files.createDirectories(jreLang);
installer.install();
assertTrue(Files.exists(jreLang));
Files.setPosixFilePermissions(
jreLang, PosixFilePermissions.fromString("r-xr-xr-x"));
try {
class FD extends FeedbackAdapter {
List<String> errors = new ArrayList<>();
@Override
public void error(String key, Throwable t, Object... params) {
errors.add(key);
}
}
FD fd = new FD();
delegateFeedback(fd);
installer.revertInstall();
assertTrue(fd.errors.isEmpty());
assertFalse(Files.list(jreLang).iterator().hasNext());
} finally {
Files.setPosixFilePermissions(
jreLang, PosixFilePermissions.fromString("rwxrwxrwx"));
}
}
@Test
public void testUnpackExistingSymlinks() throws Exception {
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
return;
}
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
Files.createDirectories(offending.getParent());
Files.createSymbolicLink(offending, SystemUtils.fromCommonString("../jre/bin/ruby"));
Path offending2 = targetPath.resolve(SystemUtils.fromCommonString("jre/languages/ruby/bin/ruby"));
Files.createDirectories(offending2.getParent());
Files.createSymbolicLink(offending2, SystemUtils.fileName("xxx"));
installer.setReplaceDiferentFiles(true);
installer.setSymlinks(loader.loadSymlinks());
installer.createSymlinks();
List<String> paths = componentInfo.getPaths();
assertTrue(paths.contains("bin/ruby"));
assertTrue(paths.contains("jre/languages/ruby/bin/ruby"));
assertEquals(SystemUtils.fileName("truffleruby"), Files.readSymbolicLink(offending2));
}
@Test
public void testFailOverwriteFileWithSymlink() throws Exception {
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
Files.createDirectories(offending.getParent());
Files.createFile(offending);
exception.expect(IOException.class);
exception.expectMessage("INSTALL_OverwriteWithLink");
installer.setSymlinks(loader.loadSymlinks());
installer.validateSymlinks();
}
@Test
public void testOverwriteFileWithSymlink() throws Exception {
if (isWindows()) {
return;
}
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
Files.createDirectories(offending.getParent());
Files.createSymbolicLink(offending, targetPath.resolve(SystemUtils.fromCommonString("../jre/bin/ruby")));
installer.setReplaceDiferentFiles(true);
installer.setSymlinks(loader.loadSymlinks());
installer.validateSymlinks();
}
@Test
public void testFailOverwriteOtherSymlink() throws Exception {
if (isWindows()) {
return;
}
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
Files.createDirectories(offending.getParent());
Files.createSymbolicLink(offending, targetPath.resolve(SystemUtils.fromCommonString("../x")));
exception.expect(FailedOperationException.class);
exception.expectMessage("INSTALL_ReplacedFileDiffers");
installer.setSymlinks(loader.loadSymlinks());
installer.validateSymlinks();
}
@Test
public void testOverwriteOtherSymlink() throws Exception {
if (isWindows()) {
return;
}
setupComponentInstall("truffleruby2.jar");
Path offending = targetPath.resolve(SystemUtils.fromCommonString("bin/ruby"));
Files.createDirectories(offending.getParent());
Files.createSymbolicLink(offending, targetPath.resolve(SystemUtils.fromCommonString("../x")));
installer.setSymlinks(loader.loadSymlinks());
installer.setReplaceDiferentFiles(true);
installer.validateSymlinks();
}
@Test
public void testComponentRegistryNotWrittenTo() throws Exception {
setupComponentInstall("trufflerubyWork.jar");
installer.setSymlinks(loader.loadSymlinks());
installer.setPermissions(loader.loadPermissions());
installer.install();
Path p = targetPath.resolve(SystemUtils.fromCommonString(CommonConstants.PATH_COMPONENT_STORAGE));
Path rubyMeta = p.resolve("org.graalvm.ruby.meta");
Path other = p.resolve("other");
Path pythonList = p.resolve("python.list");
assertFalse(Files.exists(rubyMeta));
assertFalse(Files.exists(pythonList));
assertTrue(Files.exists(other));
}
private static final String BLOCKED_CONTENT = "This is a blocked file";
private static final String INSTALL_CONTENT = "Test content: ./jre/bin/ruby";
@Test
public void testOverwriteBlockedFile() throws Exception {
Path blockedFile = targetPath.resolve(SystemUtils.fromCommonString("jre/bin/ruby"));
Files.createDirectories(blockedFile.getParent());
Files.write(blockedFile, Arrays.asList(BLOCKED_CONTENT));
BlockedFileOps blockedOps = new BlockedFileOps();
fileOps = blockedOps;
fileOps.init(this);
fileOps.setRootPath(targetPath);
blockedOps.blockedPaths.add(blockedFile);
Path delayDeletes = folder.newFile("delayDeletes").toPath();
Path copiedFiles = folder.newFile("copiedDirs").toPath();
blockedOps.setDelayDeletedList(delayDeletes);
blockedOps.setCopyContents(copiedFiles);
setupComponentInstall("trufflerubyWork.jar");
installer.setSymlinks(loader.loadSymlinks());
installer.setPermissions(loader.loadPermissions());
installer.setReplaceDiferentFiles(true);
installer.install();
assertTrue(blockedOps.getDelayDeletedPaths().isEmpty());
Map<Path, Path> copies = blockedOps.getCopiedPaths();
Path copyDir = targetPath.resolve(SystemUtils.fromCommonString("jre/bin.new"));
Path copyFile = copyDir.resolve("ruby");
assertEquals(1, copies.size());
assertEquals(copyDir, copies.get(blockedFile.getParent()));
assertEquals(BLOCKED_CONTENT, Files.readAllLines(blockedFile).get(0));
assertEquals(INSTALL_CONTENT, Files.readAllLines(copyFile).get(0));
assertTrue(blockedOps.flush());
assertEquals(0, Files.readAllLines(delayDeletes).size());
String l = blockedFile.getParent().toString() + "|" + copyDir.toString();
assertEquals(l, Files.readAllLines(copiedFiles).get(0));
}
}