1 /*
  2  * Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 8044767 8139067 8210408 8263202
 27  * @summary Basic tests for ResourceBundle with modules:
 28  *          1) Named module "test" contains resource bundles for root and en,
 29  *          and separate named modules "eubundles" and "asiabundles" contain
 30  *          other resource bundles.
 31  *          2) ResourceBundle.getBundle caller is in named module "test",
 32  *          resource bundles are grouped in main (module "mainbundles"),
 33  *          EU (module "eubundles"), and Asia (module "asiabundles").
 34  *          3) ResourceBundle.getBundle caller is in named module "test" and all
 35  *          resource bundles are in single named module "bundles".
 36  *          4) ResourceBundle.getBundle caller is in named module "test" and all
 37  *          resource bundles in xml format are in single named module "bundles".
 38  *          5) Resource bundles in a local named module with no ResourceBundleProviders.
 39  * @library /test/lib
 40  *          ..
 41  * @build jdk.test.lib.JDKToolLauncher
 42  *        jdk.test.lib.Utils
 43  *        jdk.test.lib.compiler.CompilerUtils
 44  *        jdk.test.lib.process.ProcessTools
 45  *        ModuleTestUtil
 46  * @run junit/timeout=200 BasicTest
 47  */
 48 
 49 import java.nio.file.Path;
 50 import java.nio.file.Paths;
 51 import java.util.List;
 52 
 53 import jdk.test.lib.JDKToolLauncher;
 54 import jdk.test.lib.Utils;
 55 import jdk.test.lib.compiler.CompilerUtils;
 56 import jdk.test.lib.process.ProcessTools;
 57 
 58 import static jdk.test.lib.Asserts.assertEquals;
 59 import static org.junit.jupiter.api.Assertions.assertTrue;
 60 import org.junit.jupiter.api.Test;
 61 import org.junit.jupiter.api.TestInstance;
 62 import org.junit.jupiter.params.ParameterizedTest;
 63 import org.junit.jupiter.params.provider.MethodSource;
 64 
 65 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 66 public class BasicTest {
 67     private static final String SRC_DIR_APPBASIC = "srcAppbasic";
 68     private static final String SRC_DIR_APPBASIC2 = "srcAppbasic2";
 69     private static final String SRC_DIR_BASIC = "srcBasic";
 70     private static final String SRC_DIR_SIMPLE = "srcSimple";
 71     private static final String SRC_DIR_XML = "srcXml";
 72     private static final String SRC_DIR_MODLOCAL = "srcModlocal";
 73 
 74     private static final String MODS_DIR_APPBASIC = "modsAppbasic";
 75     private static final String MODS_DIR_APPBASIC2 = "modsAppbasic2";
 76     private static final String MODS_DIR_BASIC = "modsBasic";
 77     private static final String MODS_DIR_SIMPLE = "modsSimple";
 78     private static final String MODS_DIR_XML = "modsXml";
 79     private static final String MODS_DIR_MODLOCAL = "modsModlocal";
 80 
 81     private static final String EXTRA_JAR_BASIC = "extra_basic.jar";
 82     private static final String EXTRA_JAR_MODLOCAL = "extra_modlocal.jar";
 83 
 84     private static final List<String> LOCALE_LIST = List.of("de", "fr", "ja",
 85             "zh-tw", "en", "de");
 86     private static final List<String> LOCALE_LIST_BASIC = List.of("de", "fr",
 87             "ja", "ja-jp", "zh-tw", "en", "de", "ja-jp", "in", "yi");
 88 
 89     private static final List<String> MODULE_LIST = List.of("asiabundles",
 90             "eubundles", "test");
 91     private static final List<String> MODULE_LIST_BASIC = List.of("mainbundles",
 92             "asiabundles", "eubundles", "test");
 93     private static final List<String> MODULE_LIST_SIMPLE = List.of("bundles", "test");
 94 
 95     private static final String MAIN = "test/jdk.test.Main";
 96 
 97     Object[][] basicTestData() {
 98         return new Object[][] {
 99                 // Named module "test" contains resource bundles for root and en,
100                 // and separate named modules "eubundles" and "asiabundles"
101                 // contain other resource bundles.
102                 {SRC_DIR_APPBASIC, MODS_DIR_APPBASIC, MODULE_LIST, LOCALE_LIST,
103                         ".properties"},
104                 {SRC_DIR_APPBASIC2, MODS_DIR_APPBASIC2, MODULE_LIST, LOCALE_LIST,
105                         ".properties"},
106 
107                 // Resource bundles are grouped in main (module "mainbundles"),
108                 // EU (module "eubundles"), and Asia (module "asiabundles").
109                 {SRC_DIR_BASIC, MODS_DIR_BASIC, MODULE_LIST_BASIC, LOCALE_LIST_BASIC,
110                         ".properties"},
111 
112                 // All resource bundles are in single named module "bundles".
113                 {SRC_DIR_SIMPLE, MODS_DIR_SIMPLE, MODULE_LIST_SIMPLE, LOCALE_LIST,
114                         ".properties"},
115 
116                 // All resource bundles in xml format are in single named
117                 // module "bundles".
118                 {SRC_DIR_XML, MODS_DIR_XML, MODULE_LIST_SIMPLE, LOCALE_LIST, ".xml"},
119 
120                 // Resource bundles local in named module "test".
121                 {SRC_DIR_MODLOCAL, MODS_DIR_MODLOCAL, List.of("test"), LOCALE_LIST,
122                         ".properties"},
123         };
124     }
125 
126     @ParameterizedTest
127     @MethodSource("basicTestData")
128     public void runBasicTest(String src, String mod, List<String> moduleList,
129             List<String> localeList, String resFormat) throws Throwable {
130         Path srcPath = Paths.get(Utils.TEST_SRC, src);
131         Path modPath = Paths.get(Utils.TEST_CLASSES, mod);
132         moduleList.forEach(mn -> ModuleTestUtil.prepareModule(srcPath, modPath,
133                 mn, resFormat));
134         ModuleTestUtil.runModule(modPath.toString(), MAIN, localeList);
135         ModuleTestUtil.runModuleWithLegacyCode(modPath.toString(), MAIN, localeList);
136     }
137 
138     @Test
139     public void RunBasicTestWithCp() throws Throwable {
140         Path jarPath = Paths.get(Utils.TEST_CLASSES, EXTRA_JAR_BASIC);
141         Path srcPath = Paths.get(Utils.TEST_SRC, SRC_DIR_BASIC);
142         Path modPath = Paths.get(Utils.TEST_CLASSES, MODS_DIR_BASIC);
143         Path classPath = Paths.get(Utils.TEST_CLASSES).resolve("classes")
144                 .resolve("basic");
145 
146         jarBasic(srcPath, classPath, jarPath);
147         // jdk.test.Main should NOT load bundles from the jar file specified
148         // by the class-path.
149         ModuleTestUtil.runModuleWithCp(jarPath.toString(), modPath.toString(),
150                 MAIN, List.of("es", "vi"), false);
151     }
152 
153     @Test
154     public void runModLocalTestWithCp() throws Throwable {
155         Path jarPath = Paths.get(Utils.TEST_CLASSES, EXTRA_JAR_MODLOCAL);
156         Path srcPath = Paths.get(Utils.TEST_SRC, SRC_DIR_MODLOCAL);
157         Path modPath = Paths.get(Utils.TEST_CLASSES, MODS_DIR_MODLOCAL);
158 
159         jarModLocal(srcPath, jarPath);
160         // jdk.test.Main should load bundles from the jar file specified by
161         // the class-path.
162         ModuleTestUtil.runModuleWithCp(jarPath.toString(), modPath.toString(),
163                 MAIN, List.of("vi"), true);
164     }
165 
166     /**
167      * Create extra_basic.jar to be added to the class path. It contains .class
168      * and .properties resource bundles.
169      */
170     private static void jarBasic(Path srcPath, Path classPath, Path jarPath)
171             throws Throwable {
172         boolean compiled = CompilerUtils.compile(srcPath.resolve("extra"),
173                 classPath);
174         assertTrue(compiled, "Compile Java files for extra_basic.jar failed.");
175 
176         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar");
177         launcher.addToolArg("-cf")
178                 .addToolArg(jarPath.toString())
179                 .addToolArg("-C")
180                 .addToolArg(classPath.toString())
181                 .addToolArg("jdk/test/resources/eu")
182                 .addToolArg("-C")
183                 .addToolArg(srcPath.resolve("extra").toString())
184                 .addToolArg("jdk/test/resources/asia");
185 
186         int exitCode = ProcessTools.executeCommand(launcher.getCommand())
187                 .getExitValue();
188         assertEquals(exitCode, 0, "Create extra_basic.jar failed. "
189                 + "Unexpected exit code: " + exitCode);
190     }
191 
192     /**
193      * Create extra_modlocal.jar to be added to the class path. Expected
194      * properties files are picked up from the class path.
195      */
196     private static void jarModLocal(Path srcPath, Path jarPath) throws Throwable {
197         JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar");
198         launcher.addToolArg("-cf")
199                 .addToolArg(jarPath.toString())
200                 .addToolArg("-C")
201                 .addToolArg(srcPath.resolve("extra").toString())
202                 .addToolArg("jdk/test/resources");
203 
204         int exitCode = ProcessTools.executeCommand(launcher.getCommand())
205                 .getExitValue();
206         assertEquals(exitCode, 0, "Create extra_modlocal.jar failed. "
207                 + "Unexpected exit code: " + exitCode);
208     }
209 }