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 AOT_TOOL_OPTIONS environment variable
 28  * @requires vm.cds
 29  * @requires vm.flagless
 30  * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
 31  * @build Hello
 32  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar hello.jar Hello
 33  * @run driver AOTToolOptions
 34  */
 35 
 36 import java.io.File;
 37 import java.nio.file.Files;
 38 import java.nio.file.Path;
 39 import jdk.test.lib.cds.CDSTestUtils;
 40 import jdk.test.lib.helpers.ClassFileInstaller;
 41 import jdk.test.lib.process.OutputAnalyzer;
 42 import jdk.test.lib.process.ProcessTools;
 43 
 44 public class AOTToolOptions {
 45     static String appJar = ClassFileInstaller.getJarPath("hello.jar");
 46     static String aotConfigFile = "hello.aotconfig";
 47     static String aotCacheFile = "hello.aot";
 48     static String helloClass = "Hello";
 49 
 50     public static void main(String[] args) throws Exception {
 51         //----------------------------------------------------------------------
 52         printTestCase("AOT_TOOL_OPTIONS (one-command training)");
 53 
 54         ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
 55             "-XX:AOTMode=record",
 56             "-XX:AOTCacheOutput=" + aotCacheFile,
 57             "-Xlog:cds=debug",
 58             "-cp", appJar, helloClass);
 59         // The "-Xshare:off" below should be treated as part of a property value and not
 60         // a VM option by itself
 61         pb.environment().put("AOT_TOOL_OPTIONS", "-Dsome.option='foo -Xshare:off ' -Xmx512m -XX:-AOTClassLinking");
 62         OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "ontstep-train");
 63         out.shouldContain("Hello World");
 64         out.shouldContain("AOTCache creation is complete: hello.aot");
 65         out.shouldContain("Picked up AOT_TOOL_OPTIONS: -Dsome.option='foo -Xshare:off '");
 66         checkAOTClassLinkingDisabled(out);
 67 
 68         //----------------------------------------------------------------------
 69         printTestCase("AOT_TOOL_OPTIONS (two-command training)");
 70         pb = ProcessTools.createLimitedTestJavaProcessBuilder(
 71             "-XX:AOTMode=record",
 72             "-XX:AOTConfiguration=" + aotConfigFile,
 73             "-Xlog:cds=debug",
 74             "-cp", appJar, helloClass);
 75 
 76         out = CDSTestUtils.executeAndLog(pb, "train");
 77         out.shouldContain("Hello World");
 78         out.shouldContain("AOTConfiguration recorded: " + aotConfigFile);
 79         out.shouldHaveExitValue(0);
 80 
 81         //----------------------------------------------------------------------
 82         pb = ProcessTools.createLimitedTestJavaProcessBuilder(
 83             "-XX:AOTMode=create",
 84             "-XX:AOTConfiguration=" + aotConfigFile,
 85             "-XX:AOTCache=" + aotCacheFile,
 86             "-Xlog:cds",
 87             "-cp", appJar);
 88         pb.environment().put("AOT_TOOL_OPTIONS", "-XX:-AOTClassLinking");
 89         out = CDSTestUtils.executeAndLog(pb, "asm");
 90         out.shouldContain("Picked up AOT_TOOL_OPTIONS:");
 91         checkAOTClassLinkingDisabled(out);
 92 
 93         //----------------------------------------------------------------------
 94         printTestCase("AOT_TOOL_OPTIONS (with AOTMode specified in -XX:VMOptionsFile)");
 95         String optionsFile = "opts.txt";
 96         Files.writeString(Path.of(optionsFile), "-XX:AOTMode=create");
 97 
 98         pb = ProcessTools.createLimitedTestJavaProcessBuilder(
 99             "-XX:VMOptionsFile=" + optionsFile,
100             "-XX:AOTConfiguration=" + aotConfigFile,
101             "-XX:AOTCache=" + aotCacheFile,
102             "-Xlog:cds",
103             "-cp", appJar);
104         pb.environment().put("AOT_TOOL_OPTIONS", "-XX:-AOTClassLinking");
105         out = CDSTestUtils.executeAndLog(pb, "asm");
106         out.shouldContain("Picked up AOT_TOOL_OPTIONS:");
107         checkAOTClassLinkingDisabled(out);
108 
109         //----------------------------------------------------------------------
110         printTestCase("Using -XX:VMOptionsFile inside AOT_TOOL_OPTIONS)");
111         Files.writeString(Path.of(optionsFile), "-XX:-AOTClassLinking");
112 
113         pb = ProcessTools.createLimitedTestJavaProcessBuilder(
114             "-XX:AOTMode=create",
115             "-XX:AOTConfiguration=" + aotConfigFile,
116             "-XX:AOTCache=" + aotCacheFile,
117             "-Xlog:cds",
118             "-cp", appJar);
119         pb.environment().put("AOT_TOOL_OPTIONS", "-XX:VMOptionsFile="  + optionsFile);
120         out = CDSTestUtils.executeAndLog(pb, "asm");
121         out.shouldContain("Picked up AOT_TOOL_OPTIONS:");
122         checkAOTClassLinkingDisabled(out);
123     }
124 
125     static void checkAOTClassLinkingDisabled(OutputAnalyzer out) {
126         out.shouldMatch("aot-linked =[ ]+0,"); // -XX:-AOTClassLinking should take effect
127         out.shouldNotMatch("aot-linked =[ ]+[1-9]");
128         out.shouldHaveExitValue(0);
129     }
130 
131     static int testNum = 0;
132     static void printTestCase(String s) {
133         System.out.println("vvvvvvv TEST CASE " + testNum + ": " + s + ": starts here vvvvvvv");
134         testNum++;
135     }
136 }