1 /*
  2  * Copyright (c) 2025, 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 /*
 26  * @test id=aot
 27  * @summary Use special characters in the name of the cache file specified by -XX:CacheDataStore.
 28  *          Make sure these characters are passed to the child JVM process that assembles the cache.
 29  * @requires vm.cds.supports.aot.class.linking
 30  * @comment work around JDK-8345635
 31  * @requires !vm.jvmci.enabled
 32  * @library /test/lib
 33  * @build SpecialCacheNames
 34  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp
 35  * @run driver SpecialCacheNames AOT --onestep-training
 36  */
 37 
 38 /*
 39  * @test id=leyden
 40  * @summary Use special characters in the name of the cache file specified by -XX:CacheDataStore.
 41  *          Make sure these characters are passed to the child JVM process that assembles the cache.
 42  * @requires vm.cds.supports.aot.class.linking
 43  * @comment work around JDK-8345635
 44  * @requires !vm.jvmci.enabled
 45  * @library /test/lib
 46  * @build SpecialCacheNames
 47  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp
 48  * @run driver SpecialCacheNames LEYDEN
 49  */
 50 
 51 import java.io.File;
 52 import jdk.test.lib.cds.CDSAppTester;
 53 import jdk.test.lib.helpers.ClassFileInstaller;
 54 import jdk.test.lib.Platform;
 55 import jdk.test.lib.process.OutputAnalyzer;
 56 
 57 public class SpecialCacheNames {
 58     static final String appJar = ClassFileInstaller.getJarPath("app.jar");
 59     static final String mainClass = "MyTestApp";
 60 
 61     public static void main(String[] args) throws Exception {
 62         test("with spaces", args);
 63         test("single'quote", args);
 64         if (!Platform.isWindows()) {
 65             // This seems to be a limitation of ProcessBuilder on Windows that has problem passing
 66             // double quote or unicode characters to a child process. As a result, we can't
 67             // even pass these parameters to the training run JVM.
 68             test("double\"quote", args);
 69             test("unicode\u202fspace", args); // Narrow No-Break Space
 70             test("unicode\u6587", args); // CJK unifed ideographs "wen" = "script"
 71         }
 72     }
 73 
 74     static void test(String name, String[] args) throws Exception {
 75         String archiveName = name + (args[0].equals("LEYDEN") ? ".cds" : ".aot");
 76 
 77         System.out.println("============================= Testing with AOT cache name: {{" + archiveName + "}}");
 78         new Tester(name, archiveName).run(args);
 79     }
 80 
 81     static class Tester extends CDSAppTester {
 82         String archiveName;
 83         public Tester(String name, String archiveName) {
 84             super(name);
 85             this.archiveName = archiveName;
 86         }
 87 
 88         @Override
 89         public String classpath(RunMode runMode) {
 90             return appJar;
 91         }
 92 
 93         @Override
 94         public String[] vmArgs(RunMode runMode) {
 95             // A space character in a training run vmarg should not break this vmarg into two.
 96             return new String[] { "-Dmy.test.prop=space -XX:FooBar" };
 97         }
 98 
 99         @Override
100         public String[] appCommandLine(RunMode runMode) {
101             return new String[] {
102                 mainClass,
103             };
104         }
105 
106         @Override
107         public void checkExecution(OutputAnalyzer out, RunMode runMode) {
108             if (runMode.isProductionRun()) {
109                 File f = new File(archiveName);
110                 if (f.exists()) {
111                     System.out.println("Found Archive {{" + archiveName + "}}");
112                 } else {
113                     throw new RuntimeException("Archive {{" + archiveName + "}} does not exist");
114                 }
115             }
116 
117             if (runMode.isApplicationExecuted()) {
118                 out.shouldContain("Hello World");
119             }
120         }
121     }
122 }
123 
124 class MyTestApp {
125     public static void main(String args[]) {
126         String s = System.getProperty("my.test.prop");
127         if (!"space -XX:FooBar".equals(s)) {
128             throw new RuntimeException("Expected \"space -XX:FooBar\" but got \"" + s + "\"");
129         }
130 
131         System.out.println("Hello World");
132     }
133 }