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