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