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