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