Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/e2e.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ JDK, so `java` can only come from what vfox installs:
build number `PreUse` finds among the installed versions) and the
asdf-style `<long-name>-<version>[-fx]` (`java@temurin-21.0.8+9`,
rewritten to `21.0.8+9-tem`; `java@openjdk-25.0.2+10` to `25.0.2+10`).
So does the release padded with a zero, as SDKMAN writes releases
(`java@21.0.8.0-tem`, `java@21.0.8.0+9-tem`), which `vfox install` must
first find already installed: `PreInstall` passes the zero on to Foojay,
which leaves it out, while `PreUse` looked for an installed version
starting with the padded release and reported it not installed.

The default matrix runs every distribution against both vfox channels
(`latest`, `main`):
Expand Down
5 changes: 1 addition & 4 deletions hooks/parse_legacy_file.lua
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ function PLUGIN:ParseLegacyFile(ctx)

--- SDKMAN pads the release with zeros that Foojay, and so the installed
--- name, leaves out: 27.0.0+36 is 27+36, 25.0.1.0+8 is 25.0.1+8.
local version, build = fullVersion:match("^([^+]*)(.*)$")
while version:find("%.0$") do
version = version:sub(1, -3)
end
local version, build = installed_version.unpad(fullVersion):match("^([^+]*)(.*)$")
local majorVersion = strings.split(version, ".")[1]

--- Installed versions end in -<vendor> (OpenJDK's in nothing), then -fx for
Expand Down
17 changes: 15 additions & 2 deletions lib/installed_version.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,24 @@ function installed_version.major(installed, major, suffix)
return installed_version.newest(installed, major, "^[.+][%d.+]*$", suffix) or installed[name] and name
end

--- Returns a Java version without the zeros SDKMAN pads releases with, which
--- Foojay, and so the installed name, leaves out even when asked for them:
--- 27.0.0+36 is 27+36, 25.0.1.0 is 25.0.1.
function installed_version.unpad(version)
local release, build = version:match("^([^+]*)(.*)$")
while release:find("%.0$") do
release = release:sub(1, -3)
end
return release .. build
end

--- Returns the installed version that version .. suffix names, or nil. The
--- input may leave out the build number PreInstall found, so, like PreInstall,
--- take the newest build of a release (21.0.8-tem selects 21.0.8+9-tem) and
--- the newest release of a bare major (21-tem selects 21.0.12.1+1-tem), unless
--- the name itself is installed.
--- the name itself is installed. It may also pad the release with zeros, which
--- PreInstall passes on to Foojay: 27.0.0-librca installs, and so selects, the
--- release 27 (27+36-librca), not the newest one of the major.
function installed_version.find(installed, version, suffix)
local name = version .. suffix
if installed[name] then
Expand All @@ -95,7 +108,7 @@ function installed_version.find(installed, version, suffix)
if version:match("^%d+$") then
return installed_version.major(installed, version, suffix)
end
return installed_version.release(installed, version, suffix)
return installed_version.release(installed, installed_version.unpad(version), suffix)
end

return installed_version
15 changes: 15 additions & 0 deletions tests/e2e/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,21 @@ func Alias(distribution, installed string) (string, bool) {
return alias, true
}

// PaddedSpecs renders the pinned release padded with a zero, as SDKMAN
// writes releases (27.0.0-librca, 25.0.1.0-open), in the plugin's spelling:
// "<version>.0[-<distribution>]" and, when the installed version has a
// build number, "<version>.0+<build>[-<distribution>]" (21.0.8.0-tem,
// 21.0.8.0+9-tem). PreInstall passes the zero on to Foojay, which leaves it
// out, so both install the pinned JDK, but PreUse looked for an installed
// version starting with the padded release and found none (vfox-java#87).
func PaddedSpecs(distribution, version, installed string) []string {
specs := []string{Spec(distribution, version+".0")}
if build := buildNumber.FindString(installed); build != "" {
specs = append(specs, Spec(distribution, version+".0"+build))
}
return specs
}

// Vendor returns the java.vendor property the distribution's builds report,
// when the suite knows it.
func Vendor(distribution string) (string, bool) {
Expand Down
19 changes: 19 additions & 0 deletions tests/e2e/common/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package common

import (
"slices"
"testing"
)

Expand Down Expand Up @@ -261,6 +262,24 @@ func TestAlias(t *testing.T) {
}
}

func TestPaddedSpecs(t *testing.T) {
for _, c := range []struct {
dist, version, installed string
want []string
}{
{"open", "25.0.2", "25.0.2+10", []string{"25.0.2.0", "25.0.2.0+10"}},
{"tem", "21.0.8", "21.0.8+9-tem", []string{"21.0.8.0-tem", "21.0.8.0+9-tem"}},
{"librca-fx", "25.0.4", "25.0.4+9-librca-fx", []string{"25.0.4.0-librca-fx", "25.0.4.0+9-librca-fx"}},
{"jb", "21.0.5", "21.0.5+79248-jb", []string{"21.0.5.0-jb", "21.0.5.0+79248-jb"}},
// GraalVM's versions carry no build number.
{"graalce", "25.0.2", "25.0.2-graalce", []string{"25.0.2.0-graalce"}},
} {
if got := PaddedSpecs(c.dist, c.version, c.installed); !slices.Equal(got, c.want) {
t.Errorf("PaddedSpecs(%s, %s, %s) = %q, want %q", c.dist, c.version, c.installed, got, c.want)
}
}
}

func TestDistributionFacts(t *testing.T) {
if v, ok := Vendor("librca-fx"); !ok || v != "BellSoft" {
t.Errorf("Vendor(librca-fx) = %q, %v", v, ok)
Expand Down
15 changes: 14 additions & 1 deletion tests/e2e/linux/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ func verifyToolchain(ctx context.Context, t *testing.T, ctr tc.Container, distri
// build number PreUse finds among the installed versions;
// 3. the asdf-style <long-name>-<version>[-fx] spelling (e.g.
// java@temurin-21.0.8+9), which PreUse rewrites to <version>-<short>
// (<version> for OpenJDK, installed without a suffix).
// (<version> for OpenJDK, installed without a suffix);
// 4. the release padded with a zero, as SDKMAN writes releases (e.g.
// java@21.0.8.0-tem, java@21.0.8.0+9-tem, see common.PaddedSpecs),
// which `vfox install` must first find already installed.
//
// After each `vfox use`, java on PATH must still be the installed JDK.
func verifyPreUse(ctx context.Context, t *testing.T, ctr tc.Container, distribution, version, installed string) {
Expand All @@ -170,6 +173,16 @@ func verifyPreUse(ctx context.Context, t *testing.T, ctr tc.Container, distribut
if alias, ok := common.Alias(distribution, installed); ok {
spellings = append(spellings, alias)
}
// Foojay leaves the zero out, so PreInstall names the installed JDK and
// vfox downloads nothing.
padded := common.PaddedSpecs(distribution, version, installed)
for _, spec := range padded {
out := execRetry(ctx, t, ctr, "vfox install java@"+spec, "vfox install java@"+spec)
require.Containsf(t, common.StripANSI(out), "java@"+installed+" is already installed",
"vfox install java@%s must find the installed %s", spec, installed)
}
t.Logf("PASS vfox install java@%s finds %s installed", strings.Join(padded, ", java@"), installed)
spellings = append(spellings, padded...)
for _, spelling := range spellings {
out := execOK(ctx, t, ctr, activated("vfox use --global java@"+spelling))
require.Containsf(t, common.StripANSI(out), "Now using java@"+installed+".",
Expand Down
15 changes: 14 additions & 1 deletion tests/e2e/windows/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,10 @@ func verifyToolchain(ctx context.Context, t *testing.T, ctr tc.Container, box sl
// build number PreUse finds among the installed versions;
// 3. the asdf-style <long-name>-<version>[-fx] spelling (e.g.
// java@temurin-21.0.8+9), which PreUse rewrites to <version>-<short>
// (<version> for OpenJDK, installed without a suffix).
// (<version> for OpenJDK, installed without a suffix);
// 4. the release padded with a zero, as SDKMAN writes releases (e.g.
// java@21.0.8.0-tem, java@21.0.8.0+9-tem, see common.PaddedSpecs),
// which `vfox install` must first find already installed.
//
// After each `vfox use`, java on PATH must still be the installed JDK.
func verifyPreUse(ctx context.Context, t *testing.T, ctr tc.Container, box slotBox, activation, distribution, version, installed string) {
Expand All @@ -183,6 +186,16 @@ func verifyPreUse(ctx context.Context, t *testing.T, ctr tc.Container, box slotB
if alias, ok := common.Alias(distribution, installed); ok {
spellings = append(spellings, alias)
}
// Foojay leaves the zero out, so PreInstall names the installed JDK and
// vfox downloads nothing.
padded := common.PaddedSpecs(distribution, version, installed)
for _, spec := range padded {
out := execRetry(ctx, t, ctr, "vfox install java@"+spec, "vfox install "+pwshQuote("java@"+spec), box.vars...)
require.Containsf(t, common.StripANSI(out), "java@"+installed+" is already installed",
"vfox install java@%s must find the installed %s", spec, installed)
}
t.Logf("PASS vfox install java@%s finds %s installed", strings.Join(padded, ", java@"), installed)
spellings = append(spellings, padded...)
for _, spelling := range spellings {
out := execOK(ctx, t, ctr, activated(activation, "vfox use --global "+pwshQuote("java@"+spelling)), box.vars...)
require.Containsf(t, common.StripANSI(out), "Now using java@"+installed+".",
Expand Down
24 changes: 24 additions & 0 deletions tests/pre_use_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ for _, version in ipairs({
"21.0.12.1+1-tem",
"25.0.4+9-librca",
"25.0.4+9-librca-fx",
"27+36-librca",
"27+36-librca-fx",
"21.0.5+63130-jb",
"21.0.5+79248-jb",
"17.0.12-graal",
Expand All @@ -34,6 +36,7 @@ for _, version in ipairs({
"21.0.12+8-lnxabi2-fx",
-- OpenJDK versions carry no distribution suffix.
"25.0.2+10",
"25.0.1+8",
"21+35",
"21.0.2+13",
"28-ea+18",
Expand Down Expand Up @@ -89,6 +92,27 @@ local cases = {
{ "25.0.2-open-fx", "25.0.2-fx" },
{ "17-open", "17" },
{ "28-open", "28" },
-- A release padded with zeros, as SDKMAN writes it, selects what PreInstall
-- installs for it, as Foojay leaves the zeros out (vfox-java#87): that
-- release, not the newest one of its major (21.0.0-open is 21+35).
{ "27.0.0-librca", "27+36-librca" },
{ "27.0.0+36-librca", "27+36-librca" },
{ "27.0-librca", "27+36-librca" },
{ "27.0.0-librca-fx", "27+36-librca-fx" },
{ "liberica-27.0.0+36-fx", "27+36-librca-fx" },
{ "21.0.8.0-tem", "21.0.8+9-tem" },
{ "21.0.8.0+9-tem", "21.0.8+9-tem" },
{ "21.0.12.0-tem", "21.0.12+8-tem" },
{ "17.0.12.0-graal", "17.0.12-graal" },
{ "25.0.1.0-open", "25.0.1+8" },
{ "25.0.1.0", "25.0.1+8" },
{ "openjdk-25.0.1.0+8", "25.0.1+8" },
{ "21.0.0-open", "21+35" },
{ "21.0.0", "21+35" },
-- Padded or not, never another build or an EA build.
{ "21.0.8.0+7-tem", "21.0.8.0+7-tem" },
{ "27.0.0+35-librca", "27.0.0+35-librca" },
{ "26.0.0-graal", "26.0.0-graal" },
}
for _, case in ipairs(cases) do
local result = PLUGIN:PreUse({ version = case[1], installedSdks = installed })
Expand Down
Loading