1 /* vim: set ft=java:
  2  * Copyright (c) 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.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 import static java.lang.IO.print;
 27 import static java.lang.IO.println;
 28 import java.util.regex.Matcher;
 29 import java.util.regex.Pattern;
 30 
 31 class Config {
 32     boolean headless = false;
 33     boolean verbose = false;
 34     boolean startOnFirstThread = false;
 35     boolean justShowCommandline = false;
 36     boolean runSuite = false;
 37     String backendName = null;
 38     Script.JarFile backendJar = null;
 39     String testName = null;
 40     String examplePackageName = null;
 41     String testMainClassName = null;
 42     Script.JarFile exampleJar = null;
 43     List<Script.ClassPathEntryProvider> classpath = new ArrayList<>();
 44     List<String> vmargs = new ArrayList<>();
 45     List<String> appargs = new ArrayList<>();
 46 
 47     Config(Script.BuildDir buildDir, String[] args) {
 48 
 49         var testJARFile = buildDir.jarFile("hat-tests-1.0.jar");
 50         if (testJARFile.exists()) {
 51             testMainClassName = "hat.test.engine.HATTestEngine";
 52             exampleJar = testJARFile;
 53             if (exampleJar.exists()) {
 54                 classpath.add(exampleJar);
 55             } else {
 56                 System.err.println("Cannot find example jar at " + testMainClassName);
 57             }
 58         }
 59 
 60         classpath.add(buildDir.jarFile("hat-tests-1.0.jar"));
 61         classpath.add(buildDir.jarFile("hat-core-1.0.jar"));
 62         classpath.add(buildDir.jarFile("hat-example-shared-1.0.jar"));
 63 
 64         for (int arg = 0; arg < args.length; arg++) {
 65 
 66             if (args[arg].equals("suite")) {
 67                 runSuite = true;
 68             } else if (args[arg].startsWith("ffi-")) {
 69                 backendName = args[arg];
 70                 backendJar = buildDir.jarFile("hat-backend-" + backendName + "-1.0.jar");
 71                 classpath.add(buildDir.jarFile("hat-backend-ffi-shared-1.0.jar"));
 72                 classpath.add(backendJar);
 73             } else if (args[arg].startsWith("java-")) {
 74                 backendName = args[arg];
 75                 backendJar = buildDir.jarFile("hat-backend-" + backendName + "-1.0.jar");
 76                 classpath.add(backendJar);
 77             } else {
 78                 switch (args[arg]) {
 79                     case "headless" -> headless = true;
 80                     case "verbose" -> verbose = true;
 81                     case "justShowCommandLine" -> justShowCommandline = true;
 82                     case "startOnFirstThread" -> startOnFirstThread = true;
 83                     default -> {
 84                         this.appargs.add(args[arg]);
 85                     }
 86                 }
 87             }
 88         }
 89     }
 90 }
 91 
 92 class Stats {
 93     int passed = 0;
 94     int failed = 0;
 95     int unsupported = 0;
 96     public void incrementPassed(int val) {
 97         this.passed += val;
 98     }
 99     public void incrementFailed(int fail) {
100         this.failed += fail;
101     }
102     public void incrementUnsupported(int unsupporeted) {
103         this.unsupported += unsupporeted;
104     }
105 
106     public int getPassed() {
107         return passed;
108     }
109     public int getFailed() {
110         return failed;
111     }
112     public int getUnsupported() {
113         return unsupported;
114     }
115 
116     @Override
117     public String toString() {
118         return String.format("Global passed: %d, failed: %d, unsupported: %d, pass-rate: %.2f%%",
119                 passed, failed, unsupported, ((float)(passed * 100 / (passed + failed + unsupported))));
120     }
121 }
122 
123 void main(String[] argv) {
124     var usage = """
125               usage:
126                 java @hat/test [backend] class
127                     backend   : opencl|cuda
128 
129                 examples:
130                    java @hat/test suite ffi-opencl
131                    java @hat/test ffi-opencl class#method
132                    java @hat/test suite ffi-cuda
133                    java @hat/test ffi-cuda class#method
134             """;
135 
136     var hatDir = Script.DirEntry.current();
137     var buildDir = hatDir.existingBuildDir("build");
138 
139     Config config = new Config(buildDir, argv);
140 
141     if (config.classpath.isEmpty()) {
142         println("Classpath is empty!");
143     } else if (config.backendJar == null || !config.backendJar.exists()) {
144         println("No backend !");
145     } else if (!config.exampleJar.exists()) {
146         println("No example !");
147     } else {
148         var extraction_opencl_jar = buildDir.jarFile("hat-extraction-opencl-1.0.jar");
149         var extraction_opengl_jar = buildDir.jarFile("hat-extraction-opengl-1.0.jar");
150         var wrap_shared_jar = buildDir.jarFile("hat-wrap-shared-1.0.jar");
151         var wrap_opencl_jar = buildDir.jarFile("hat-wrap-opencl-1.0.jar");
152         var wrap_opengl_jar = buildDir.jarFile("hat-wrap-opengl-1.0.jar");
153         switch (config.backendName) {
154             default -> {
155             }
156         }
157     }
158 
159     // Remove the previous report file:
160     Path file = Paths.get("test_report.txt");
161     try {
162         Files.deleteIfExists(file);
163     } catch (IOException e) {
164         e.printStackTrace();
165     }
166 
167     if (config.runSuite) {
168 
169         String[] suite = new String[] {
170                 "hat.test.TestMatMul",
171                 "hat.test.TestArrays",
172                 "hat.test.TestMandel",
173                 "hat.test.TestLocal",
174                 "hat.test.TestReductions",
175                 "hat.test.TestPrivate",
176                 "hat.test.TestParenthesis",
177                 "hat.test.TestConstants",
178                 "hat.test.TestBlackscholes",
179                 "hat.test.TestNbody",
180                 "hat.test.TestArrayView",
181                 "hat.test.TestVectorTypes",
182                 "hat.test.TestF16Type",
183                 "hat.test.TestFloat2"
184         };
185 
186         // Test the whole suite
187         for (String testClass : suite) {
188             Script.java(java -> java
189                     .enable_preview()
190                     .verbose(true)
191                     .enable_native_access("ALL-UNNAMED")
192                     .library_path(buildDir)
193                     .when(config.headless, Script.JavaBuilder::headless)
194                     .when(config.startOnFirstThread, Script.JavaBuilder::start_on_first_thread)
195                     .class_path(config.classpath)
196                     .vmargs(config.vmargs)
197                     .main_class(config.testMainClassName)
198                     .args(testClass)
199                     .justShowCommandline(config.justShowCommandline));
200         }
201 
202         // Final report
203         String regex = "passed: (\\d+), failed: (\\d+), unsupported: (\\d+)";
204         Pattern pattern = Pattern.compile(regex);
205         Stats stats = new Stats();
206 
207         System.out.println("\n\n************************************************");
208         System.out.println("                 HAT Test Report ");
209         System.out.println("************************************************");
210         try {
211             List<String> lines = Files.readAllLines(file);
212             for (String line : lines) {
213                 System.out.println(line);
214 
215                 Matcher matcher = pattern.matcher(line);
216                 if (matcher.find()) {
217                     int passed = Integer.parseInt(matcher.group(1));
218                     int fail = Integer.parseInt(matcher.group(2));
219                     int unsupported = Integer.parseInt(matcher.group(3));
220                     stats.incrementPassed(passed);
221                     stats.incrementFailed(fail);
222                     stats.incrementUnsupported(unsupported);
223                 }
224             }
225         } catch (IOException e) {
226             e.printStackTrace();
227         }
228         System.out.println(stats);
229 
230     } else {
231         // A single command for a specific class/method
232         Script.java(java -> java
233                 .enable_preview()
234                 .verbose(true)
235                 .enable_native_access("ALL-UNNAMED")
236                 .library_path(buildDir)
237                 .when(config.headless, Script.JavaBuilder::headless)
238                 .when(config.startOnFirstThread, Script.JavaBuilder::start_on_first_thread)
239                 .class_path(config.classpath)
240                 .vmargs(config.vmargs)
241                 .main_class(config.testMainClassName)
242                 .args(config.appargs)
243                 .justShowCommandline(config.justShowCommandline));
244     }
245 
246 }