1 /* 2 * Copyright (c) 2015, 2017, 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 * @test 26 * @summary Unit test for java.lang.Runtime.Version 27 * @bug 8072379 8144062 8161236 8160956 28 */ 29 30 import java.lang.Runtime.Version; 31 import java.math.BigInteger; 32 import java.util.ArrayList; 33 import java.util.Arrays; 34 import java.util.List; 35 import java.util.Optional; 36 import java.util.stream.Collectors; 37 38 import static java.lang.System.out; 39 40 public class Basic { 41 42 private static final Class<? extends Throwable> IAE 43 = IllegalArgumentException.class; 44 private static final Class<? extends Throwable> NPE 45 = NullPointerException.class; 46 private static final Class<? extends Throwable> NFE 47 = NumberFormatException.class; 48 49 private static final BigInteger TOO_BIG 50 = (BigInteger.valueOf(Integer.MAX_VALUE)).add(BigInteger.ONE); 51 private static final String TOO_BIG_STR = TOO_BIG.toString(); 52 53 public static void main(String ... args) { 54 55 //// Tests for parse(), feature(), interim(), update(), patch(), 56 //// pre(), build(), optional(), version(), and toString() 57 // v f i u p pre bld opt 58 59 // $VNUM 60 test("9", 9, 0, 0, 0, "", 0, ""); 61 test("9.1", 9, 1, 0, 0, "", 0, ""); 62 test("9.0.1", 9, 0, 1, 0, "", 0, ""); 63 test("9.0.0.1", 9, 0, 0, 1, "", 0, ""); 64 test("9.0.0.0.1", 9, 0, 0, 0, "", 0, ""); 65 test("404.1.2", 404, 1, 2, 0, "", 0, ""); 66 test("9.1.2.3", 9, 1, 2, 3, "", 0, ""); 67 test("1000.0.0.0.0.0.99999999", 1000, 0, 0, 0, "", 0, ""); 68 69 tryCatch(null, NPE); 70 tryCatch("", IAE); 71 tryCatch("foo", IAE); 72 tryCatch("7a", IAE); 73 tryCatch("0", IAE); 74 tryCatch("09", IAE); 75 tryCatch("9.0", IAE); 76 tryCatch("9.0.", IAE); 77 tryCatch("1.9,1", IAE); 78 tryCatch(TOO_BIG_STR, NFE); 79 80 // $PRE 81 test("9-ea", 9, 0, 0, 0, "ea", 0, ""); 82 test("9-internal", 9, 0, 0, 0, "internal", 0, ""); 83 test("9-0", 9, 0, 0, 0, "0", 0, ""); 84 test("9.2.7-8", 9, 2, 7, 0, "8", 0, ""); 85 test("1-ALL", 1, 0, 0, 0, "ALL", 0, ""); 86 test("2.3.4.5-1a", 2, 3, 4, 5, "1a", 0, ""); 87 test("1-" + TOO_BIG_STR, 1, 0, 0, 0, TOO_BIG_STR, 0, ""); 88 89 tryCatch("9:-ea", IAE); 90 tryCatch("3.14159-", IAE); 91 tryCatch("3.14159-%", IAE); 92 93 // $BUILD 94 test("9+0", 9, 0, 0, 0, "", 0, ""); 95 test("3.14+9999900", 3, 14, 0, 0, "", 9999900, ""); 96 test("9-pre+105", 9, 0, 0, 0, "pre", 105, ""); 97 test("6.0.42-8beta+4", 6, 0, 42, 0, "8beta", 4, ""); 98 99 tryCatch("9+", IAE); 100 tryCatch("7+a", IAE); 101 tryCatch("9+00", IAE); 102 tryCatch("4.2+01", IAE); 103 tryCatch("4.2+1a", IAE); 104 tryCatch("1+" + TOO_BIG_STR, NFE); 105 106 // $OPT 107 test("9+-foo", 9, 0, 0, 0, "", 0, "foo"); 108 test("9-pre-opt", 9, 0, 0, 0, "pre", 0, "opt"); 109 test("42+---bar", 42, 0, 0, 0, "", 0, "--bar"); 110 test("2.91+-8061493-", 2, 91, 0, 0, "", 0, "8061493-"); 111 test("24+-foo.bar", 24, 0, 0, 0, "", 0, "foo.bar"); 112 test("9-ribbit+17-...", 9, 0, 0, 0, "ribbit", 17, "..."); 113 test("7+1-" + TOO_BIG_STR, 7,0, 0, 0, "", 1, TOO_BIG_STR); 114 115 tryCatch("9-pre+-opt", IAE); 116 tryCatch("1.4142+-", IAE); 117 tryCatch("2.9979+-%", IAE); 118 tryCatch("10--ea", IAE); 119 120 //// Test for Runtime.version() 121 testVersion(); 122 123 //// Test for equals{IgnoreOptional}?(), hashCode(), 124 //// compareTo{IgnoreOptional}?() 125 // compare: after "<" == -1, equal == 0, before ">" == 1 126 // v0 v1 eq eqNO cmp cmpNO 127 testEHC("9", "9", true, true, 0, 0); 128 129 testEHC("8", "9", false, false, -1, -1); 130 testEHC("9", "10", false, false, -1, -1); 131 testEHC("9", "8", false, false, 1, 1); 132 133 testEHC("10.512.1", "10.512.2", false, false, -1, -1); 134 testEHC("10.512.0.1", "10.512.0.2", false, false, -1, -1); 135 testEHC("10.512.0.0.1", "10.512.0.0.2", false, false, -1, -1); 136 testEHC("512.10.1", "512.11.1", false, false, -1, -1); 137 138 // $OPT comparison 139 testEHC("9", "9+-oink", false, true, -1, 0); 140 testEHC("9+-ribbit", "9+-moo", false, true, 1, 0); 141 testEHC("9-quack+3-ribbit", 142 "9-quack+3-moo", false, true, 1, 0); 143 testEHC("9.1+7", "9.1+7-moo-baa-la", false, true, -1, 0); 144 145 // numeric vs. non-numeric $PRE 146 testEHC("9.1.1.2-2a", "9.1.1.2-12", false, false, 1, 1); 147 testEHC("9.1.1.2-12", "9.1.1.2-4", false, false, 1, 1); 148 149 testEHC("27.16", "27.16+120", false, false, -1, -1); 150 testEHC("10", "10-ea", false, false, 1, 1); 151 testEHC("10.1+1", "10.1-ea+1", false, false, 1, 1); 152 testEHC("10.0.1+22", "10.0.1+21", false, false, 1, 1); 153 154 // numeric vs. non-numeric $PRE 155 testEHC("9.1.1.2-12", "9.1.1.2-a2", false, false, -1, -1); 156 testEHC("9.1.1.2-1", "9.1.1.2-4", false, false, -1, -1); 157 158 testEHC("9-internal", "9", false, false, -1, -1); 159 testEHC("9-ea+120", "9+120", false, false, -1, -1); 160 testEHC("9-ea+120", "9+120", false, false, -1, -1); 161 testEHC("9+101", "9", false, false, 1, 1); 162 testEHC("9+101", "9+102", false, false, -1, -1); 163 testEHC("1.9-ea", "9-ea", false, false, -1, -1); 164 165 if (fail != 0) 166 throw new RuntimeException((fail + pass) + " tests: " 167 + fail + " failure(s), first", first); 168 else 169 out.println("all " + (fail + pass) + " tests passed"); 170 171 } 172 173 private static void test(String s, Integer feature, Integer interim, 174 Integer update, Integer patch, 175 String pre, Integer build, String opt) 176 { 177 Version v = testParse(s); 178 179 testStr(v.toString(), s); 180 181 testInt(v.feature(), feature); 182 testInt(v.major(), feature); 183 testInt(v.interim(), interim); 184 testInt(v.minor(), interim); 185 testInt(v.update(), update); 186 testInt(v.security(), update); 187 testInt(v.patch(), patch); 188 testStr((v.pre().isPresent() ? v.pre().get() : ""), pre); 189 testInt((v.build().isPresent() ? v.build().get() : 0), build); 190 testStr((v.optional().isPresent() ? v.optional().get() : ""), opt); 191 192 testVersion(v.version(), s); 193 } 194 195 private static Version testParse(String s) { 196 Version v = Version.parse(s); 197 pass(); 198 return v; 199 } 200 201 private static void testInt(int got, int exp) { 202 if (got != exp) { 203 fail("testInt()", Integer.toString(exp), Integer.toString(got)); 204 } else { 205 pass(); 206 } 207 } 208 209 private static void testStr(String got, String exp) { 210 if (!got.equals(exp)) { 211 fail("testStr()", exp, got); 212 } else { 213 pass(); 214 } 215 } 216 217 private static void tryCatch(String s, Class<? extends Throwable> ex) { 218 Throwable t = null; 219 try { 220 Version.parse(s); 221 } catch (Throwable x) { 222 if (ex.isAssignableFrom(x.getClass())) { 223 t = x; 224 } else 225 x.printStackTrace(); 226 } 227 if ((t == null) && (ex != null)) 228 fail(s, ex); 229 else 230 pass(); 231 } 232 233 private static void testVersion() { 234 Version current = Runtime.version(); 235 String javaVer = System.getProperty("java.runtime.version"); 236 237 // java.runtime.version == $VNUM(\-$PRE)?(\+$BUILD)?(-$OPT)? 238 String [] jv = javaVer.split("\\+"); 239 String [] ver = jv[0].split("-"); 240 List<Integer> javaVerVNum 241 = Arrays.stream(ver[0].split("\\.")) 242 .map(Integer::parseInt) 243 .collect(Collectors.toList()); 244 if (!javaVerVNum.equals(current.version())) { 245 fail("Runtime.version()", javaVerVNum.toString(), 246 current.version().toString()); 247 } else { 248 pass(); 249 } 250 251 Optional<String> javaVerPre 252 = (ver.length == 2) 253 ? Optional.ofNullable(ver[1]) 254 : Optional.empty(); 255 if (!javaVerPre.equals(current.pre())) { 256 fail("testCurrent() pre()", javaVerPre.toString(), 257 current.pre().toString()); 258 } else { 259 pass(); 260 } 261 262 testEHC(current.toString(), javaVer, true, true, 0, 0); 263 } 264 265 private static void testVersion(List<Integer> vnum, String s) { 266 List<Integer> svnum = new ArrayList<>(); 267 StringBuilder sb = new StringBuilder(); 268 for (int i = 0; i < s.length(); i++) { 269 Character c = s.charAt(i); 270 if (Character.isDigit(c)) { 271 sb.append(c); 272 } else { 273 svnum.add(Integer.parseInt(sb.toString())); 274 sb = new StringBuilder(); 275 if (c == '+' || c == '-') { 276 break; 277 } 278 } 279 } 280 if (sb.length() > 0) { 281 svnum.add(Integer.parseInt(sb.toString())); 282 } 283 284 if (!svnum.equals(vnum)) { 285 fail("testVersion() equals()", svnum.toString(), vnum.toString()); 286 } else { 287 pass(); 288 } 289 } 290 291 private static void testEHC(String s0, String s1, boolean eq, boolean eqNO, 292 int cmp, int cmpNO) 293 { 294 Version v0 = Version.parse(s0); 295 Version v1 = Version.parse(s1); 296 297 testEquals(v0, v1, eq); 298 testEqualsNO(v0, v1, eqNO); 299 300 testHashCode(v0, v1, eq); 301 302 testCompare(v0, v1, cmp); 303 testCompareNO(v0, v1, cmpNO); 304 } 305 306 private static void testEqualsNO(Version v0, Version v1, boolean eq) { 307 if (eq == v0.equalsIgnoreOptional(v1)) { 308 pass(); 309 } else { 310 fail("equalsIgnoreOptional() " + Boolean.toString(eq), 311 v0.toString(), v1.toString()); 312 } 313 } 314 315 private static void testEquals(Version v0, Version v1, boolean eq) { 316 if (eq == v0.equals(v1)) { 317 pass(); 318 } else { 319 fail("equals() " + Boolean.toString(eq), 320 v0.toString(), v1.toString()); 321 } 322 } 323 324 private static void testHashCode(Version v0, Version v1, boolean eq) { 325 int h0 = v0.hashCode(); 326 int h1 = v1.hashCode(); 327 if (eq) { 328 testInt(h0, h1); 329 } else if (h0 == h1) { 330 fail(String.format("hashCode() %s", h0), 331 Integer.toString(h0), 332 Integer.toString(h1)); 333 } else { // !eq && (h0 != h1) 334 pass(); 335 } 336 } 337 338 private static void testCompareNO(Version v0, Version v1, int compare) { 339 int cmp = v0.compareToIgnoreOptional(v1); 340 checkCompare(v0, v1, compare, cmp); 341 } 342 343 private static void testCompare(Version v0, Version v1, int compare) { 344 int cmp = v0.compareTo(v1); 345 checkCompare(v0, v1, compare, cmp); 346 } 347 348 private static void checkCompare(Version v0, Version v1, 349 int expected, int actual) 350 { 351 if (Integer.signum(expected) == Integer.signum(actual)) { 352 pass(); 353 } else { 354 fail(String.format("compare() (actual = %s) (expected = %s)", 355 actual, expected), 356 v0.toString(), v1.toString()); 357 } 358 } 359 360 private static int fail = 0; 361 private static int pass = 0; 362 363 private static Throwable first; 364 365 static void pass() { 366 pass++; 367 } 368 369 static void fail(String fs, Class ex) { 370 String s = "'" + fs + "'"; 371 if (ex != null) 372 s += ": " + ex.getName() + " not thrown"; 373 if (first == null) 374 setFirst(s); 375 System.err.println("FAILED: " + s); 376 fail++; 377 } 378 379 static void fail(String t, String exp, String got) { 380 String s = t + ": Expected '" + exp + "', got '" + got + "'"; 381 if (first == null) 382 setFirst(s); 383 System.err.println("FAILED: " + s); 384 fail++; 385 } 386 387 private static void setFirst(String s) { 388 try { 389 throw new RuntimeException(s); 390 } catch (RuntimeException x) { 391 first = x; 392 } 393 } 394 395 }