1 /* vim: set ft=java:
2 * Copyright (c) 2024-2026, 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 int precisionErrors = 0;
97 public void incrementPassed(int val) { this.passed += val; }
98 public void incrementFailed(int fail) {
99 this.failed += fail;
100 }
101 public void incrementUnsupported(int unsupporeted) {
102 this.unsupported += unsupporeted;
103 }
104 public void incrementPrecisionErrors(int precisionErrors) {
105 this.precisionErrors += precisionErrors;
106 }
107
108 public int getPassed() {
109 return passed;
110 }
111 public int getFailed() {
112 return failed;
113 }
114 public int getUnsupported() {
115 return unsupported;
116 }
117 public int getPrecisionErrors { return precisionErrors }
118
119 @Override
120 public String toString() {
121 return String.format("Global passed: %d, failed: %d, unsupported: %d, precision-errors: %d, pass-rate: %.2f%%",
122 passed, failed, unsupported, precisionErrors, ((float)(passed * 100 / (passed + failed + unsupported + precisionErrors))));
123 }
124 }
125
126 void main(String[] argv) {
127 var usage = """
128 usage:
129 java @hat/test [backend] class
130 backend : opencl|cuda
131
132 examples:
133 java @hat/test suite ffi-opencl
134 java @hat/test ffi-opencl class#method
135 java @hat/test suite ffi-cuda
136 java @hat/test ffi-cuda class#method
137 """;
138
139 var hatDir = Script.DirEntry.current();
140 var buildDir = hatDir.existingBuildDir("build");
141
142 Config config = new Config(buildDir, argv);
143
144 if (config.classpath.isEmpty()) {
145 println("Classpath is empty!");
146 } else if (config.backendJar == null || !config.backendJar.exists()) {
147 println("No backend !");
148 } else if (!config.exampleJar.exists()) {
149 println("No example !");
150 } else {
151 var extraction_opencl_jar = buildDir.jarFile("hat-extraction-opencl-1.0.jar");
152 var extraction_opengl_jar = buildDir.jarFile("hat-extraction-opengl-1.0.jar");
153 var wrap_shared_jar = buildDir.jarFile("hat-wrap-shared-1.0.jar");
154 var wrap_opencl_jar = buildDir.jarFile("hat-wrap-opencl-1.0.jar");
155 var wrap_opengl_jar = buildDir.jarFile("hat-wrap-opengl-1.0.jar");
156 switch (config.backendName) {
157 default -> {
158 }
159 }
160 }
161
162 // Remove the previous report file:
163 Path file = Paths.get("test_report.txt");
164 try {
165 Files.deleteIfExists(file);
166 } catch (IOException e) {
167 e.printStackTrace();
168 }
169
170 if (config.runSuite) {
171
172 String[] suite = new String[] {
173 "hat.test.TestMatMul",
174 "hat.test.TestArrays",
175 "hat.test.TestMandel",
176 "hat.test.TestLocal",
177 "hat.test.TestReductions",
178 "hat.test.TestPrivate",
179 "hat.test.TestParenthesis",
180 "hat.test.TestConstants",
181 "hat.test.TestBlackscholes",
182 "hat.test.TestNbody",
183 "hat.test.TestArrayView",
184 "hat.test.TestVectorTypes",
185 "hat.test.TestF16Type",
186 "hat.test.TestFloat2",
187 "hat.test.TestBFloat16Type",
188 "hat.test.TestDeviceType",
189 "hat.test.TestVecorArrayView",
190 "hat.test.TestNumBlocks"
191 };
192
193 // Test the whole suite
194 for (String testClass : suite) {
195 Script.java(java -> java
196 .enable_preview()
197 .verbose(true)
198 .enable_native_access("ALL-UNNAMED")
199 .add_modules("jdk.incubator.code")
200 .library_path(buildDir)
201 .when(config.headless, Script.JavaBuilder::headless)
202 .when(config.startOnFirstThread, Script.JavaBuilder::start_on_first_thread)
203 .class_path(config.classpath)
204 .vmargs(config.vmargs)
205 .main_class(config.testMainClassName)
206 .args(testClass)
207 .justShowCommandline(config.justShowCommandline));
208 }
209
210 // Final report
211 String regex = "passed: (\\d+), failed: (\\d+), unsupported: (\\d+)";
212 Pattern pattern = Pattern.compile(regex);
213 Stats stats = new Stats();
214
215 System.out.println("\n\n************************************************");
216 System.out.println(" HAT Test Report ");
217 System.out.println("************************************************");
218 try {
219 List<String> lines = Files.readAllLines(file);
220 for (String line : lines) {
221 System.out.println(line);
222
223 Matcher matcher = pattern.matcher(line);
224 if (matcher.find()) {
225 int passed = Integer.parseInt(matcher.group(1));
226 int fail = Integer.parseInt(matcher.group(2));
227 int unsupported = Integer.parseInt(matcher.group(3));
228 int precisionErrors = Integer.parseInt(matcher.group(4));
229 stats.incrementPassed(passed);
230 stats.incrementFailed(fail);
231 stats.incrementUnsupported(unsupported);
232 stats.incrementPrecisionErrors(precisionErrors);
233 }
234 }
235 } catch (IOException e) {
236 e.printStackTrace();
237 }
238 System.out.println(stats);
239 if (stats.failed > 0) {
240 System.exit(-1);
241 } else {
242 System.exit(0);
243 }
244 } else {
245 // A single command for a specific class/method
246 Script.java(java -> java
247 .enable_preview()
248 .verbose(true)
249 .enable_native_access("ALL-UNNAMED")
250 .add_modules("jdk.incubator.code")
251 .library_path(buildDir)
252 .when(config.headless, Script.JavaBuilder::headless)
253 .when(config.startOnFirstThread, Script.JavaBuilder::start_on_first_thread)
254 .class_path(config.classpath)
255 .vmargs(config.vmargs)
256 .main_class(config.testMainClassName)
257 .args(config.appargs)
258 .justShowCommandline(config.justShowCommandline));
259 }
260 }