1 /*
  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.
  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 import java.lang.reflect.code.Op;
 24 import java.lang.reflect.code.OpTransformer;
 25 import java.util.List;
 26 import java.lang.invoke.MethodHandles;
 27 import java.lang.reflect.Method;
 28 import java.lang.reflect.code.interpreter.Interpreter;
 29 import java.lang.reflect.code.op.CoreOp;
 30 import java.lang.runtime.CodeReflection;
 31 
 32 import org.testng.Assert;
 33 import org.testng.annotations.Test;
 34 
 35 /*
 36  * @test
 37  * @run testng/othervm -ea TestAssert
 38  */
 39 public class TestAssert {
 40 
 41     public static final String FAILURESTRING = "failure";
 42     public static final char FAILURECHAR = 'o';
 43 
 44     public static final float FAILUREFLOAT = -1.0f;
 45     public static final double FAILUREDOUBLE = -1.0d;
 46     public static final byte FAILUREBYTE = -1;
 47     public static final short FAILURESHORT = -1;
 48     public static final int FAILUREINT = -1;
 49 
 50     public static final long FAILURELONG = -1;
 51 
 52     public static final String FAILUREOBJECTMSG = "FAILURE OBJECT";
 53 
 54     public static final Object FAILUREOBJECT = new FailureObject();
 55 
 56 
 57     @Test
 58     public void testAssertThrows(){
 59         testThrows("assertThrow");
 60     }
 61 
 62     @Test
 63     public void testAssertString(){
 64         AssertionError ae = testThrows("assertThrowWithMessage");
 65         if (ae.getMessage() == null || !ae.getMessage().equals(FAILURESTRING)) {
 66             Assert.fail("Assertion failure messages do not match.");
 67         }
 68     }
 69 
 70     @Test
 71     public void testAssertChar() {
 72         AssertionError ae = testThrows("assertChar");
 73         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILURECHAR))){
 74             Assert.fail("Assertion failure messages do not match.");
 75         }
 76     }
 77 
 78     @Test
 79     public void testAssertFloat() {
 80         AssertionError ae = testThrows("assertFloat");
 81         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREFLOAT))){
 82             Assert.fail("Assertion failure messages do not match.");
 83         }
 84     }
 85 
 86     @Test
 87     public void testAssertDouble() {
 88         AssertionError ae = testThrows("assertDouble");
 89         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREDOUBLE))){
 90             Assert.fail("Assertion failure messages do not match.");
 91         }
 92     }
 93 
 94     @Test
 95     public void testAssertByte() {
 96         AssertionError ae = testThrows("assertByte");
 97         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREBYTE))){
 98             Assert.fail("Assertion failure messages do not match.");
 99         }
100     }
101 
102     @Test
103     public void testAssertShort() {
104         AssertionError ae = testThrows("assertShort");
105         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILURESHORT))){
106             Assert.fail("Assertion failure messages do not match.");
107         }
108     }
109 
110     @Test
111     public void testAssertInt() {
112         AssertionError ae = testThrows("assertInt");
113         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREINT))){
114             Assert.fail("Assertion failure messages do not match.");
115         }
116     }
117 
118     @Test
119     public void testAssertLong() {
120         AssertionError ae = testThrows("assertLong");
121         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILURELONG))){
122             Assert.fail("Assertion failure messages do not match.");
123         }
124     }
125 
126     @Test
127     public void testAssertObject() {
128         AssertionError ae = testThrows("assertObject");
129         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREOBJECT))){
130             Assert.fail("Assertion failure messages do not match.");
131         }
132     }
133 
134     @Test
135     public void testAssertExpr1() {
136         AssertionError ae = testThrows("assertExpr1");
137         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREINT + FAILURELONG))){
138             Assert.fail("Assertion failure messages do not match.");
139         }
140     }
141 
142     @Test
143     public void testAssertExpr2() {
144         AssertionError ae = testThrows("assertExpr2", List.of(int.class), 52);
145         if (ae.getMessage() == null || !ae.getMessage().equals(String.valueOf(FAILUREINT))){
146             Assert.fail("Assertion failure messages do not match.");
147         }
148     }
149 
150     @Test
151     public void testAssertExpr3() {
152          testRun("assertExpr3", List.of(int.class), 52);
153     }
154 
155     private static AssertionError testThrows(String methodName) {
156         return testThrows(methodName, List.of());
157     }
158     private static void testRun(String methodName, List<Class<?>> params, Object...args) {
159         try {
160             Class<TestAssert> clazz = TestAssert.class;
161             Method method = clazz.getDeclaredMethod(methodName,params.toArray(new Class[params.size()]));
162             CoreOp.FuncOp f = method.getCodeModel().orElseThrow();
163 
164             //Ensure we're fully lowered before testing.
165             final var fz = f.transform(OpTransformer.LOWERING_TRANSFORMER);
166 
167             Interpreter.invoke(MethodHandles.lookup(), fz ,args);
168         } catch (NoSuchMethodException e) {
169             throw new RuntimeException(e);
170         }
171     }
172 
173     private static AssertionError testThrows(String methodName, List<Class<?>> params, Object...args) {
174         try {
175             Class<TestAssert> clazz = TestAssert.class;
176             Method method = clazz.getDeclaredMethod(methodName,params.toArray(new Class[params.size()]));
177             CoreOp.FuncOp f = method.getCodeModel().orElseThrow();
178 
179             //Ensure we're fully lowered before testing.
180             final var fz = f.transform(OpTransformer.LOWERING_TRANSFORMER);
181 
182 
183             AssertionError ae = (AssertionError) retCatch(() -> Interpreter.invoke(MethodHandles.lookup(), fz ,args));
184             Assert.assertNotNull(ae);
185             return ae;
186         } catch (NoSuchMethodException e) {
187             throw new RuntimeException(e);
188         }
189     }
190 
191     private static Throwable retCatch(Runnable r) {
192         try {
193             r.run();
194         } catch (Throwable t) {
195             return t;
196         }
197         return null;
198     }
199 
200 
201 
202     @CodeReflection
203     public static void assertThrow() {
204         assert false;
205     }
206 
207     @CodeReflection
208     public static void assertThrowWithMessage() {
209         assert false : FAILURESTRING;
210     }
211 
212     @CodeReflection
213     public static void assertChar() {
214         char c = FAILURECHAR;
215         assert false : c;
216     }
217 
218     @CodeReflection
219     public static void assertFloat() {
220         float f = FAILUREFLOAT;
221         assert false : f;
222     }
223 
224     @CodeReflection
225     public static void assertDouble() {
226         double d = FAILUREDOUBLE;
227         assert false : d;
228     }
229 
230     @CodeReflection
231     public static void assertByte() {
232         byte b = FAILUREBYTE;
233         assert false : b;
234     }
235 
236     @CodeReflection
237     public static void assertShort() {
238         short s = FAILURESHORT;
239         assert false : s;
240     }
241 
242     @CodeReflection
243     public static void assertInt() {
244         int i = FAILUREINT;
245         assert false : i;
246     }
247 
248     @CodeReflection
249     public static void assertLong() {
250         long l = FAILURELONG;
251         assert false : l;
252     }
253 
254     @CodeReflection
255     public static void assertObject() {
256         Object o = FAILUREOBJECT;
257         assert false : o;
258     }
259 
260     @CodeReflection
261     public static void assertExpr1() {
262         int i = FAILUREINT;
263         long l = FAILURELONG;
264         assert false : i + l;
265         String y = "test";
266     }
267 
268     @CodeReflection
269     public static void assertExpr2(int iz) {
270         int i = FAILUREINT;
271         long l = FAILURELONG;
272         assert false : (i > iz) ? i + l : i;
273         String s = "";
274     }
275 
276     @CodeReflection
277     public static void assertExpr3(int iz) {
278         int i = FAILUREINT;
279         long l = FAILURELONG;
280         assert true : (i > iz) ? i + l : i;
281         String s = "";
282     }
283 
284     static class FailureObject {
285         @Override
286         public String toString(){
287            return FAILUREOBJECTMSG;
288         }
289     }
290 }