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