Skip to content

Commit

Permalink
[FIXED JENKINS-23505] Ensure correct package for OS X version is inst…
Browse files Browse the repository at this point in the history
…alled.
  • Loading branch information
orrc committed Jun 21, 2014
1 parent 28b85d6 commit 2bc19be
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 9 deletions.
44 changes: 35 additions & 9 deletions src/main/java/org/jenkinsci/plugins/golang/GolangInstaller.java
@@ -1,5 +1,6 @@
package org.jenkinsci.plugins.golang;

import com.google.common.annotations.VisibleForTesting;
import hudson.Extension;
import hudson.FilePath;
import hudson.model.DownloadService;
Expand All @@ -15,6 +16,8 @@

import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -71,12 +74,21 @@ private Installable getInstallable(Node node) throws IOException, InterruptedExc

// Gather properties for the node to install on
String[] properties = node.getChannel().call(new GetSystemProperties("os.name", "os.arch", "os.version"));
String platform = getPlatform(properties[0]);
String architecture = getArchitecture(properties[1]);
String osVersion = properties[2];

// Search for an appropriate variant
for (GolangInstallable i : release.variants) {
// Get the best matching install candidate for this node
return getInstallCandidate(release, properties[0], properties[1], properties[2]);
}

@VisibleForTesting
static GolangInstallable getInstallCandidate(GolangRelease release, String osName, String osArch, String osVersion)
throws InstallationFailedException {
String platform = getPlatform(osName);
String architecture = getArchitecture(osArch);

// Sort and search for an appropriate variant
List<GolangInstallable> variants = Arrays.asList(release.variants);
Collections.sort(variants);
for (GolangInstallable i : variants) {
if (i.os.equals(platform) && i.arch.equals(architecture)) {
if (i.osxversion == null) {
return i;
Expand All @@ -87,8 +99,8 @@ private Installable getInstallable(Node node) throws IOException, InterruptedExc
}
}

String osWithVersion = osVersion == null ? properties[0] : String.format("%s %s", properties[0], osVersion);
throw new InstallationFailedException(Messages.NoInstallerForOs(release.name, osWithVersion, properties[1]));
String osWithVersion = osVersion == null ? osName : String.format("%s %s", osName, osVersion);
throw new InstallationFailedException(Messages.NoInstallerForOs(release.name, osWithVersion, osArch));
}

private GolangRelease getConfiguredRelease() {
Expand Down Expand Up @@ -151,10 +163,24 @@ public static class GolangRelease {
}

// Needs to be public for JSON deserialisation
public static class GolangInstallable extends DownloadFromUrlInstaller.Installable {
public static class GolangInstallable extends Installable implements Comparable<GolangInstallable> {
public String os;
public String osxversion;
public String arch;

public int compareTo(GolangInstallable o) {
// Sort by OS X version, descending
if (osxversion != null && o.osxversion != null) {
return new VersionNumber(o.osxversion).compareTo(new VersionNumber(osxversion));
}
// Otherwise we don't really care; sort by OS name
return os.compareTo(o.os);
}

@Override
public String toString() {
return String.format("GolangInstallable[os=%s, arch=%s, version=%s]", os, arch, osxversion);
}
}

/** @return The OS value used in a Go archive filename, for the given {@code os.name} value. */
Expand Down Expand Up @@ -207,7 +233,7 @@ public String[] call() {
}

// Extend IOException so we can throw and stop the build if installation fails
private static class InstallationFailedException extends IOException {
static class InstallationFailedException extends IOException {
InstallationFailedException(String message) {
super(message);
}
Expand Down
@@ -0,0 +1,94 @@
package org.jenkinsci.plugins.golang;

import org.junit.Test;

import static org.jenkinsci.plugins.golang.GolangInstaller.GolangInstallable;
import static org.jenkinsci.plugins.golang.GolangInstaller.GolangRelease;
import static org.jenkinsci.plugins.golang.GolangInstaller.InstallationFailedException;
import static org.junit.Assert.assertEquals;

public class GolangInstallerTest {

private static final GolangInstallable LINUX_32 = createPackage("linux", "386", null);
private static final GolangInstallable LINUX_64 = createPackage("linux", "amd64", null);
private static final GolangInstallable OS_X_10_6 = createPackage("darwin", "amd64", "10.6");
private static final GolangInstallable OS_X_10_8 = createPackage("darwin", "amd64", "10.8");

@Test(expected = InstallationFailedException.class)
public void testUnsupportedOs() throws InstallationFailedException {
// Given we have configured a release we want to install
GolangRelease release = createReleaseInfo();

// When we try to get the install package for an OS which is not supported
GolangInstaller.getInstallCandidate(release, "Android", "armv7a", null);

// Then an exception should be thrown
}

@Test
public void testLatestPackageForOsXVersionReturned() throws InstallationFailedException {
// Given we have configured a release we want to install
GolangRelease release = createReleaseInfo();

// When we try to get the install package for a much newer OS X version
GolangInstallable pkg = GolangInstaller.getInstallCandidate(release, "Mac OS X", "x86_64", "10.11.12");

// Then we should get the newest package which is older than our version
assertEquals("Got unexpected package", OS_X_10_8, pkg);
}

@Test
public void testEarlierPackageForOsXVersionReturned() throws InstallationFailedException {
// Given we have configured a release we want to install
GolangRelease release = createReleaseInfo();

// When we try to get the install package for an older, but supported OS X version
GolangInstallable pkg = GolangInstaller.getInstallCandidate(release, "Mac OS X", "x86_64", "10.7");

// Then we should get the newest package which is older than our version
assertEquals("Got unexpected package", OS_X_10_6, pkg);
}

@Test
public void testExactMatchPackageForOsXVersionReturned() throws InstallationFailedException {
// Given we have configured a release we want to install
GolangRelease release = createReleaseInfo();

// When we try to get a install package which has an exact match on OS X version
GolangInstallable pkg = GolangInstaller.getInstallCandidate(release, "Mac OS X", "x86_64", "10.6");

// Then we should get the package which matches the given version exactly
assertEquals("Got unexpected package", OS_X_10_6, pkg);
}

@Test(expected = InstallationFailedException.class)
public void testUnsupportedOsXVersion() throws InstallationFailedException {
// Given we have configured a release we want to install
GolangRelease release = createReleaseInfo();

// When we try to get a install package which has an exact match on OS X version
GolangInstallable pkg = GolangInstaller.getInstallCandidate(release, "Mac OS X", "x86_64", "10.5");

// Then an exception should be thrown
}

private static GolangRelease createReleaseInfo() {
GolangRelease release = new GolangRelease();
release.variants = new GolangInstallable[] {
LINUX_32,
LINUX_64,
OS_X_10_6,
OS_X_10_8
};
return release;
}

private static GolangInstallable createPackage(String os, String arch, String osxVersion) {
GolangInstallable pkg = new GolangInstallable();
pkg.os = os;
pkg.arch = arch;
pkg.osxversion = osxVersion;
return pkg;
}

}

0 comments on commit 2bc19be

Please sign in to comment.