package org.graalvm.component.installer.commands;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.graalvm.component.installer.BundleConstants;
import org.graalvm.component.installer.CommandInput;
import org.graalvm.component.installer.CommandTestBase;
import org.graalvm.component.installer.Commands;
import org.graalvm.component.installer.CommonConstants;
import org.graalvm.component.installer.ComponentCatalog;
import org.graalvm.component.installer.ComponentParam;
import org.graalvm.component.installer.FailedOperationException;
import org.graalvm.component.installer.UnknownVersionException;
import org.graalvm.component.installer.Version;
import org.graalvm.component.installer.model.CatalogContents;
import org.graalvm.component.installer.model.ComponentInfo;
import org.graalvm.component.installer.model.ComponentRegistry;
import org.graalvm.component.installer.model.GraalEdition;
import org.graalvm.component.installer.persist.MetadataLoader;
import org.graalvm.component.installer.persist.ProxyResource;
import org.graalvm.component.installer.persist.test.Handler;
import org.graalvm.component.installer.remote.CatalogIterable;
import org.graalvm.component.installer.remote.RemoteCatalogDownloader;
import org.junit.After;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Rule;
import org.junit.Test;
public class UpgradeTest extends CommandTestBase {
private UpgradeProcess helper;
private RemoteCatalogDownloader downloader;
private Version initVersion(String s) throws IOException {
return initVersion(s, "../repo/catalog.properties");
}
private Version initVersion(String s, String catalogResource) throws IOException {
Version v = Version.fromString(s);
storage.graalInfo.put(BundleConstants.GRAAL_VERSION, s);
Path catalogPath = dataFile(catalogResource);
downloader = new RemoteCatalogDownloader(
this,
this,
catalogPath.toUri().toURL());
registry = new CatalogContents(this, downloader.getStorage(), localRegistry);
paramIterable = new CatalogIterable(this, this);
helper = new UpgradeProcess(this, this, registry);
return v;
}
@Test
public void testNoUpgrade() throws Exception {
initVersion("1.1.1-0.rc.1");
ComponentInfo info = helper.findGraalVersion(localRegistry.getGraalVersion().match(Version.Match.Type.INSTALLABLE));
assertNotNull(info);
assertEquals(localRegistry.getGraalVersion(), info.getVersion());
assertFalse(helper.prepareInstall(info));
}
@Test
public void testNoUpgradeCommand() throws Exception {
initVersion("1.1.1-0.rc.1");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
assertEquals(1, cmd.execute());
assertFalse(Files.list(getGraalHomePath().getParent()).anyMatch((fn) -> fn.getFileName().toString().contains("rc.1")));
}
@Test
public void testRefuseDowngradeComponentsFail() throws Exception {
initVersion("1.1.0.1");
ComponentInfo info = helper.findGraalVersion(
Version.fromString("1.0.0.0").match(Version.Match.Type.EXACT));
assertNull(info);
}
@Test
public void testRefuseDowngradeFromCommandline() throws Exception {
exception.expect(FailedOperationException.class);
exception.expectMessage("UPGRADE_CannotDowngrade");
initVersion("1.1.0.1");
textParams.add("1.0.0.0");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
cmd.execute();
}
@Test
public void testUpgradeToCompatibleVersion() throws Exception {
initVersion("1.0.0.0");
textParams.add("1.0.1");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
helper.resetExistingComponents();
ComponentInfo info = helper.findGraalVersion(
Version.fromString("1.0.1").match(Version.Match.Type.COMPATIBLE));
assertNotNull(info);
assertEquals("1.0.1.0", info.getVersion().toString());
}
@Test
public void testUpgradeToCompatibleVersionCommandline() throws Exception {
initVersion("1.0.0.0");
textParams.add("1.0.1");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
assertEquals(0, cmd.execute());
ComponentRegistry newReg = cmd.getProcess().getNewGraalRegistry();
ComponentInfo ruby = newReg.findComponent("ruby");
assertEquals("1.0.1.1", ruby.getVersion().toString());
}
@Test
public void testRefuseUpgradeUnsatisfiedComponent() throws Exception {
exception.expect(FailedOperationException.class);
exception.expectMessage("UPGRADE_ComponentsCannotMigrate");
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
helper.resetExistingComponents();
ComponentInfo info = helper.findGraalVersion(
Version.fromString("1.1.0").match(Version.Match.Type.COMPATIBLE));
assertNotNull(info);
}
@Test
public void testRefuseUnsatisfiedCommandline() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
textParams.add("1.1.0");
storage.installed.add(ci);
exception.expect(FailedOperationException.class);
exception.expectMessage("UPGRADE_ComponentsCannotMigrate");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
cmd.execute();
}
@Test
public void testUpgradeToNewestAvailable() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
cmd.execute();
Version installedGraalVMVersion = cmd.getProcess().getNewGraalRegistry().getGraalVersion();
Version installedRubyVersion = cmd.getProcess().getNewGraalRegistry().findComponent("ruby").getVersion();
assertEquals("1.0.1.0", installedGraalVMVersion.toString());
assertEquals("1.0.1.1", installedRubyVersion.toString());
}
@Test
public void testIgnoreUnsatisfiedComponent() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
helper.resetExistingComponents();
helper.setAllowMissing(true);
ComponentInfo info = helper.findGraalVersion(
Version.fromString("1.1.0").match(Version.Match.Type.COMPATIBLE));
assertNotNull(info);
assertEquals("1.1.0.1", info.getVersion().toString());
}
@Test
public void testIgnoreUnsatisfiedComponentCommandline() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
options.put(Commands.OPTION_IGNORE_MISSING_COMPONENTS, "");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
cmd.execute();
Version installedGraalVMVersion = cmd.getProcess().getNewGraalRegistry().getGraalVersion();
assertEquals("1.1.1-0.rc.1", installedGraalVMVersion.originalString());
assertNull("Ruby should not be migrated", cmd.getProcess().getNewGraalRegistry().findComponent("ruby"));
}
@Test
public void testInstallWithoutCoreUpgrade() throws Exception {
initVersion("1.0.1.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.1.0");
storage.installed.add(ci);
helper.resetExistingComponents();
ComponentInfo info = helper.findGraalVersion(
Version.fromString("1.0.1").match(Version.Match.Type.COMPATIBLE));
assertNotNull(info);
boolean inst = helper.installGraalCore(info);
assertFalse(inst);
}
@Test
public void testInstallNewWithoutCoreUpgrade() throws Exception {
initVersion("1.0.1.0");
textParams.add("ruby");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
helper = cmd.getProcess();
ComponentInfo info = cmd.configureProcess();
assertNotNull(info);
assertFalse(helper.installGraalCore(info));
assertNull(helper.getTargetInfo());
assertEquals(getLocalRegistry().getGraalVersion(), info.getVersion());
List<ComponentParam> toDownload = helper.allComponents();
assertEquals(1, toDownload.size());
assertEquals("org.graalvm.ruby", toDownload.get(0).getShortName());
}
@Test
public void testInstallMinorUpdate() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand(false);
cmd.init(this, this);
ComponentInfo info = cmd.configureProcess();
assertFalse(cmd.getProcess().prepareInstall(info));
}
@Test
public void testRefuseNonAdminUpgrade() throws Exception {
initVersion("1.0.0.0");
storage.writableUser = "hero";
textParams.add("1.0.1");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
exception.expect(FailedOperationException.class);
exception.expectMessage("ADMIN");
cmd.execute();
}
@Test
public void testUpgradeExistingComponent() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
textParams.add("ruby");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
helper = cmd.getProcess();
ComponentInfo info = cmd.configureProcess();
assertNotNull(info);
assertEquals(Version.fromString("1.0.1"), info.getVersion());
}
@Test
public void testInstallIntoExistingNonempty() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
textParams.add("ruby");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
helper = cmd.getProcess();
ComponentInfo info = cmd.configureProcess();
Path p = getGraalHomePath().normalize();
Path ndir = graalVMDirectory(p, "1.0.1");
Files.createDirectories(ndir);
Files.write(ndir.resolve("some-content"), Arrays.asList("Fail"));
exception.expect(FailedOperationException.class);
exception.expectMessage("UPGRADE_TargetExistsNotEmpty");
helper.prepareInstall(info);
}
private Path graalVMDirectory(Path sibling, String version) {
return sibling.resolveSibling("graalvm-ce-java" +
getLocalRegistry().getGraalCapabilities().get(CommonConstants.CAP_JAVA_VERSION) + "-" + version);
}
@Test
public void testInstallIntoExistingRelease() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
textParams.add("ruby");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
helper = cmd.getProcess();
ComponentInfo info = cmd.configureProcess();
Path p = getGraalHomePath().normalize();
Path ndir = graalVMDirectory(p, "1.0.1");
Files.createDirectories(ndir);
Files.write(ndir.resolve("some-content"), Arrays.asList("Fail"));
Path toCopy = dataFile("../persist/release_simple.properties");
Files.copy(toCopy, ndir.resolve("release"));
exception.expect(FailedOperationException.class);
exception.expectMessage("UPGRADE_TargetExistsContainsGraalVM");
helper.prepareInstall(info);
}
@Test
public void testInstallIntoExistingEmpty() throws Exception {
initVersion("1.0.0.0");
ComponentInfo ci = new ComponentInfo("org.graalvm.ruby", "Installed Ruby", "1.0.0.0");
storage.installed.add(ci);
textParams.add("ruby");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
helper = cmd.getProcess();
ComponentInfo info = cmd.configureProcess();
Path p = getGraalHomePath().normalize();
Path ndir = graalVMDirectory(p, "1.0.1");
Files.createDirectories(ndir);
assertTrue(helper.prepareInstall(info));
}
@Test
public void testUpgradePythonMostRecent() throws Exception {
initVersion("1.0.0.0");
textParams.add("python+1.0.1");
ComponentInfo ci = new ComponentInfo("org.graalvm.python", "Installed Python", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
assertEquals(0, cmd.execute());
ComponentRegistry newReg = cmd.getProcess().getNewGraalRegistry();
ComponentInfo python = newReg.findComponent("python");
assertEquals("1.1.0.0", python.getVersion().toString());
}
@Test
public void testUpgradeExact() throws Exception {
initVersion("1.0.0.0");
textParams.add("python=1.0.1");
ComponentInfo ci = new ComponentInfo("org.graalvm.python", "Installed Python", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
assertEquals(0, cmd.execute());
ComponentRegistry newReg = cmd.getProcess().getNewGraalRegistry();
ComponentInfo python = newReg.findComponent("python");
assertEquals("1.0.1", python.getVersion().displayString());
}
@Test
public void testUpgradeToNextRC() throws Exception {
initVersion("1.0.0.0");
textParams.add("1.1.1-rc");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
assertEquals(0, cmd.execute());
ComponentRegistry newReg = cmd.getProcess().getNewGraalRegistry();
assertEquals("1.1.1.0-0.rc.1", newReg.getGraalVersion().toString());
}
@Test
public void testNoUpgradeToRCInsteadOfRelease() throws Exception {
initVersion("1.0.0.0");
textParams.add("1.1.1");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
try {
cmd.execute();
} catch (UnknownVersionException ex) {
assertNotNull(ex.getCandidate());
assertTrue(ex.getCandidate().toString().contains("rc"));
}
}
@Test
public void testUpgradeIfAllowsNewer() throws Exception {
initVersion("1.0.0.0");
textParams.add("+1.1.1");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
assertEquals(0, cmd.execute());
ComponentRegistry newReg = cmd.getProcess().getNewGraalRegistry();
assertEquals("1.1.1.0-0.rc.1", newReg.getGraalVersion().toString());
}
@Test
public void testUpgradeFromDevToSpecificVersion() throws Exception {
initVersion("1.0.0-dev");
textParams.add("1.0.1");
textParams.add("python");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
ComponentInfo graalInfo = cmd.configureProcess();
assertNotNull(graalInfo);
assertEquals("1.0.1.0", graalInfo.getVersion().toString());
assertEquals(1, cmd.getProcess().addedComponents().size());
ComponentParam p = cmd.getProcess().addedComponents().iterator().next();
ComponentInfo ci = p.createMetaLoader().getComponentInfo();
assertEquals("1.0.1.0", ci.getVersion().toString());
}
@Test
public void testUpgradeFromDevToSpecificVersion2() throws Exception {
initVersion("1.0.0-dev");
textParams.add("python=1.0.1");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
ComponentInfo graalInfo = cmd.configureProcess();
assertNotNull(graalInfo);
assertEquals("1.0.1.0", graalInfo.getVersion().toString());
assertEquals(1, cmd.getProcess().addedComponents().size());
ComponentParam p = cmd.getProcess().addedComponents().iterator().next();
ComponentInfo ci = p.createMetaLoader().getComponentInfo();
assertEquals("1.0.1.0", ci.getVersion().toString());
}
@Test
public void testUpgradeToSameVersion() throws Exception {
initVersion("1.0.0-dev");
textParams.add("1.0.0-dev");
textParams.add("python");
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
ComponentInfo graalInfo = cmd.configureProcess();
assertNotNull(graalInfo);
assertEquals("1.0.0-dev", graalInfo.getVersion().displayString());
assertEquals(1, cmd.getProcess().addedComponents().size());
ComponentParam p = cmd.getProcess().addedComponents().iterator().next();
ComponentInfo ci = p.createMetaLoader().getComponentInfo();
assertEquals("1.0.0-dev", ci.getVersion().displayString());
}
static class InstallTrampoline extends InstallCommand {
@Override
protected void prepareInstallation() throws IOException {
super.prepareInstallation();
}
@Override
protected void executionInit() throws IOException {
super.executionInit();
}
}
CatalogFactory factory;
@Override
public CatalogFactory getCatalogFactory() {
return factory != null ? factory : super.getCatalogFactory();
}
@Test
public void testUpgradeWithDependencies() throws Exception {
initVersion("1.0.0.0", "../repo/catalog-19.3.properties");
ComponentInfo ci = new ComponentInfo("org.graalvm.r", "Installed R", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
textParams.add("r");
ComponentInfo graalInfo = cmd.configureProcess();
assertNotNull(graalInfo);
assertEquals(Version.fromString("19.3.0.0"), graalInfo.getVersion());
boolean installed = cmd.getProcess().installGraalCore(graalInfo);
assertTrue(installed);
factory = new CatalogFactory() {
@Override
public ComponentCatalog createComponentCatalog(CommandInput in) {
RemoteCatalogDownloader dnl = new RemoteCatalogDownloader(in, UpgradeTest.this, downloader.getOverrideCatalogSpec());
return new CatalogContents(UpgradeTest.this, dnl.getStorage(), in.getLocalRegistry());
}
@Override
public List<GraalEdition> listEditions(ComponentRegistry targetGraalVM) {
return Collections.emptyList();
}
};
InstallTrampoline targetInstall = new InstallTrampoline();
cmd.getProcess().configureInstallCommand(targetInstall);
targetInstall.executionInit();
targetInstall.prepareInstallation();
assertTrue(targetInstall.getUnresolvedDependencies().isEmpty());
List<ComponentParam> deps = targetInstall.getDependencies();
assertEquals(1, deps.size());
MetadataLoader ldr = deps.iterator().next().createFileLoader();
assertEquals("org.graalvm.llvm-toolchain", ldr.getComponentInfo().getId());
}
@Rule public ProxyResource proxyResource = new ProxyResource();
@After
public void clearHandlerBindings() {
Handler.clear();
}
@Test
public void testUpgradeRespectsTargetCatalogURLs() throws Exception {
URL u = new URL("test://catalog-19.3.properties");
Handler.bind(u.toString(), dataFile("../repo/catalog-19.3.properties").toUri().toURL());
initVersion("1.0.0.0", "../repo/catalog-19.3.properties");
ComponentInfo ci = new ComponentInfo("org.graalvm.r", "Installed R", "1.0.0.0");
storage.installed.add(ci);
UpgradeCommand cmd = new UpgradeCommand();
cmd.init(this, this);
ComponentInfo graalInfo = cmd.configureProcess();
boolean installed = cmd.getProcess().installGraalCore(graalInfo);
assertTrue(installed);
factory = new CatalogFactory() {
@Override
public ComponentCatalog createComponentCatalog(CommandInput in) {
RemoteCatalogDownloader dnl = new RemoteCatalogDownloader(in, UpgradeTest.this, (String) null);
return new CatalogContents(UpgradeTest.this, dnl.getStorage(), in.getLocalRegistry());
}
@Override
public List<GraalEdition> listEditions(ComponentRegistry targetGraalVM) {
return Collections.emptyList();
}
};
InstallTrampoline targetInstall = new InstallTrampoline();
cmd.getProcess().configureInstallCommand(targetInstall);
targetInstall.executionInit();
targetInstall.prepareInstallation();
assertTrue(Handler.isVisited(u));
}
}