cec222e460
Reviewed-by: alanb, ihse, mcimadamore, jlahoda, jwaters
253 lines
11 KiB
Java
253 lines
11 KiB
Java
/*
|
|
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @library /test/lib .. ./cases/modules
|
|
* @build JNativeScanTestBase
|
|
* org.singlejar/* org.lib/* org.myapp/* org.service/*
|
|
* cases.classpath.singlejar.main.Main
|
|
* cases.classpath.lib.Lib
|
|
* cases.classpath.app.App
|
|
* cases.classpath.unnamed_package.UnnamedPackage
|
|
* @run junit TestJNativeScan
|
|
*/
|
|
|
|
import jdk.test.lib.process.OutputAnalyzer;
|
|
import jdk.test.lib.util.JarUtils;
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.file.Path;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
import java.util.jar.Attributes;
|
|
import java.util.jar.Manifest;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
|
class TestJNativeScan extends JNativeScanTestBase {
|
|
|
|
static Path TEST_CLASSES;
|
|
|
|
static Path CLASS_PATH_APP;
|
|
static Path SINGLE_JAR_CLASS_PATH;
|
|
static Path SINGLE_JAR_MODULAR;
|
|
static Path ORG_MYAPP;
|
|
static Path ORG_LIB;
|
|
static Path UNNAMED_PACKAGE_JAR;
|
|
static Path LIB_JAR;
|
|
|
|
@BeforeAll
|
|
public static void before() throws IOException {
|
|
SINGLE_JAR_CLASS_PATH = Path.of("singleJar.jar");
|
|
TEST_CLASSES = Path.of(System.getProperty("test.classes", ""));
|
|
JarUtils.createJarFile(SINGLE_JAR_CLASS_PATH, TEST_CLASSES, Path.of("main", "Main.class"));
|
|
|
|
LIB_JAR = Path.of("lib.jar");
|
|
JarUtils.createJarFile(LIB_JAR, TEST_CLASSES, Path.of("lib", "Lib.class"));
|
|
Manifest manifest = new Manifest();
|
|
Attributes mainAttrs = manifest.getMainAttributes();
|
|
mainAttrs.put(Attributes.Name.MANIFEST_VERSION, "1.0"); // need version or other attributes will be ignored
|
|
mainAttrs.putValue("Class-Path", "lib.jar non-existent.jar");
|
|
CLASS_PATH_APP = Path.of("app.jar");
|
|
JarUtils.createJarFile(CLASS_PATH_APP, manifest, TEST_CLASSES, Path.of("app", "App.class"));
|
|
|
|
SINGLE_JAR_MODULAR = makeModularJar("org.singlejar");
|
|
ORG_MYAPP = makeModularJar("org.myapp");
|
|
ORG_LIB = makeModularJar("org.lib");
|
|
makeModularJar("org.service");
|
|
|
|
UNNAMED_PACKAGE_JAR = Path.of("unnamed_package.jar");
|
|
JarUtils.createJarFile(UNNAMED_PACKAGE_JAR, TEST_CLASSES, Path.of("UnnamedPackage.class"));
|
|
}
|
|
|
|
@Test
|
|
public void testSingleJarClassPath() {
|
|
assertSuccess(jnativescan("--class-path", SINGLE_JAR_CLASS_PATH.toString()))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("ALL-UNNAMED")
|
|
.stdoutShouldContain("main.Main")
|
|
.stdoutShouldContain("main.Main::m()void is a native method declaration")
|
|
.stdoutShouldContain("main.Main::main(String[])void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testSingleJarModulePath() {
|
|
assertSuccess(jnativescan("--module-path", MODULE_PATH, "--add-modules", "org.singlejar"))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("org.singlejar")
|
|
.stdoutShouldContain("org.singlejar.main.Main")
|
|
.stdoutShouldContain("org.singlejar.main.Main::m()void is a native method declaration")
|
|
.stdoutShouldContain("org.singlejar.main.Main::main(String[])void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testWithDepModule() {
|
|
assertSuccess(jnativescan("--module-path", MODULE_PATH, "--add-modules", "org.myapp"))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("org.lib")
|
|
.stdoutShouldContain("org.lib.Lib")
|
|
.stdoutShouldContain("org.lib.Lib::m()void is a native method declaration")
|
|
.stdoutShouldContain("org.lib.Lib::doIt()void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment")
|
|
.stdoutShouldContain("org.service")
|
|
.stdoutShouldContain("org.service.ServiceImpl")
|
|
.stdoutShouldContain("org.service.ServiceImpl::m()void is a native method declaration")
|
|
.stdoutShouldContain("org.service.ServiceImpl::doIt()void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testAllModulePath() {
|
|
assertSuccess(jnativescan("--module-path", MODULE_PATH, "--add-modules", "ALL-MODULE-PATH"))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("org.singlejar")
|
|
.stdoutShouldContain("org.lib")
|
|
.stdoutShouldContain("org.service");
|
|
}
|
|
|
|
@Test
|
|
public void testClassPathAttribute() {
|
|
assertSuccess(jnativescan("--class-path", CLASS_PATH_APP.toString()))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("ALL-UNNAMED")
|
|
.stdoutShouldContain("lib.Lib")
|
|
.stdoutShouldContain("lib.Lib::m()void is a native method declaration")
|
|
.stdoutShouldContain("lib.Lib::doIt()void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidRelease() {
|
|
assertFailure(jnativescan("--module-path", MODULE_PATH, "--add-modules", "ALL-MODULE-PATH", "--release", "asdf"))
|
|
.stderrShouldContain("Invalid release");
|
|
}
|
|
|
|
@Test
|
|
public void testReleaseNotSupported() {
|
|
assertFailure(jnativescan("--module-path", MODULE_PATH, "--add-modules", "ALL-MODULE-PATH", "--release", "9999999"))
|
|
.stderrShouldContain("Release: 9999999 not supported");
|
|
}
|
|
|
|
@Test
|
|
public void testFileDoesNotExist() {
|
|
assertFailure(jnativescan("--class-path", "non-existent.jar"))
|
|
.stderrShouldContain("Path does not appear to be a jar file, or directory containing classes");
|
|
}
|
|
|
|
@Test
|
|
public void testModuleNotAJarFile() {
|
|
String modulePath = moduleRoot("org.myapp").toString() + File.pathSeparator + ORG_LIB.toString();
|
|
assertSuccess(jnativescan("--module-path", modulePath,
|
|
"--add-modules", "ALL-MODULE-PATH"))
|
|
.stdoutShouldContain("lib.Lib")
|
|
.stdoutShouldContain("lib.Lib::m()void is a native method declaration")
|
|
.stdoutShouldContain("lib.Lib::doIt()void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testPrintNativeAccess() {
|
|
assertSuccess(jnativescan("--module-path", MODULE_PATH,
|
|
"-add-modules", "org.singlejar,org.myapp",
|
|
"--print-native-access"))
|
|
.stdoutShouldMatch("org.lib,org.service,org.singlejar");
|
|
}
|
|
|
|
@Test
|
|
public void testNoDuplicateNames() {
|
|
String classPath = SINGLE_JAR_CLASS_PATH + File.pathSeparator + CLASS_PATH_APP;
|
|
OutputAnalyzer output = assertSuccess(jnativescan("--class-path", classPath, "--print-native-access"));
|
|
String[] moduleNames = output.getStdout().split(",");
|
|
Set<String> names = new HashSet<>();
|
|
for (String name : moduleNames) {
|
|
assertTrue(names.add(name.strip()));
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testUnnamedPackage() {
|
|
assertSuccess(jnativescan("--class-path", UNNAMED_PACKAGE_JAR.toString()))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("ALL-UNNAMED")
|
|
.stdoutShouldNotContain(".UnnamedPackage")
|
|
.stdoutShouldContain("UnnamedPackage")
|
|
.stdoutShouldContain("UnnamedPackage::m()void is a native method declaration")
|
|
.stdoutShouldContain("UnnamedPackage::main(String[])void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testPositionalArguments() {
|
|
assertFailure(jnativescan("foo"))
|
|
.stdoutShouldBeEmpty()
|
|
.stderrShouldContain("jnativescan does not accept positional arguments");
|
|
}
|
|
|
|
@Test
|
|
public void testMissingRootModules() {
|
|
assertFailure(jnativescan("--module-path", MODULE_PATH))
|
|
.stdoutShouldBeEmpty()
|
|
.stderrShouldContain("Missing required option(s) [add-modules]");
|
|
}
|
|
|
|
@Test
|
|
public void testClassPathDirectory() {
|
|
assertSuccess(jnativescan("--class-path", TEST_CLASSES.toString()))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("ALL-UNNAMED")
|
|
.stdoutShouldContain("UnnamedPackage")
|
|
.stdoutShouldContain("UnnamedPackage::m()void is a native method declaration")
|
|
.stdoutShouldContain("UnnamedPackage::main(String[])void references restricted methods")
|
|
.stdoutShouldContain("main.Main")
|
|
.stdoutShouldContain("main.Main::m()void is a native method declaration")
|
|
.stdoutShouldContain("main.Main::main(String[])void references restricted methods")
|
|
.stdoutShouldContain("lib.Lib")
|
|
.stdoutShouldContain("lib.Lib::m()void is a native method declaration")
|
|
.stdoutShouldContain("lib.Lib::doIt()void references restricted methods")
|
|
.stdoutShouldContain("java.lang.foreign.MemorySegment::reinterpret(long)MemorySegment");
|
|
}
|
|
|
|
@Test
|
|
public void testMultipleClassPathJars() {
|
|
// make sure all of these are reported, even when they are all in the ALL-UNNAMED module
|
|
String classPath = UNNAMED_PACKAGE_JAR
|
|
+ File.pathSeparator + SINGLE_JAR_CLASS_PATH
|
|
+ File.pathSeparator + LIB_JAR;
|
|
assertSuccess(jnativescan("--class-path", classPath))
|
|
.stderrShouldBeEmpty()
|
|
.stdoutShouldContain("ALL-UNNAMED")
|
|
.stdoutShouldContain("UnnamedPackage")
|
|
.stdoutShouldContain(UNNAMED_PACKAGE_JAR.toString())
|
|
.stdoutShouldContain("lib.Lib")
|
|
.stdoutShouldContain(LIB_JAR.toString())
|
|
.stdoutShouldContain("main.Main")
|
|
.stdoutShouldContain(SINGLE_JAR_CLASS_PATH.toString());
|
|
}
|
|
}
|