/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/tools/jlink/plugins/IncludeLocalesPluginTest.java
512 строк
28 KB
Christoph Langer
8389480: GenerateJLIClassesPluginTest.java and IncludeLocalesPluginTest.java tests in tools/jlink/plugins/ fail due to AccessDeniedExceptions on Windows
11 авг 2026, 19:07
11 авг 2026, 19:07
99ece54
Код
Авторство
О чём код?
/* * Copyright (c) 2016, 2026, 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. */ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.tools.jlink.internal.LinkableRuntimeImage; import jdk.tools.jlink.internal.TaskHelper; import jdk.tools.jlink.internal.plugins.PluginsResourceBundle; import jdk.tools.jlink.plugin.PluginException; import jdk.test.lib.Platform; import jdk.test.lib.util.FileUtils; import tests.Helper; import tests.JImageGenerator; import tests.JImageValidator; import tests.Result; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; /* * @test * @bug 8152143 8152704 8155649 8165804 8185841 8176841 8190918 * 8179071 8202537 8221432 8222098 8251317 8258794 8265315 * 8296248 8306116 8174269 8347146 8346948 8354548 * @summary IncludeLocalesPlugin tests * @author Naoto Sato * @requires (vm.compMode != "Xcomp" & os.maxMemory >= 2g) * @library ../../lib /test/lib * @modules java.base/jdk.internal.jimage * jdk.jlink/jdk.tools.jlink.internal * jdk.jlink/jdk.tools.jlink.internal.plugins * jdk.jlink/jdk.tools.jlink.plugin * jdk.jlink/jdk.tools.jmod * jdk.jlink/jdk.tools.jimage * jdk.compiler * @build tests.* * @build jdk.test.lib.Platform * @build jdk.test.lib.util.FileUtils * @build tools.jlink.plugins.GetAvailableLocales * @run junit/othervm/timeout=720 -Xmx1g IncludeLocalesPluginTest */ public class IncludeLocalesPluginTest { private static final String MODULE_NAME = "IncludeLocalesTest"; private static Helper helper; private Path lastImageDir; private boolean testPassed; // Test data should include: // - --include-locales command line option // - --add-modules command line option values // - List of required resources in the result image // - List of resources that should not exist in the result image // - List of available locales in the result image // - Error message private static Stream<Arguments> testData() { return Stream.of( // without --include-locales option: should include all locales Arguments.of( "", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of(), Arrays.stream(Locale.getAvailableLocales()) // "(root)" for Locale.ROOT rather than "" .map(loc -> loc.equals(Locale.ROOT) ? "(root)" : loc.toString()) .collect(Collectors.toList()), ""), // Asterisk works exactly the same as above Arguments.of( "--include-locales=*", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of(), Arrays.stream(Locale.getAvailableLocales()) // "(root)" for Locale.ROOT rather than "" .map(loc -> loc.equals(Locale.ROOT) ? "(root)" : loc.toString()) .collect(Collectors.toList()), ""), // World English/Spanish in Latin America Arguments.of( "--include-locales=en-001,es-419", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_150.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_AT.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_es.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_es_419.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_es_AR.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), List.of( "(root)", "en", "en_001", "en_150", "en_AG", "en_AI", "en_AT", "en_AU", "en_BB", "en_BE", "en_BM", "en_BS", "en_BW", "en_BZ", "en_CC", "en_CH", "en_CK", "en_CM", "en_CX", "en_CY", "en_CZ", "en_DE", "en_DG", "en_DK", "en_DM", "en_EE", "en_ER", "en_ES", "en_FI", "en_FJ", "en_FK", "en_FM", "en_FR", "en_GB", "en_GD", "en_GE", "en_GG", "en_GH", "en_GI", "en_GM", "en_GS", "en_GY", "en_HK", "en_HU", "en_ID", "en_IE", "en_IL", "en_IM", "en_IN", "en_IO", "en_IT", "en_JE", "en_JM", "en_KE", "en_KI", "en_KN", "en_KY", "en_LC", "en_LR", "en_LS", "en_LT", "en_LV", "en_MG", "en_MO", "en_MS", "en_MT", "en_MU", "en_MV", "en_MW", "en_MY", "en_NA", "en_NF", "en_NG", "en_NL", "en_NO", "en_NR", "en_NU", "en_NZ", "en_PG", "en_PK", "en_PL", "en_PN", "en_PT", "en_PW", "en_RO", "en_RW", "en_SB", "en_SC", "en_SD", "en_SE", "en_SG", "en_SH", "en_SI", "en_SK", "en_SL", "en_SS", "en_SX", "en_SZ", "en_TC", "en_TK", "en_TO", "en_TT", "en_TV", "en_TZ", "en_UA", "en_UG", "en_US", "en_US_#Latn", "en_US_POSIX", "en_VC", "en_VG", "en_VU", "en_WS", "en_ZA", "en_ZM", "en_ZW", "es", "es_419", "es_AR", "es_BO", "es_BR", "es_BZ", "es_CL", "es_CO", "es_CR", "es_CU", "es_DO", "es_EC", "es_GT", "es_HN", "es_MX", "es_NI", "es_PA", "es_PE", "es_PR", "es_PY", "es_SV", "es_US", "es_UY", "es_VE", // CLDR's "hi-Latn" falls back to "en-001", "hi-Latn"/"hi-Latn-IN" are added // here. Since Locale.Matcher cannot handle such exceptional inheritance, // allowing to include "hi"/"hi-IN" resource files. "hi", "hi__#Latn", "hi_IN", "hi_IN_#Latn"), ""), // All English and Japanese locales Arguments.of( "--include-locales=en,ja", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( "(root)", "en", "en_001", "en_150", "en_AE", "en_AG", "en_AI", "en_AS", "en_AT", "en_AU", "en_BB", "en_BE", "en_BI", "en_BM", "en_BS", "en_BW", "en_BZ", "en_CA", "en_CC", "en_CH", "en_CK", "en_CM", "en_CX", "en_CY", "en_CZ", "en_DE", "en_DG", "en_DK", "en_DM", "en_EE", "en_ER", "en_ES", "en_FI", "en_FJ", "en_FK", "en_FM", "en_FR", "en_GB", "en_GD", "en_GE", "en_GG", "en_GH", "en_GI", "en_GM", "en_GS", "en_GU", "en_GY", "en_HK", "en_HU", "en_ID", "en_IE", "en_IL", "en_IM", "en_IN", "en_IO", "en_IT", "en_JE", "en_JM", "en_JP", "en_KE", "en_KI", "en_KN", "en_KY", "en_LC", "en_LR", "en_LS", "en_LT", "en_LV", "en_MG", "en_MH", "en_MO", "en_MP", "en_MS", "en_MT", "en_MU", "en_MV", "en_MW", "en_MY", "en_NA", "en_NF", "en_NG", "en_NL", "en_NO", "en_NR", "en_NU", "en_NZ", "en_PG", "en_PH", "en_PK", "en_PL", "en_PN", "en_PR", "en_PT", "en_PW", "en_RO", "en_RW", "en_SB", "en_SC", "en_SD", "en_SE", "en_SG", "en_SH", "en_SI", "en_SK", "en_SL", "en_SS", "en_SX", "en_SZ", "en_TC", "en_TK", "en_TO", "en_TT", "en_TV", "en_TZ", "en_UA","en_UG", "en_UM", "en_US", "en_US_#Latn", "en_US_POSIX", "en_VC", "en_VG", "en_VI", "en_VU", "en_WS", "en_ZA", "en_ZM", "en_ZW", "ja", "ja_JP", "ja_JP_#Jpan", "ja_JP_JP_#u-ca-japanese"), ""), // All locales in Austria Arguments.of( "--include-locales=*-AT", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_de.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_de_AT.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_150.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_AT.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), List.of( "(root)", "en", "en_001", "en_150", "en_AT", "en_US", "en_US_#Latn", "en_US_POSIX", "de", "de_AT"), ""), // All locales in India Arguments.of( "--include-locales=*-IN", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_IN.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class", "/jdk.localedata/sun/util/resources/cldr/ext/CalendarData_as_IN.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( "(root)", "as", "as_IN", "as_IN_#Beng", "bgc", "bgc_IN", "bgc_IN_#Deva", "bho", "bho_IN", "bho_IN_#Deva", "bn", "bn_IN", "bo", "bo_IN", "brx", "brx_IN", "brx_IN_#Deva", "ccp", "ccp_IN", "doi", "doi_IN", "doi_IN_#Deva", "en", "en_001", "en_IN", "en_US", "en_US_#Latn", "en_US_POSIX", "gu", "gu_IN", "gu_IN_#Gujr", "hi", "hi__#Latn", "hi_IN", "hi_IN_#Deva", "hi_IN_#Latn", "kn", "kn_IN", "kn_IN_#Knda", "kok", "kok__#Deva", "kok__#Latn", "kok_IN", "kok_IN_#Deva", "kok_IN_#Latn", "ks", "ks__#Arab", "ks__#Deva", "ks_IN", "ks_IN_#Arab", "ks_IN_#Deva", "kxv", "kxv_IN", "kxv_IN_#Deva", "kxv_IN_#Latn", "kxv_IN_#Orya", "kxv_IN_#Telu", "kxv__#Deva", "kxv__#Latn", "kxv__#Orya", "kxv__#Telu", "mai", "mai_IN", "mai_IN_#Deva", "mni", "mni__#Beng", "mni_IN", "mni_IN_#Beng", "ml", "ml_IN", "ml_IN_#Mlym", "mr", "mr_IN", "mr_IN_#Deva", "ne", "ne_IN", "or", "or_IN", "or_IN_#Orya", "pa", "pa__#Guru", "pa_IN", "pa_IN_#Guru", "raj", "raj_IN", "raj_IN_#Deva", "sa", "sa_IN", "sa_IN_#Deva", "sat", "sat__#Olck", "sat_IN", "sat_IN_#Olck", "sd", "sd__#Deva", "sd_IN", "sd_IN_#Deva", "ta", "ta_IN", "ta_IN_#Taml", "te", "te_IN", "te_IN_#Telu", "ur_IN", "ur", "xnr", "xnr_IN", "xnr_IN_#Deva"), ""), // Thai Arguments.of( "--include-locales=th", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class"), List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( "(root)", "en", "en_US", "en_US_#Latn", "en_US_POSIX", "th", "th_TH", "th_TH_#Thai", "th_TH_TH_#u-nu-thai"), ""), // Hong Kong Arguments.of( "--include-locales=zh-HK", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), List.of( "(root)", "en", "en_US", "en_US_#Latn", "en_US_POSIX", "zh", "zh__#Hans", "zh__#Hant", "zh_HK", "zh_HK_#Hans", "zh_HK_#Hant"), ""), // Simplified Chinese Arguments.of( "--include-locales=zh-Hans", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_zh.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), List.of( "(root)", "en", "en_US", "en_US_#Latn", "en_US_POSIX", "zh", "zh__#Latn", "zh__#Hans", "zh_CN", "zh_CN_#Latn", "zh_CN_#Hans", "zh_HK", "zh_HK_#Hans", "zh_MO", "zh_MO_#Hans", "zh_MY_#Hans", "zh_SG", "zh_SG_#Hans"), ""), // Norwegian Arguments.of( "--include-locales=nb,nn,no", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_nb.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_nn.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_no.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), List.of( "(root)", "en", "en_US", "en_US_#Latn", "en_US_POSIX", "nb", "nb_NO", "nb_NO_#Latn", "nb_SJ", "nn", "nn_NO", "nn_NO_#Latn", "no", "no_NO", "no_NO_NY", "no_NO_#Latn"), ""), // Hebrew/Indonesian/Yiddish Arguments.of( "--include-locales=he,id,yi", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_he.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_id.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_yi.class"), List.of( "/jdk.localedata/sun/text/resources/ext/LineBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/thai_dict", "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th", "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_ja.class", "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_th.class"), List.of( "(root)", "en", "en_US", "en_US_#Latn", "en_US_POSIX", "id", "id_ID", "id_ID_#Latn", "he", "he_IL", "he_IL_#Hebr", "yi", "yi_UA", "yi_UA_#Hebr"), ""), // Langtag including extensions. Should be ignored. Arguments.of( "--include-locales=en,ja-u-nu-thai", "jdk.localedata", List.of( "/jdk.localedata/sun/text/resources/cldr/ext/FormatData_en_001.class"), List.of(), List.of( "(root)", "en", "en_001", "en_150", "en_AE", "en_AG", "en_AI", "en_AS", "en_AT", "en_AU", "en_BB", "en_BE", "en_BI", "en_BM", "en_BS", "en_BW", "en_BZ", "en_CA", "en_CC", "en_CH", "en_CK", "en_CM", "en_CX", "en_CY", "en_CZ", "en_DE", "en_DG", "en_DK", "en_DM", "en_EE", "en_ER", "en_ES", "en_FI", "en_FJ", "en_FK", "en_FM", "en_FR", "en_GB", "en_GD", "en_GE", "en_GG", "en_GH", "en_GI", "en_GM", "en_GS", "en_GU", "en_GY", "en_HK", "en_HU", "en_ID", "en_IE", "en_IL", "en_IM", "en_IN", "en_IO", "en_IT", "en_JE", "en_JM", "en_JP", "en_KE", "en_KI", "en_KN", "en_KY", "en_LC", "en_LR", "en_LS", "en_LT", "en_LV", "en_MG", "en_MH", "en_MO", "en_MP", "en_MS", "en_MT", "en_MU", "en_MV", "en_MW", "en_MY", "en_NA", "en_NF", "en_NG", "en_NL", "en_NO", "en_NR", "en_NU", "en_NZ", "en_PG", "en_PH", "en_PK", "en_PL", "en_PN", "en_PR", "en_PT", "en_PW", "en_RO", "en_RW", "en_SB", "en_SC", "en_SD", "en_SE", "en_SG", "en_SH", "en_SI", "en_SK", "en_SL", "en_SS", "en_SX", "en_SZ", "en_TC", "en_TK", "en_TO", "en_TT", "en_TV", "en_TZ", "en_UA","en_UG", "en_UM", "en_US", "en_US_#Latn", "en_US_POSIX", "en_VC", "en_VG", "en_VI", "en_VU", "en_WS", "en_ZA", "en_ZM", "en_ZW"), ""), // Error case: No matching locales Arguments.of( "--include-locales=xyz", "jdk.localedata", null, null, null, new PluginException(String.format( PluginsResourceBundle.getMessage("include-locales.nomatchinglocales"), "xyz")) .getMessage()), // Error case: Invalid argument Arguments.of( "--include-locales=en,zh_HK", "jdk.localedata", null, null, null, new PluginException(String.format( PluginsResourceBundle.getMessage("include-locales.invalidtag"), "zh_hk")) .getMessage()), // Error case: jdk.localedata is not added Arguments.of( "--include-locales=en-US", "java.base", null, null, null, new PluginException( PluginsResourceBundle.getMessage("include-locales.localedatanotfound")) .getMessage()) ); } @BeforeAll public static void setup() throws IOException { boolean isLinkableRuntime = LinkableRuntimeImage.isLinkableRuntime(); System.out.println("Running test on " + (isLinkableRuntime ? "enabled" : "disabled") + " capability of linking from the run-time image."); System.out.println("Default module-path, 'jmods', " + (Helper.jdkHasPackagedModules() ? "" : "NOT ") + "present."); helper = Helper.newHelper(isLinkableRuntime); assertNotNull(helper, "Helper could not be initialized"); } @ParameterizedTest @MethodSource("testData") public void launch(String optIncludeLocales, String optAddModules, List<String> requiredRes, List<String> shouldNotExistRes, List<String> availableLocs, String errorMsg) throws Exception { testPassed = false; // create image for each test data Result result; lastImageDir = helper.createNewImageDir(MODULE_NAME); if (optIncludeLocales.isEmpty()) { System.out.println("Invoking jlink with no --include-locales option"); result = JImageGenerator.getJLinkTask() .output(lastImageDir) .option("--strip-debug") .addMods(optAddModules) .call(); } else { System.out.println("Invoking jlink with \"" + optIncludeLocales + "\""); result = JImageGenerator.getJLinkTask() .output(lastImageDir) .option("--strip-debug") .addMods(optAddModules) .option(optIncludeLocales) .call(); } if (errorMsg.isEmpty()) { Path image = result.assertSuccess(); // test locale data entries testLocaleDataEntries(image, requiredRes, shouldNotExistRes); // test available locales testAvailableLocales(image, availableLocs); } else { result.assertFailure(new TaskHelper(TaskHelper.JLINK_BUNDLE) .getMessage("error.prefix") + " " +errorMsg); System.out.println("\tExpected failure: " + result.getMessage()); } testPassed = true; } @AfterEach public void cleanup() { if (testPassed && lastImageDir != null && Files.exists(lastImageDir)) { // On Windows, the java.exe process spawned by testAvailableLocales() may // hold open handles to files even after waitFor() returns. // Use a non-throwing cleanup method but tolerate failures. Just log them. List<IOException> failures = FileUtils.deleteFileTreeUnchecked(lastImageDir); if (!failures.isEmpty()) { System.err.println("WARNING: cleanup of " + lastImageDir + " incomplete:"); failures.forEach(e -> System.err.println(" " + e)); } } } private static void testLocaleDataEntries(Path image, List<String> expectedLocations, List<String> unexpectedPaths) throws Exception { System.out.println("testLocaleDataEntries:"); try { JImageValidator.validate( image.resolve("lib").resolve("modules"), expectedLocations, unexpectedPaths); } catch (Exception e) { fail("\tFailed with: " + e); } } private static void testAvailableLocales(Path image, List<String> availableLocales) throws Exception { System.out.println("testAvailableLocales:"); Path launcher = image.resolve("bin/java" + (Platform.isWindows() ? ".exe" : "")); List<String> args = new ArrayList<>(availableLocales.size() + 2); args.add(launcher.toString()); args.add("GetAvailableLocales"); args.addAll(availableLocales); Process proc = new ProcessBuilder(args).inheritIO().start(); int len = Math.min(10, args.size()); String command = args.subList(0, len).stream().collect(Collectors.joining(" ")) + (len < availableLocales.size() ? " ..." : ""); int status = proc.waitFor(); assertTrue(status == 0, "\tExit " + status + "\t" + command); System.out.println("\tDone\t" + command); System.out.println(); } }