Skip to content

Commit 5ffc13f

Browse files
authored
IBM Semeru (OpenJ9) Support (#289)
1 parent 669e072 commit 5ffc13f

File tree

10 files changed

+7937
-5048
lines changed

10 files changed

+7937
-5048
lines changed

.github/workflows/e2e-versions.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
'zulu',
2929
'liberica',
3030
'microsoft',
31+
'semeru',
3132
'corretto'
3233
] # internally 'adopt-hotspot' is the same as 'adopt'
3334
version: ['8', '11', '16']
@@ -199,7 +200,7 @@ jobs:
199200
fail-fast: false
200201
matrix:
201202
os: [macos-latest, windows-latest, ubuntu-latest]
202-
distribution: ['temurin', 'zulu', 'liberica']
203+
distribution: ['temurin', 'zulu', 'liberica', 'semeru']
203204
java-package: ['jre']
204205
version: ['17.0']
205206
include:

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,6 @@ typings/
9494
# DynamoDB Local files
9595
.dynamodb/
9696
.vscode/
97+
98+
# IntelliJ / WebStorm
99+
/.idea/

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,12 @@ Currently, the following distributions are supported:
103103
| `liberica` | Liberica JDK | [Link](https://bell-sw.com/) | [Link](https://bell-sw.com/liberica_eula/) |
104104
| `microsoft` | Microsoft Build of OpenJDK | [Link](https://www.microsoft.com/openjdk) | [Link](https://docs.microsoft.com/java/openjdk/faq)
105105
| `corretto` | Amazon Corretto Build of OpenJDK | [Link](https://aws.amazon.com/corretto/) | [Link](https://aws.amazon.com/corretto/faqs/)
106+
| `semeru` | IBM Semeru Runtime Open Edition | [Link](https://developer.ibm.com/languages/java/semeru-runtimes/downloads/) | [Link](https://openjdk.java.net/legal/gplv2+ce.html) |
106107
| `oracle` | Oracle JDK | [Link](https://www.oracle.com/java/technologies/downloads/) | [Link](https://java.com/freeuselicense)
107108

108109
**NOTE:** The different distributors can provide discrepant list of available versions / supported configurations. Please refer to the official documentation to see the list of supported versions.
109110

110-
**NOTE:** AdoptOpenJDK got moved to Eclipse Temurin and won't be updated anymore. It is highly recommended to migrate workflows from `adopt` to `temurin` to keep receiving software and security updates. See more details in the [Good-bye AdoptOpenJDK post](https://blog.adoptopenjdk.net/2021/08/goodbye-adoptopenjdk-hello-adoptium/).
111+
**NOTE:** AdoptOpenJDK got moved to Eclipse Temurin and won't be updated anymore. It is highly recommended to migrate workflows from `adopt` and `adopt-openj9`, to `temurin` and `semeru` respectively, to keep receiving software and security updates. See more details in the [Good-bye AdoptOpenJDK post](https://blog.adoptopenjdk.net/2021/08/goodbye-adoptopenjdk-hello-adoptium/).
111112

112113
**NOTE:** For Azul Zulu OpenJDK architectures x64 and arm64 are mapped to x86 / arm with proper hw_bitness.
113114

__tests__/data/semeru.json

Lines changed: 2168 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
import {HttpClient} from '@actions/http-client';
2+
3+
import {JavaInstallerOptions} from '../../src/distributions/base-models';
4+
import {SemeruDistribution} from '../../src/distributions/semeru/installer';
5+
6+
import manifestData from '../data/semeru.json';
7+
8+
describe('getAvailableVersions', () => {
9+
let spyHttpClient: jest.SpyInstance;
10+
11+
beforeEach(() => {
12+
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
13+
spyHttpClient.mockReturnValue({
14+
statusCode: 200,
15+
headers: {},
16+
result: []
17+
});
18+
});
19+
20+
afterEach(() => {
21+
jest.resetAllMocks();
22+
jest.clearAllMocks();
23+
jest.restoreAllMocks();
24+
});
25+
26+
it.each([
27+
[
28+
{
29+
version: '16',
30+
architecture: 'x64',
31+
packageType: 'jdk',
32+
checkLatest: false
33+
},
34+
'os=mac&architecture=x64&image_type=jdk&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
35+
],
36+
[
37+
{
38+
version: '16',
39+
architecture: 'x86',
40+
packageType: 'jdk',
41+
checkLatest: false
42+
},
43+
'os=mac&architecture=x86&image_type=jdk&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
44+
],
45+
[
46+
{
47+
version: '16',
48+
architecture: 'x64',
49+
packageType: 'jre',
50+
checkLatest: false
51+
},
52+
'os=mac&architecture=x64&image_type=jre&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
53+
],
54+
[
55+
{
56+
version: '16',
57+
architecture: 'x64',
58+
packageType: 'jdk',
59+
checkLatest: false
60+
},
61+
'os=mac&architecture=x64&image_type=jdk&release_type=ga&jvm_impl=openj9&page_size=20&page=0'
62+
]
63+
])(
64+
'build correct url for %s',
65+
async (installerOptions: JavaInstallerOptions, expectedParameters) => {
66+
const distribution = new SemeruDistribution(installerOptions);
67+
const baseUrl =
68+
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D';
69+
const expectedUrl = `${baseUrl}?project=jdk&vendor=ibm&heap_size=normal&sort_method=DEFAULT&sort_order=DESC&${expectedParameters}`;
70+
distribution['getPlatformOption'] = () => 'mac';
71+
72+
await distribution['getAvailableVersions']();
73+
74+
expect(spyHttpClient.mock.calls).toHaveLength(1);
75+
expect(spyHttpClient.mock.calls[0][0]).toBe(expectedUrl);
76+
}
77+
);
78+
79+
it('load available versions', async () => {
80+
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
81+
spyHttpClient
82+
.mockReturnValueOnce({
83+
statusCode: 200,
84+
headers: {},
85+
result: manifestData as any
86+
})
87+
.mockReturnValueOnce({
88+
statusCode: 200,
89+
headers: {},
90+
result: manifestData as any
91+
})
92+
.mockReturnValueOnce({
93+
statusCode: 200,
94+
headers: {},
95+
result: []
96+
});
97+
98+
const distribution = new SemeruDistribution({
99+
version: '8',
100+
architecture: 'x64',
101+
packageType: 'jdk',
102+
checkLatest: false
103+
});
104+
const availableVersions = await distribution['getAvailableVersions']();
105+
expect(availableVersions).not.toBeNull();
106+
expect(availableVersions.length).toBe(manifestData.length * 2);
107+
});
108+
109+
it.each([
110+
['jdk', 'Java_IBM_Semeru_jdk'],
111+
['jre', 'Java_IBM_Semeru_jre']
112+
])('find right toolchain folder', (packageType: string, expected: string) => {
113+
const distribution = new SemeruDistribution({
114+
version: '8',
115+
architecture: 'x64',
116+
packageType: packageType,
117+
checkLatest: false
118+
});
119+
120+
// @ts-ignore - because it is protected
121+
expect(distribution.toolcacheFolderName).toBe(expected);
122+
});
123+
});
124+
125+
describe('findPackageForDownload', () => {
126+
it.each([
127+
['8', '8.0.322+6'],
128+
['16', '16.0.2+7'],
129+
['16.0', '16.0.2+7'],
130+
['16.0.2', '16.0.2+7'],
131+
['8.x', '8.0.322+6'],
132+
['x', '17.0.2+8']
133+
])('version is resolved correctly %s -> %s', async (input, expected) => {
134+
const distribution = new SemeruDistribution({
135+
version: '8',
136+
architecture: 'x64',
137+
packageType: 'jdk',
138+
checkLatest: false
139+
});
140+
distribution['getAvailableVersions'] = async () => manifestData as any;
141+
const resolvedVersion = await distribution['findPackageForDownload'](input);
142+
expect(resolvedVersion.version).toBe(expected);
143+
});
144+
145+
it('version is found but binaries list is empty', async () => {
146+
const distribution = new SemeruDistribution({
147+
version: '9.0.8',
148+
architecture: 'x64',
149+
packageType: 'jdk',
150+
checkLatest: false
151+
});
152+
distribution['getAvailableVersions'] = async () => manifestData as any;
153+
await expect(
154+
distribution['findPackageForDownload']('9.0.8')
155+
).rejects.toThrow(/Could not find satisfied version for SemVer */);
156+
});
157+
158+
it('version is not found', async () => {
159+
const distribution = new SemeruDistribution({
160+
version: '7.x',
161+
architecture: 'x64',
162+
packageType: 'jdk',
163+
checkLatest: false
164+
});
165+
distribution['getAvailableVersions'] = async () => manifestData as any;
166+
await expect(distribution['findPackageForDownload']('7.x')).rejects.toThrow(
167+
/Could not find satisfied version for SemVer */
168+
);
169+
});
170+
171+
it('version list is empty', async () => {
172+
const distribution = new SemeruDistribution({
173+
version: '8',
174+
architecture: 'x64',
175+
packageType: 'jdk',
176+
checkLatest: false
177+
});
178+
distribution['getAvailableVersions'] = async () => [];
179+
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
180+
/Could not find satisfied version for SemVer */
181+
);
182+
});
183+
184+
it.each(['x64', 'x86', 'ppc64le', 'ppc64', 's390x', 'aarch64'])(
185+
'correct Semeru `%s` architecture resolves',
186+
async (arch: string) => {
187+
const distribution = new SemeruDistribution({
188+
version: '8',
189+
architecture: arch,
190+
packageType: 'jdk',
191+
checkLatest: false
192+
});
193+
distribution['getAvailableVersions'] = async () => manifestData as any;
194+
const resolvedVersion = await distribution['findPackageForDownload']('8');
195+
expect(resolvedVersion.version).not.toBeNull();
196+
}
197+
);
198+
199+
it.each(['zos', 'z/OS', 'z/os', 'test0987654321=', '++=++', 'myArch'])(
200+
'incorrect Semeru `%s` architecture throws',
201+
async (arch: string) => {
202+
const distribution = new SemeruDistribution({
203+
version: '8',
204+
architecture: arch,
205+
packageType: 'jdk',
206+
checkLatest: false
207+
});
208+
distribution['getAvailableVersions'] = async () => [];
209+
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
210+
`Unsupported architecture for IBM Semeru: ${arch}, the following are supported: x64, x86, ppc64le, ppc64, s390x, aarch64`
211+
);
212+
}
213+
);
214+
215+
it.each(['9-ea', '17-ea', '8-ea', '4-ea'])(
216+
'early access version are illegal for Semeru (%s)',
217+
async (version: string) => {
218+
const distribution = new SemeruDistribution({
219+
version: version,
220+
architecture: 'x64',
221+
packageType: 'jdk',
222+
checkLatest: false
223+
});
224+
distribution['getAvailableVersions'] = async () => manifestData as any;
225+
await expect(
226+
distribution['findPackageForDownload'](version)
227+
).rejects.toThrow(
228+
'IBM Semeru does not provide builds for early access versions'
229+
);
230+
}
231+
);
232+
233+
it.each([
234+
'jdk+fx',
235+
'jre+fx',
236+
'test',
237+
'test2',
238+
'jdk-fx',
239+
'javafx',
240+
'jdk-javafx',
241+
'ibm',
242+
' '
243+
])(
244+
'rejects incorrect `%s` Semeru package type',
245+
async (packageType: string) => {
246+
const distribution = new SemeruDistribution({
247+
version: '8',
248+
architecture: 'x64',
249+
packageType: packageType,
250+
checkLatest: false
251+
});
252+
distribution['getAvailableVersions'] = async () => manifestData as any;
253+
await expect(distribution['findPackageForDownload']('8')).rejects.toThrow(
254+
'IBM Semeru only provide `jdk` and `jre` package types'
255+
);
256+
}
257+
);
258+
259+
it.each(['jdk', 'jre'])(
260+
'accepts correct `%s` Semeru package type',
261+
async (packageType: string) => {
262+
const distribution = new SemeruDistribution({
263+
version: '8',
264+
architecture: 'x64',
265+
packageType: packageType,
266+
checkLatest: false
267+
});
268+
distribution['getAvailableVersions'] = async () => manifestData as any;
269+
const resolvedVersion = await distribution['findPackageForDownload']('8');
270+
await expect(resolvedVersion.version).toMatch(/8[0-9.]+/);
271+
}
272+
);
273+
274+
it('fails when long release name is used', async () => {
275+
expect(
276+
() =>
277+
new SemeruDistribution({
278+
version: 'jdk-16.0.2+7_openj9-0.27.1',
279+
architecture: 'x64',
280+
packageType: 'jdk',
281+
checkLatest: false
282+
})
283+
).toThrow(
284+
"The string 'jdk-16.0.2+7_openj9-0.27.1' is not valid SemVer notation for a Java version. Please check README file for code snippets and more detailed information"
285+
);
286+
});
287+
});

0 commit comments

Comments
 (0)