1 /*
  2  * Copyright (c) 2023, 2024, 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 /*
 27  * @test id=static
 28  * @requires vm.cds
 29  * @summary run Spring Pet Clinic demo with the classic static archive workflow
 30  * @library /test/lib
 31  * @run driver/timeout=120 SpringPetClinic STATIC
 32  */
 33 
 34 /*
 35  * @test id=dynamic
 36  * @requires vm.cds
 37  * @summary run Spring Pet Clinic demo with the classic dynamic archive workflow
 38  * @library /test/lib
 39  * @run driver/timeout=120 SpringPetClinic DYNAMIC
 40  */
 41 
 42 /*
 43  * @test id=leyden
 44  * @requires vm.cds
 45  * @requires vm.cds.write.archived.java.heap
 46  * @summary run Spring Pet Clinic demo with leyden-premain "new workflow"
 47  * @library /test/lib
 48  * @run driver/timeout=120 SpringPetClinic LEYDEN
 49  */
 50 
 51 /*
 52  * @test id=leyden_old
 53  * @requires vm.cds
 54  * @requires vm.cds.write.archived.java.heap
 55  * @summary run Spring Pet Clinic demo with leyden-premain
 56  * @library /test/lib
 57  * @run driver/timeout=120 SpringPetClinic LEYDEN_OLD
 58  */
 59 
 60 
 61 import java.io.BufferedInputStream;
 62 import java.io.BufferedOutputStream;
 63 import java.io.BufferedReader;
 64 import java.io.File;
 65 import java.io.FileOutputStream;
 66 import java.nio.file.Path;
 67 import java.util.Enumeration;
 68 import java.util.Map;
 69 import java.util.zip.ZipEntry;
 70 import java.util.zip.ZipFile;
 71 import jdk.test.lib.StringArrayUtils;
 72 import jdk.test.lib.artifacts.Artifact;
 73 import jdk.test.lib.artifacts.ArtifactResolver;
 74 import jdk.test.lib.cds.CDSAppTester;
 75 import jdk.test.lib.process.OutputAnalyzer;
 76 
 77 // NOTE: if you have not set up an artifactory, you can create spring-petclinic-3.2.0.zip by:
 78 //
 79 // - Make a clone of https://github.com/openjdk/leyden/tree/premain
 80 // - Change to the directory test/hotspot/jtreg/premain/spring-petclinic
 81 // - Edit the Makefile
 82 // - Run the command "make unpack"
 83 //
 84 // Then, you can add the following to your jtreg command-line to run the test cases in this directory:
 85 // -vmoption:-Djdk.test.lib.artifacts.spring-petclinic=/repo/test/hotspot/jtreg/premain/spring-petclinic/petclinic-snapshot/target/spring-petclinic-3.2.0.zip
 86 
 87 @Artifact(organization = "org.springframework.samples", name = "spring-petclinic", revision = "3.2.0", extension = "zip", unpack = false)
 88 public class SpringPetClinic {
 89     public static void main(String args[]) throws Exception {
 90         String cp = getArtifact();
 91         SpringPetClinicTester tester = new SpringPetClinicTester(cp);
 92         tester.run(args);
 93     }
 94 
 95     private static String getArtifact() throws Exception {
 96         File cpFile = new File("petclinic-snapshot/target/unpacked/classpath");
 97         if (!cpFile.exists()) {
 98             long started = System.currentTimeMillis();
 99             System.out.println("Download and extract spring-petclinic");
100 
101             Map<String, Path> artifacts = ArtifactResolver.resolve(SpringPetClinic.class);
102             System.out.println(artifacts);
103             Path zip = artifacts.get("org.springframework.samples.spring-petclinic-3.2.0");
104 
105             long elapsed = System.currentTimeMillis() - started;
106             System.out.println("Resolved artifacts in " + elapsed + " ms");
107 
108             extractZip(zip.toString(), new File("."));
109         }
110 
111         return "@" + cpFile.toString();
112     }
113 
114     static void extractZip(String srcFile, File outDir) throws Exception {
115         long zipSize = (new File(srcFile)).length();
116         System.out.println("Extracting from " + srcFile + " (" + zipSize + " bytes) to " + outDir);
117 
118         long started = System.currentTimeMillis();
119         try (ZipFile zipFile = new ZipFile(srcFile)) {
120             int numFiles = 0;
121             long numBytes = 0;
122             Enumeration<? extends ZipEntry> e = zipFile.entries();
123 
124             byte buffer[] = new byte[1024];
125             while (e.hasMoreElements()) {
126                 ZipEntry entry = e.nextElement();
127                 if (!entry.isDirectory()) {
128                     File destinationPath = new File(outDir, entry.getName());
129                     destinationPath.getParentFile().mkdirs();
130 
131                     numFiles ++;
132                     try (
133                          BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
134                          FileOutputStream fos = new FileOutputStream(destinationPath);
135                          BufferedOutputStream bos = new BufferedOutputStream(fos, 1024)) {
136                         int n;
137                         while ((n = bis.read(buffer, 0, 1024)) != -1) {
138                             bos.write(buffer, 0, n);
139                             numBytes += n;
140                         }
141                     }
142                 }
143             }
144             long elapsed = System.currentTimeMillis() - started;
145             System.out.println("Extracted " + numFiles + " file(s) = " + numBytes + " bytes in " + elapsed + " ms");
146         }
147     }
148 
149 
150     static class SpringPetClinicTester extends CDSAppTester {
151         String cp;
152 
153         SpringPetClinicTester(String cp) {
154             super("SpringPetClinic");
155             this.cp = cp;
156         }
157 
158         @Override
159         public String[] vmArgs(RunMode runMode) {
160             return new String[] {
161                 "-Xlog:init",
162                 "-DautoQuit=true",
163                 "-Dspring.output.ansi.enabled=NEVER",
164                 "-Dspring.aot.enabled=true",
165                 "-Dserver.port=0", // use system-assigned port
166 
167                 // PetClinic runs very slowly in debug builds if VerifyDependencies is enabled.
168                 "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-VerifyDependencies",
169               //These don't seem necessary when pet-clinic is run in "Spring AOT" mode
170               //"--add-opens", "java.base/java.io=ALL-UNNAMED",
171               //"--add-opens", "java.base/java.lang=ALL-UNNAMED",
172               //"--add-opens", "java.rmi/sun.rmi.transport=ALL-UNNAMED"
173             };
174         }
175 
176         @Override
177         public String classpath(RunMode runMode) {
178             return cp;
179         }
180 
181         @Override
182         public String[] appCommandLine(RunMode runMode) {
183             String cmdLine[] = new String[] {
184                 "org.springframework.samples.petclinic.PetClinicApplication"
185             };
186             if (runMode == RunMode.PRODUCTION) {
187                 // FIXME: bug JDK-8318393
188                 cmdLine = StringArrayUtils.concat("-XX:-LoadCachedCode", cmdLine);
189             }
190 
191             if (runMode.isProductionRun()) {
192                 cmdLine = StringArrayUtils.concat("-Xlog:scc=error", cmdLine);
193             }
194             return cmdLine;
195         }
196 
197         @Override
198         public void checkExecution(OutputAnalyzer out, RunMode runMode) {
199             if (!runMode.isStaticDump()) {
200                 out.shouldContain("Booted and returned in ");
201             }
202         }
203     }
204 }