/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/tools/jlink/SnippetsTest.java
271 строка
11 KB
Sergey Bylokhov
8374365: Update copyright year to 2025 for test/jdk in files where it was missed
27 дек 2025, 10:02
27 дек 2025, 10:02
9512a43
Код
Авторство
О чём код?
/* * Copyright (c) 2024, 2025, 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. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * 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. */ import java.io.IOException; import java.lang.classfile.ClassBuilder; import java.lang.classfile.ClassFile; import static java.lang.classfile.ClassFile.ACC_PUBLIC; import java.lang.constant.ClassDesc; import static java.lang.constant.ConstantDescs.CD_Integer; import static java.lang.constant.ConstantDescs.CD_Object; import static java.lang.constant.ConstantDescs.CD_String; import static java.lang.constant.ConstantDescs.INIT_NAME; import static java.lang.constant.ConstantDescs.MTD_void; import java.lang.constant.MethodTypeDesc; import static java.lang.invoke.MethodHandles.lookup; import java.lang.invoke.MethodType; import java.lang.module.ModuleDescriptor; import java.lang.reflect.AccessFlag; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.*; import jdk.tools.jlink.internal.Snippets.*; /* * @test * @summary Test snippets generation for array and set. * @bug 8321413 * @enablePreview * @modules jdk.jlink/jdk.tools.jlink.internal * @run junit SnippetsTest */ public class SnippetsTest { private static final boolean WRITE_CLASS_FILE = Boolean.parseBoolean(System.getProperty("DumpArraySnippetsTestClasses", "false")); @ParameterizedTest @ValueSource(ints = { 10, 75, 90, 120, 200, 399, 400, 401}) void testLoad400StringsArray(int pageSize) { testPaginatedArray(400, pageSize); } @Test void testStringArrayLimitsWithPagination() { // Each string takes 2 constant pool slot, one for String, another for Utf8 testPaginatedArray(31_000, 8000); try { testPaginatedArray(32_000, 8000); } catch (IllegalArgumentException iae) { // expected constant pool explode } } @Test void testStringArrayLimitsWithoutPagination() { // each string array assignment takes ~8 bytes testSimpleArray(8200); try { testSimpleArray(8300); fail(); } catch (IllegalArgumentException iae) { // expected code size explode } } @Test void testLoadableEnum() { Enum<?>[] enums = { AccessFlag.FINAL, ModuleDescriptor.Requires.Modifier.MANDATED, ModuleDescriptor.Opens.Modifier.SYNTHETIC, ModuleDescriptor.Requires.Modifier.TRANSITIVE }; Snippet[] elementSnippets = Snippet.buildAll(Arrays.asList(enums), Snippet::loadEnum); var loadable = new ArraySnippetBuilder(Enum.class.describeConstable().get()) .build(elementSnippets); Supplier<Enum<?>[]> supplier = generateSupplier("LoadableEnumTest", clb -> loadable); assertArrayEquals(enums, supplier.get()); } @Test void testArraySnippetBuilder() { Integer[] expected = IntStream.range(0, 200) .boxed() .toArray(Integer[]::new); var className = "LoadableArrayOf200Paged"; var elementSnippets = Snippet.buildAll(Arrays.asList(expected), Snippet::loadInteger); var instance = new ArraySnippetBuilder(CD_Integer) .ownerClassDesc(ClassDesc.of(className)) .enablePagination("page", 100); try { instance.build(elementSnippets); fail("Should throw NPE without ClassBuilder"); } catch (NullPointerException npe) { // expected } Supplier<Integer[]> supplier = generateSupplier(className, clb -> instance.classBuilder(clb).build(elementSnippets)); verifyPaginationMethods(supplier.getClass(), Integer.class, "page", 2); assertArrayEquals(expected, supplier.get()); var loadable = instance.disablePagination() .ownerClassDesc(ClassDesc.of("LoadableArrayOf200NotPaged")) .build(elementSnippets); // SimpleArray generate bytecode inline, so can be generated in any class supplier = generateSupplier("TestLoadableArrayFactory", clb -> loadable); verifyPaginationMethods(supplier.getClass(), Integer.class, "page", 0); assertArrayEquals(expected, supplier.get()); } @Test void testSetSnippetBuilder() { String[] data = IntStream.range(0, 100) .mapToObj(i -> "SetData" + i) .toArray(String[]::new); var tiny = Set.of(data[0], data[1], data[2]); var all = Set.of(data); var setBuilder = new SetSnippetBuilder(CD_String); Supplier<Set<String>> supplier = generateSupplier("TinySetTest", clb -> setBuilder.build(Snippet.buildAll(tiny, Snippet::loadConstant))); // Set does not guarantee ordering, so not assertIterableEquals assertEquals(tiny, supplier.get()); var allSnippets = Snippet.buildAll(all, Snippet::loadConstant); supplier = generateSupplier("AllSetTestNoPage", clb -> setBuilder.build(allSnippets)); assertEquals(all, supplier.get()); var className = "AllSetTestPageNotActivated"; var methodNamePrefix = "page"; var loadable = setBuilder.disablePagination() .ownerClassDesc(ClassDesc.of(className)) .build(allSnippets); supplier = generateSupplier(className, clb -> loadable); assertEquals(all, supplier.get()); className = "AllSetTestPageSize20"; setBuilder.ownerClassDesc(ClassDesc.of(className)); supplier = generateSupplier(className, clb -> setBuilder.classBuilder(clb) .enablePagination(methodNamePrefix, 20) .build(allSnippets)); verifyPaginationMethods(supplier.getClass(), String.class, methodNamePrefix, 5); assertEquals(all, supplier.get()); } void testPaginatedArray(int elementCount, int pageSize) { String[] expected = IntStream.range(0, elementCount) .mapToObj(i -> "Package" + i) .toArray(String[]::new); var className = String.format("SnippetArrayProviderTest%dPagedBy%d", elementCount, pageSize); ClassDesc testClassDesc = ClassDesc.of(className); var builder = new ArraySnippetBuilder(CD_String) .enablePagination("ArrayPage", pageSize, 1) .ownerClassDesc(testClassDesc); var snippets = Snippet.buildAll(Arrays.asList(expected), Snippet::loadConstant); var pagingContext = new PagingContext(expected.length, pageSize); Supplier<String[]> supplier = generateSupplier(className, clb -> builder.classBuilder(clb).build(snippets)); verifyPaginationMethods(supplier.getClass(), String.class, "ArrayPage", pagingContext.pageCount()); assertEquals((elementCount % pageSize) != 0, pagingContext.isLastPagePartial()); assertArrayEquals(expected, supplier.get()); } void testSimpleArray(int elementCount) { String[] expected = IntStream.range(0, elementCount) .mapToObj(i -> "NoPage" + i) .toArray(String[]::new); String className = "SnippetArrayProviderTest" + elementCount; var array = new ArraySnippetBuilder(CD_String) .disablePagination() .build(Snippet.buildAll(Arrays.asList(expected), Snippet::loadConstant)); Supplier<String[]> supplier = generateSupplier(className, clb -> array); verifyPaginationMethods(supplier.getClass(), String.class, "page", 0); assertArrayEquals(expected, supplier.get()); } <T> Supplier<T> generateSupplier(String className, Function<ClassBuilder, Loadable> builder) { var testClassDesc = ClassDesc.of(className); byte[] classBytes = generateSupplierClass(testClassDesc, builder); try { writeClassFile(className, classBytes); var testClass = lookup().defineClass(classBytes); lookup().findVirtual(testClass, "get", MethodType.methodType(Object.class)); return (Supplier<T>) testClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } void verifyPaginationMethods(Class<?> testClass, Class<?> elementType, String methodNamePrefix, int pageCount) { var methodType = MethodType.methodType(elementType.arrayType(), elementType.arrayType()); if (pageCount <= 0) { try { lookup().findStatic(testClass, methodNamePrefix + "_0", methodType); fail("Unexpected paginate helper function"); } catch (Exception ex) {} } for (int i = 0; i < pageCount; i++) { try { lookup().findStatic(testClass, methodNamePrefix + "_" + i, methodType); } catch (Exception ex) { throw new RuntimeException(ex); } } } byte[] generateSupplierClass(ClassDesc testClassDesc, Function<ClassBuilder, Loadable> builder) { return ClassFile.of().build(testClassDesc, clb -> { clb.withSuperclass(CD_Object); clb.withInterfaceSymbols(ClassDesc.ofInternalName("java/util/function/Supplier")); clb.withMethodBody(INIT_NAME, MTD_void, ACC_PUBLIC, cob -> { cob.aload(0); cob.invokespecial(CD_Object, INIT_NAME, MTD_void); cob.return_(); }); var loadable = builder.apply(clb); clb.withMethodBody("get", MethodTypeDesc.of(CD_Object), ACC_PUBLIC, cob -> { loadable.emit(cob); cob.areturn(); }); }); } void writeClassFile(String className, byte[] classBytes) throws IOException { if (WRITE_CLASS_FILE) { Files.write(Path.of(className + ".class"), classBytes); } } }