1 /* 2 * Copyright (c) 2014, 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 * @bug 8015081 27 * @modules java.base/sun.misc 28 * java.management 29 * java.security.jgss 30 * @compile Subject.java 31 * @compile SubjectNullTests.java 32 * @build SubjectNullTests 33 * @run main SubjectNullTests 34 * @summary javax.security.auth.Subject.toString() throws NPE 35 */ 36 37 import java.io.File; 38 import java.io.ByteArrayInputStream; 39 import java.io.FileInputStream; 40 import java.io.ObjectInputStream; 41 import java.io.IOException; 42 import java.security.Principal; 43 import java.util.Arrays; 44 import java.util.Collection; 45 import java.util.HashSet; 46 import java.util.LinkedList; 47 import java.util.List; 48 import java.util.Set; 49 import javax.management.remote.JMXPrincipal; 50 import javax.security.auth.Subject; 51 import javax.security.auth.x500.X500Principal; 52 import javax.security.auth.kerberos.KerberosPrincipal; 53 54 public class SubjectNullTests { 55 56 // Value templates for the constructor 57 private static Principal[] princVals = { 58 new X500Principal("CN=Tom Sawyer, ST=Missouri, C=US"), 59 new JMXPrincipal("Huckleberry Finn"), 60 new KerberosPrincipal("mtwain/author@LITERATURE.US") 61 }; 62 private static String[] pubVals = {"tsawyer", "hfinn", "mtwain"}; 63 private static String[] privVals = {"th3R!v3r", "oNth3R4ft", "5Cl3M3nz"}; 64 65 // Templates for collection-based modifiers for the Subject 66 private static Principal[] tmplAddPrincs = { 67 new X500Principal("CN=John Doe, O=Bogus Corp."), 68 new KerberosPrincipal("jdoe/admin@BOGUSCORP.COM") 69 }; 70 private static String[] tmplAddPubVals = {"jdoe", "djoe"}; 71 private static String[] tmplAddPrvVals = {"b4dpa55w0rd", "pass123"}; 72 73 /** 74 * Byte arrays used for deserialization: 75 * These byte arrays contain serialized Subjects and SecureSets, 76 * either with or without nulls. These use 77 * jjjjj.security.auth.Subject, which is a modified Subject 78 * implementation that allows the addition of null elements 79 */ 80 private static final byte[] SUBJ_NO_NULL = 81 jjjjj.security.auth.Subject.enc(makeSubjWithNull(false)); 82 private static final byte[] SUBJ_WITH_NULL = 83 jjjjj.security.auth.Subject.enc(makeSubjWithNull(true)); 84 private static final byte[] PRIN_NO_NULL = 85 jjjjj.security.auth.Subject.enc(makeSecSetWithNull(false)); 86 private static final byte[] PRIN_WITH_NULL = 87 jjjjj.security.auth.Subject.enc(makeSecSetWithNull(true)); 88 89 /** 90 * Method to allow creation of a subject that can optionally 91 * insert a null reference into the principals Set. 92 */ 93 private static jjjjj.security.auth.Subject makeSubjWithNull( 94 boolean nullPrinc) { 95 Set<Principal> setPrinc = new HashSet<>(Arrays.asList(princVals)); 96 if (nullPrinc) { 97 setPrinc.add(null); 98 } 99 100 return (new jjjjj.security.auth.Subject(setPrinc)); 101 } 102 103 /** 104 * Method to allow creation of a SecureSet that can optionally 105 * insert a null reference. 106 */ 107 private static Set<Principal> makeSecSetWithNull(boolean nullPrinc) { 108 Set<Principal> setPrinc = new HashSet<>(Arrays.asList(princVals)); 109 if (nullPrinc) { 110 setPrinc.add(null); 111 } 112 113 jjjjj.security.auth.Subject subj = 114 new jjjjj.security.auth.Subject(setPrinc); 115 116 return subj.getPrincipals(); 117 } 118 119 /** 120 * Construct a subject, and optionally place a null in any one 121 * of the three Sets used to initialize a Subject's values 122 */ 123 private static Subject makeSubj(boolean nullPrinc, boolean nullPub, 124 boolean nullPriv) { 125 Set<Principal> setPrinc = new HashSet<>(Arrays.asList(princVals)); 126 Set<String> setPubCreds = new HashSet<>(Arrays.asList(pubVals)); 127 Set<String> setPrvCreds = new HashSet<>(Arrays.asList(privVals)); 128 129 if (nullPrinc) { 130 setPrinc.add(null); 131 } 132 133 if (nullPub) { 134 setPubCreds.add(null); 135 } 136 137 if (nullPriv) { 138 setPrvCreds.add(null); 139 } 140 141 return (new Subject(false, setPrinc, setPubCreds, setPrvCreds)); 142 } 143 144 /** 145 * Provide a simple interface for abstracting collection-on-collection 146 * functions 147 */ 148 public interface Function { 149 boolean execCollection(Set<?> subjSet, Collection<?> actorData); 150 } 151 152 public static final Function methAdd = new Function() { 153 @SuppressWarnings("unchecked") 154 @Override 155 public boolean execCollection(Set<?> subjSet, Collection<?> actorData) { 156 return subjSet.addAll((Collection)actorData); 157 } 158 }; 159 160 public static final Function methContains = new Function() { 161 @Override 162 public boolean execCollection(Set<?> subjSet, Collection<?> actorData) { 163 return subjSet.containsAll(actorData); 164 } 165 }; 166 167 public static final Function methRemove = new Function() { 168 @Override 169 public boolean execCollection(Set<?> subjSet, Collection<?> actorData) { 170 return subjSet.removeAll(actorData); 171 } 172 }; 173 174 public static final Function methRetain = new Function() { 175 @Override 176 public boolean execCollection(Set<?> subjSet, Collection<?> actorData) { 177 return subjSet.retainAll(actorData); 178 } 179 }; 180 181 /** 182 * Run a test using a specified Collection method upon a Subject's 183 * SecureSet fields. This method expects NullPointerExceptions 184 * to be thrown, and throws RuntimeException when the operation 185 * succeeds 186 */ 187 private static void nullTestCollection(Function meth, Set<?> subjSet, 188 Collection<?> actorData) { 189 try { 190 meth.execCollection(subjSet, actorData); 191 throw new RuntimeException("Failed to throw NullPointerException"); 192 } catch (NullPointerException npe) { 193 System.out.println("Caught expected NullPointerException [PASS]"); 194 } 195 } 196 197 /** 198 * Run a test using a specified Collection method upon a Subject's 199 * SecureSet fields. This method expects the function and arguments 200 * passed in to complete without exception. It returns false 201 * if either an exception occurs or the result of the operation is 202 * false. 203 */ 204 private static boolean validTestCollection(Function meth, Set<?> subjSet, 205 Collection<?> actorData) { 206 boolean result = false; 207 208 try { 209 result = meth.execCollection(subjSet, actorData); 210 } catch (Exception exc) { 211 System.out.println("Caught exception " + exc); 212 } 213 214 return result; 215 } 216 217 /** 218 * Deserialize an object from a byte array. 219 * 220 * @param type The {@code Class} that the serialized file is supposed 221 * to contain. 222 * @param serBuffer The byte array containing the serialized object data 223 * 224 * @return An object of the type specified in the {@code type} parameter 225 */ 226 private static <T> T deserializeBuffer(Class<T> type, byte[] serBuffer) 227 throws IOException, ClassNotFoundException { 228 229 ByteArrayInputStream bis = new ByteArrayInputStream(serBuffer); 230 ObjectInputStream ois = new ObjectInputStream(bis); 231 232 T newObj = type.cast(ois.readObject()); 233 ois.close(); 234 bis.close(); 235 236 return newObj; 237 } 238 239 private static void testCTOR() { 240 System.out.println("------ constructor ------"); 241 242 try { 243 // Case 1: Create a subject with a null principal 244 // Expected result: NullPointerException 245 Subject mtSubj = makeSubj(true, false, false); 246 throw new RuntimeException( 247 "constructor [principal w/ null]: Failed to throw NPE"); 248 } catch (NullPointerException npe) { 249 System.out.println("constructor [principal w/ null]: " + 250 "NullPointerException [PASS]"); 251 } 252 253 try { 254 // Case 2: Create a subject with a null public credential element 255 // Expected result: NullPointerException 256 Subject mtSubj = makeSubj(false, true, false); 257 throw new RuntimeException( 258 "constructor [pub cred w/ null]: Failed to throw NPE"); 259 } catch (NullPointerException npe) { 260 System.out.println("constructor [pub cred w/ null]: " + 261 "NullPointerException [PASS]"); 262 } 263 264 try { 265 // Case 3: Create a subject with a null private credential element 266 // Expected result: NullPointerException 267 Subject mtSubj = makeSubj(false, false, true); 268 throw new RuntimeException( 269 "constructor [priv cred w/ null]: Failed to throw NPE"); 270 } catch (NullPointerException npe) { 271 System.out.println("constructor [priv cred w/ null]: " + 272 "NullPointerException [PASS]"); 273 } 274 275 // Case 4: Create a new subject using the principals, public 276 // and private credentials from another well-formed subject 277 // Expected result: Successful construction 278 Subject srcSubj = makeSubj(false, false, false); 279 Subject mtSubj = new Subject(false, srcSubj.getPrincipals(), 280 srcSubj.getPublicCredentials(), 281 srcSubj.getPrivateCredentials()); 282 System.out.println("Construction from another well-formed Subject's " + 283 "principals/creds [PASS]"); 284 } 285 286 @SuppressWarnings("unchecked") 287 private static void testDeserialize() throws Exception { 288 System.out.println("------ deserialize -----"); 289 290 Subject subj = null; 291 Set<Principal> prin = null; 292 293 // Case 1: positive deserialization test of a Subject 294 // Expected result: well-formed Subject 295 subj = deserializeBuffer(Subject.class, SUBJ_NO_NULL); 296 System.out.println("Positive deserialization test (Subject) passed"); 297 298 // Case 2: positive deserialization test of a SecureSet 299 // Expected result: well-formed Set 300 prin = deserializeBuffer(Set.class, PRIN_NO_NULL); 301 System.out.println("Positive deserialization test (SecureSet) passed"); 302 303 System.out.println( 304 "* Testing deserialization with null-poisoned objects"); 305 // Case 3: deserialization test of a null-poisoned Subject 306 // Expected result: NullPointerException 307 try { 308 subj = deserializeBuffer(Subject.class, SUBJ_WITH_NULL); 309 throw new RuntimeException("Failed to throw NullPointerException"); 310 } catch (NullPointerException npe) { 311 System.out.println("Caught expected NullPointerException [PASS]"); 312 } 313 314 // Case 4: deserialization test of a null-poisoned SecureSet 315 // Expected result: NullPointerException 316 try { 317 prin = deserializeBuffer(Set.class, PRIN_WITH_NULL); 318 throw new RuntimeException("Failed to throw NullPointerException"); 319 } catch (NullPointerException npe) { 320 System.out.println("Caught expected NullPointerException [PASS]"); 321 } 322 } 323 324 private static void testAdd() { 325 System.out.println("------ add() ------"); 326 // Create a well formed subject 327 Subject mtSubj = makeSubj(false, false, false); 328 329 try { 330 // Case 1: Attempt to add null values to principal 331 // Expected result: NullPointerException 332 mtSubj.getPrincipals().add(null); 333 throw new RuntimeException( 334 "PRINCIPAL add(null): Failed to throw NPE"); 335 } catch (NullPointerException npe) { 336 System.out.println( 337 "PRINCIPAL add(null): NullPointerException [PASS]"); 338 } 339 340 try { 341 // Case 2: Attempt to add null into the public creds 342 // Expected result: NullPointerException 343 mtSubj.getPublicCredentials().add(null); 344 throw new RuntimeException( 345 "PUB CRED add(null): Failed to throw NPE"); 346 } catch (NullPointerException npe) { 347 System.out.println( 348 "PUB CRED add(null): NullPointerException [PASS]"); 349 } 350 351 try { 352 // Case 3: Attempt to add null into the private creds 353 // Expected result: NullPointerException 354 mtSubj.getPrivateCredentials().add(null); 355 throw new RuntimeException( 356 "PRIV CRED add(null): Failed to throw NPE"); 357 } catch (NullPointerException npe) { 358 System.out.println( 359 "PRIV CRED add(null): NullPointerException [PASS]"); 360 } 361 } 362 363 private static void testRemove() { 364 System.out.println("------ remove() ------"); 365 // Create a well formed subject 366 Subject mtSubj = makeSubj(false, false, false); 367 368 try { 369 // Case 1: Attempt to remove null values from principal 370 // Expected result: NullPointerException 371 mtSubj.getPrincipals().remove(null); 372 throw new RuntimeException( 373 "PRINCIPAL remove(null): Failed to throw NPE"); 374 } catch (NullPointerException npe) { 375 System.out.println( 376 "PRINCIPAL remove(null): NullPointerException [PASS]"); 377 } 378 379 try { 380 // Case 2: Attempt to remove null from the public creds 381 // Expected result: NullPointerException 382 mtSubj.getPublicCredentials().remove(null); 383 throw new RuntimeException( 384 "PUB CRED remove(null): Failed to throw NPE"); 385 } catch (NullPointerException npe) { 386 System.out.println( 387 "PUB CRED remove(null): NullPointerException [PASS]"); 388 } 389 390 try { 391 // Case 3: Attempt to remove null from the private creds 392 // Expected result: NullPointerException 393 mtSubj.getPrivateCredentials().remove(null); 394 throw new RuntimeException( 395 "PRIV CRED remove(null): Failed to throw NPE"); 396 } catch (NullPointerException npe) { 397 System.out.println( 398 "PRIV CRED remove(null): NullPointerException [PASS]"); 399 } 400 } 401 402 private static void testContains() { 403 System.out.println("------ contains() ------"); 404 // Create a well formed subject 405 Subject mtSubj = makeSubj(false, false, false); 406 407 try { 408 // Case 1: Attempt to check for null values in principals 409 // Expected result: NullPointerException 410 mtSubj.getPrincipals().contains(null); 411 throw new RuntimeException( 412 "PRINCIPAL contains(null): Failed to throw NPE"); 413 } catch (NullPointerException npe) { 414 System.out.println( 415 "PRINCIPAL contains(null): NullPointerException [PASS]"); 416 } 417 418 try { 419 // Case 2: Attempt to check for null in public creds 420 // Expected result: NullPointerException 421 mtSubj.getPublicCredentials().contains(null); 422 throw new RuntimeException( 423 "PUB CRED contains(null): Failed to throw NPE"); 424 } catch (NullPointerException npe) { 425 System.out.println( 426 "PUB CRED contains(null): NullPointerException [PASS]"); 427 } 428 429 try { 430 // Case 3: Attempt to check for null in private creds 431 // Expected result: NullPointerException 432 mtSubj.getPrivateCredentials().contains(null); 433 throw new RuntimeException( 434 "PRIV CRED contains(null): Failed to throw NPE"); 435 } catch (NullPointerException npe) { 436 System.out.println( 437 "PRIV CRED contains(null): NullPointerException [PASS]"); 438 } 439 } 440 441 private static void testAddAll() { 442 // Create a well formed subject and additional collections 443 Subject mtSubj = makeSubj(false, false, false); 444 Set<Principal> morePrincs = new HashSet<>(Arrays.asList(tmplAddPrincs)); 445 Set<Object> morePubVals = new HashSet<>(Arrays.asList(tmplAddPubVals)); 446 Set<Object> morePrvVals = new HashSet<>(Arrays.asList(tmplAddPrvVals)); 447 448 // Run one success test for each Subject family to verify the 449 // overloaded method works as intended. 450 Set<Principal> setPrin = mtSubj.getPrincipals(); 451 Set<Object> setPubCreds = mtSubj.getPublicCredentials(); 452 Set<Object> setPrvCreds = mtSubj.getPrivateCredentials(); 453 int prinOrigSize = setPrin.size(); 454 int pubOrigSize = setPubCreds.size(); 455 int prvOrigSize = setPrvCreds.size(); 456 457 System.out.println("------ addAll() -----"); 458 459 // Add the new members, then check the resulting size of the 460 // Subject attributes to verify they've increased by the proper 461 // amounts. 462 if ((validTestCollection(methAdd, setPrin, morePrincs) != true) || 463 (setPrin.size() != prinOrigSize + morePrincs.size())) 464 { 465 throw new RuntimeException("Failed addAll() on principals"); 466 } 467 if ((validTestCollection(methAdd, setPubCreds, 468 morePubVals) != true) || 469 (setPubCreds.size() != pubOrigSize + morePubVals.size())) 470 { 471 throw new RuntimeException("Failed addAll() on public creds"); 472 } 473 if ((validTestCollection(methAdd, setPrvCreds, 474 morePrvVals) != true) || 475 (setPrvCreds.size() != prvOrigSize + morePrvVals.size())) 476 { 477 throw new RuntimeException("Failed addAll() on private creds"); 478 } 479 System.out.println("Positive addAll() test passed"); 480 481 // Now add null elements into each container, then retest 482 morePrincs.add(null); 483 morePubVals.add(null); 484 morePrvVals.add(null); 485 486 System.out.println("* Testing addAll w/ null values on Principals"); 487 nullTestCollection(methAdd, mtSubj.getPrincipals(), null); 488 nullTestCollection(methAdd, mtSubj.getPrincipals(), morePrincs); 489 490 System.out.println("* Testing addAll w/ null values on Public Creds"); 491 nullTestCollection(methAdd, mtSubj.getPublicCredentials(), null); 492 nullTestCollection(methAdd, mtSubj.getPublicCredentials(), 493 morePubVals); 494 495 System.out.println("* Testing addAll w/ null values on Private Creds"); 496 nullTestCollection(methAdd, mtSubj.getPrivateCredentials(), null); 497 nullTestCollection(methAdd, mtSubj.getPrivateCredentials(), 498 morePrvVals); 499 } 500 501 private static void testRemoveAll() { 502 // Create a well formed subject and additional collections 503 Subject mtSubj = makeSubj(false, false, false); 504 Set<Principal> remPrincs = new HashSet<>(); 505 Set<Object> remPubVals = new HashSet<>(); 506 Set<Object> remPrvVals = new HashSet<>(); 507 508 remPrincs.add(new KerberosPrincipal("mtwain/author@LITERATURE.US")); 509 remPubVals.add("mtwain"); 510 remPrvVals.add("5Cl3M3nz"); 511 512 // Run one success test for each Subject family to verify the 513 // overloaded method works as intended. 514 Set<Principal> setPrin = mtSubj.getPrincipals(); 515 Set<Object> setPubCreds = mtSubj.getPublicCredentials(); 516 Set<Object> setPrvCreds = mtSubj.getPrivateCredentials(); 517 int prinOrigSize = setPrin.size(); 518 int pubOrigSize = setPubCreds.size(); 519 int prvOrigSize = setPrvCreds.size(); 520 521 System.out.println("------ removeAll() -----"); 522 523 // Remove the specified members, then check the resulting size of the 524 // Subject attributes to verify they've decreased by the proper 525 // amounts. 526 if ((validTestCollection(methRemove, setPrin, remPrincs) != true) || 527 (setPrin.size() != prinOrigSize - remPrincs.size())) 528 { 529 throw new RuntimeException("Failed removeAll() on principals"); 530 } 531 if ((validTestCollection(methRemove, setPubCreds, 532 remPubVals) != true) || 533 (setPubCreds.size() != pubOrigSize - remPubVals.size())) 534 { 535 throw new RuntimeException("Failed removeAll() on public creds"); 536 } 537 if ((validTestCollection(methRemove, setPrvCreds, 538 remPrvVals) != true) || 539 (setPrvCreds.size() != prvOrigSize - remPrvVals.size())) 540 { 541 throw new RuntimeException("Failed removeAll() on private creds"); 542 } 543 System.out.println("Positive removeAll() test passed"); 544 545 // Now add null elements into each container, then retest 546 remPrincs.add(null); 547 remPubVals.add(null); 548 remPrvVals.add(null); 549 550 System.out.println("* Testing removeAll w/ null values on Principals"); 551 nullTestCollection(methRemove, mtSubj.getPrincipals(), null); 552 nullTestCollection(methRemove, mtSubj.getPrincipals(), remPrincs); 553 554 System.out.println( 555 "* Testing removeAll w/ null values on Public Creds"); 556 nullTestCollection(methRemove, mtSubj.getPublicCredentials(), null); 557 nullTestCollection(methRemove, mtSubj.getPublicCredentials(), 558 remPubVals); 559 560 System.out.println( 561 "* Testing removeAll w/ null values on Private Creds"); 562 nullTestCollection(methRemove, mtSubj.getPrivateCredentials(), null); 563 nullTestCollection(methRemove, mtSubj.getPrivateCredentials(), 564 remPrvVals); 565 } 566 567 private static void testContainsAll() { 568 // Create a well formed subject and additional collections 569 Subject mtSubj = makeSubj(false, false, false); 570 Set<Principal> testPrincs = new HashSet<>(Arrays.asList(princVals)); 571 Set<Object> testPubVals = new HashSet<>(Arrays.asList(pubVals)); 572 Set<Object> testPrvVals = new HashSet<>(Arrays.asList(privVals)); 573 574 System.out.println("------ containsAll() -----"); 575 576 // Run one success test for each Subject family to verify the 577 // overloaded method works as intended. 578 if ((validTestCollection(methContains, mtSubj.getPrincipals(), 579 testPrincs) == false) && 580 (validTestCollection(methContains, mtSubj.getPublicCredentials(), 581 testPubVals) == false) && 582 (validTestCollection(methContains, 583 mtSubj.getPrivateCredentials(), testPrvVals) == false)) { 584 throw new RuntimeException("Valid containsAll() check failed"); 585 } 586 System.out.println("Positive containsAll() test passed"); 587 588 // Now let's add a null into each collection and watch the fireworks. 589 testPrincs.add(null); 590 testPubVals.add(null); 591 testPrvVals.add(null); 592 593 System.out.println( 594 "* Testing containsAll w/ null values on Principals"); 595 nullTestCollection(methContains, mtSubj.getPrincipals(), null); 596 nullTestCollection(methContains, mtSubj.getPrincipals(), testPrincs); 597 598 System.out.println( 599 "* Testing containsAll w/ null values on Public Creds"); 600 nullTestCollection(methContains, mtSubj.getPublicCredentials(), 601 null); 602 nullTestCollection(methContains, mtSubj.getPublicCredentials(), 603 testPubVals); 604 605 System.out.println( 606 "* Testing containsAll w/ null values on Private Creds"); 607 nullTestCollection(methContains, mtSubj.getPrivateCredentials(), 608 null); 609 nullTestCollection(methContains, mtSubj.getPrivateCredentials(), 610 testPrvVals); 611 } 612 613 private static void testRetainAll() { 614 // Create a well formed subject and additional collections 615 Subject mtSubj = makeSubj(false, false, false); 616 Set<Principal> remPrincs = new HashSet<>(Arrays.asList(tmplAddPrincs)); 617 Set<Object> remPubVals = new HashSet<>(Arrays.asList(tmplAddPubVals)); 618 Set<Object> remPrvVals = new HashSet<>(Arrays.asList(tmplAddPrvVals)); 619 620 // Add in values that exist within the Subject 621 remPrincs.add(princVals[2]); 622 remPubVals.add(pubVals[2]); 623 remPrvVals.add(privVals[2]); 624 625 // Run one success test for each Subject family to verify the 626 // overloaded method works as intended. 627 Set<Principal> setPrin = mtSubj.getPrincipals(); 628 Set<Object> setPubCreds = mtSubj.getPublicCredentials(); 629 Set<Object> setPrvCreds = mtSubj.getPrivateCredentials(); 630 int prinOrigSize = setPrin.size(); 631 int pubOrigSize = setPubCreds.size(); 632 int prvOrigSize = setPrvCreds.size(); 633 634 System.out.println("------ retainAll() -----"); 635 636 // Retain the specified members (those that exist in the Subject) 637 // and validate the results. 638 if (validTestCollection(methRetain, setPrin, remPrincs) == false || 639 setPrin.size() != 1 || setPrin.contains(princVals[2]) == false) 640 { 641 throw new RuntimeException("Failed retainAll() on principals"); 642 } 643 644 if (validTestCollection(methRetain, setPubCreds, 645 remPubVals) == false || 646 setPubCreds.size() != 1 || 647 setPubCreds.contains(pubVals[2]) == false) 648 { 649 throw new RuntimeException("Failed retainAll() on public creds"); 650 } 651 if (validTestCollection(methRetain, setPrvCreds, 652 remPrvVals) == false || 653 setPrvCreds.size() != 1 || 654 setPrvCreds.contains(privVals[2]) == false) 655 { 656 throw new RuntimeException("Failed retainAll() on private creds"); 657 } 658 System.out.println("Positive retainAll() test passed"); 659 660 // Now add null elements into each container, then retest 661 remPrincs.add(null); 662 remPubVals.add(null); 663 remPrvVals.add(null); 664 665 System.out.println("* Testing retainAll w/ null values on Principals"); 666 nullTestCollection(methRetain, mtSubj.getPrincipals(), null); 667 nullTestCollection(methRetain, mtSubj.getPrincipals(), remPrincs); 668 669 System.out.println( 670 "* Testing retainAll w/ null values on Public Creds"); 671 nullTestCollection(methRetain, mtSubj.getPublicCredentials(), null); 672 nullTestCollection(methRetain, mtSubj.getPublicCredentials(), 673 remPubVals); 674 675 System.out.println( 676 "* Testing retainAll w/ null values on Private Creds"); 677 nullTestCollection(methRetain, mtSubj.getPrivateCredentials(), null); 678 nullTestCollection(methRetain, mtSubj.getPrivateCredentials(), 679 remPrvVals); 680 } 681 682 private static void testIsEmpty() { 683 Subject populatedSubj = makeSubj(false, false, false); 684 Subject emptySubj = new Subject(); 685 686 System.out.println("------ isEmpty() -----"); 687 688 if (populatedSubj.getPrincipals().isEmpty()) { 689 throw new RuntimeException( 690 "Populated Subject Principals incorrectly returned empty"); 691 } 692 if (emptySubj.getPrincipals().isEmpty() == false) { 693 throw new RuntimeException( 694 "Empty Subject Principals incorrectly returned non-empty"); 695 } 696 System.out.println("isEmpty() test passed"); 697 } 698 699 private static void testSecureSetEquals() { 700 System.out.println("------ SecureSet.equals() -----"); 701 702 Subject subj = makeSubj(false, false, false); 703 Subject subjComp = makeSubj(false, false, false); 704 705 // Case 1: null comparison [expect false] 706 if (subj.getPublicCredentials().equals(null) != false) { 707 throw new RuntimeException( 708 "equals(null) incorrectly returned true"); 709 } 710 711 // Case 2: Self-comparison [expect true] 712 Set<Principal> princs = subj.getPrincipals(); 713 princs.equals(subj.getPrincipals()); 714 715 // Case 3: Comparison with non-Set type [expect false] 716 List<Principal> listPrinc = new LinkedList<>(Arrays.asList(princVals)); 717 if (subj.getPublicCredentials().equals(listPrinc) != false) { 718 throw new RuntimeException( 719 "equals([Non-Set]) incorrectly returned true"); 720 } 721 722 // Case 4: SecureSets of differing sizes [expect false] 723 Subject subj1princ = new Subject(); 724 Subject subj2princ = new Subject(); 725 subj1princ.getPrincipals().add( 726 new X500Principal("CN=Tom Sawyer, ST=Missouri, C=US")); 727 subj1princ.getPrincipals().add( 728 new X500Principal("CN=John Doe, O=Bogus Corp.")); 729 subj2princ.getPrincipals().add( 730 new X500Principal("CN=Tom Sawyer, ST=Missouri, C=US")); 731 if (subj1princ.getPrincipals().equals( 732 subj2princ.getPrincipals()) != false) { 733 throw new RuntimeException( 734 "equals([differing sizes]) incorrectly returned true"); 735 } 736 737 // Case 5: Content equality test [expect true] 738 Set<Principal> equalSet = new HashSet<>(Arrays.asList(princVals)); 739 if (subj.getPrincipals().equals(equalSet) != true) { 740 throw new RuntimeException( 741 "equals([equivalent set]) incorrectly returned false"); 742 } 743 744 // Case 5: Content inequality test [expect false] 745 // Note: to not fall into the size inequality check the two 746 // sets need to have the same number of elements. 747 Set<Principal> inequalSet = 748 new HashSet<Principal>(Arrays.asList(tmplAddPrincs)); 749 inequalSet.add(new JMXPrincipal("Samuel Clemens")); 750 751 if (subj.getPrincipals().equals(inequalSet) != false) { 752 throw new RuntimeException( 753 "equals([equivalent set]) incorrectly returned false"); 754 } 755 System.out.println("SecureSet.equals() tests passed"); 756 } 757 758 private static void testSecureSetHashCode() { 759 System.out.println("------ SecureSet.hashCode() -----"); 760 761 Subject subj = makeSubj(false, false, false); 762 763 // Make sure two other Set types that we know are equal per 764 // SecureSet.equals() and verify their hashCodes are also the same 765 Set<Principal> equalHashSet = new HashSet<>(Arrays.asList(princVals)); 766 767 if (subj.getPrincipals().hashCode() != equalHashSet.hashCode()) { 768 throw new RuntimeException( 769 "SecureSet and HashSet hashCodes() differ"); 770 } 771 System.out.println("SecureSet.hashCode() tests passed"); 772 } 773 774 private static void testToArray() { 775 System.out.println("------ toArray() -----"); 776 777 Subject subj = makeSubj(false, false, false); 778 779 // Case 1: no-parameter toArray with equality comparison 780 // Expected result: true 781 List<Object> alSubj = Arrays.asList(subj.getPrincipals().toArray()); 782 List<Principal> alPrincs = Arrays.asList(princVals); 783 784 if (alSubj.size() != alPrincs.size() || 785 alSubj.containsAll(alPrincs) != true) { 786 throw new RuntimeException( 787 "Unexpected inequality on returned toArray()"); 788 } 789 790 // Case 2: generic-type toArray where passed array is of sufficient 791 // size. 792 // Expected result: returned Array is reference-equal to input param 793 // and content equal to data used to construct the originating Subject. 794 Principal[] pBlock = new Principal[3]; 795 Principal[] pBlockRef = subj.getPrincipals().toArray(pBlock); 796 alSubj = Arrays.asList((Object[])pBlockRef); 797 798 if (pBlockRef != pBlock) { 799 throw new RuntimeException( 800 "Unexpected reference-inequality on returned toArray(T[])"); 801 } else if (alSubj.size() != alPrincs.size() || 802 alSubj.containsAll(alPrincs) != true) { 803 throw new RuntimeException( 804 "Unexpected content-inequality on returned toArray(T[])"); 805 } 806 807 // Case 3: generic-type toArray where passed array is of 808 // insufficient size. 809 // Expected result: returned Array is not reference-equal to 810 // input param but is content equal to data used to construct the 811 // originating Subject. 812 pBlock = new Principal[1]; 813 pBlockRef = subj.getPrincipals().toArray(pBlock); 814 alSubj = Arrays.asList((Object[])pBlockRef); 815 816 if (pBlockRef == pBlock) { 817 throw new RuntimeException( 818 "Unexpected reference-equality on returned toArray(T[])"); 819 } else if (alSubj.size() != alPrincs.size() || 820 alSubj.containsAll(alPrincs) != true) { 821 throw new RuntimeException( 822 "Unexpected content-inequality on returned toArray(T[])"); 823 } 824 System.out.println("toArray() tests passed"); 825 } 826 827 public static void main(String[] args) throws Exception { 828 829 testCTOR(); 830 831 testDeserialize(); 832 833 testAdd(); 834 835 testRemove(); 836 837 testContains(); 838 839 testAddAll(); 840 841 testRemoveAll(); 842 843 testContainsAll(); 844 845 testRetainAll(); 846 847 testIsEmpty(); 848 849 testSecureSetEquals(); 850 851 testSecureSetHashCode(); 852 853 testToArray(); 854 } 855 }