gt:             Subject mtSubj = makeSubj(true, false, false);
context: /*
   * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  /*
   * @test
   * @bug 8015081
   * @modules java.management
   *          java.security.jgss
   * @compile Subject.java
   * @compile SubjectNullTests.java
   * @build SubjectNullTests
   * @run main SubjectNullTests
   * @summary javax.security.auth.Subject.toString() throws NPE
   */
  
  import java.io.File;
  import java.io.ByteArrayInputStream;
  import java.io.FileInputStream;
  import java.io.ObjectInputStream;
  import java.io.IOException;
  import java.security.Principal;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.HashSet;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Set;
  import javax.management.remote.JMXPrincipal;
  import javax.security.auth.Subject;
  import javax.security.auth.x500.X500Principal;
  import javax.security.auth.kerberos.KerberosPrincipal;
  
  public class SubjectNullTests {
  
      // Value templates for the constructor
      private static Principal[] princVals = {
          new X500Principal("CN=Tom Sawyer, ST=Missouri, C=US"),
          new JMXPrincipal("Huckleberry Finn"),
          new KerberosPrincipal("mtwain/author@LITERATURE.US")
      };
      private static String[] pubVals = {"tsawyer", "hfinn", "mtwain"};
      private static String[] privVals = {"th3R!v3r", "oNth3R4ft", "5Cl3M3nz"};
  
      // Templates for collection-based modifiers for the Subject
      private static Principal[] tmplAddPrincs = {
          new X500Principal("CN=John Doe, O=Bogus Corp."),
          new KerberosPrincipal("jdoe/admin@BOGUSCORP.COM")
      };
      private static String[] tmplAddPubVals = {"jdoe", "djoe"};
      private static String[] tmplAddPrvVals = {"b4dpa55w0rd", "pass123"};
  
      /**
       * Byte arrays used for deserialization:
       * These byte arrays contain serialized Subjects and SecureSets,
       * either with or without nulls.  These use
       * jjjjj.security.auth.Subject, which is a modified Subject
       * implementation that allows the addition of null elements
       */
      private static final byte[] SUBJ_NO_NULL =
          jjjjj.security.auth.Subject.enc(makeSubjWithNull(false));
      private static final byte[] SUBJ_WITH_NULL =
          jjjjj.security.auth.Subject.enc(makeSubjWithNull(true));
      private static final byte[] PRIN_NO_NULL =
          jjjjj.security.auth.Subject.enc(makeSecSetWithNull(false));
      private static final byte[] PRIN_WITH_NULL =
          jjjjj.security.auth.Subject.enc(makeSecSetWithNull(true));
  
      /**
       * Method to allow creation of a subject that can optionally
       * insert a null reference into the principals Set.
       */
      private static jjjjj.security.auth.Subject makeSubjWithNull(
              boolean nullPrinc) {
          Set<Principal> setPrinc = new HashSet<>(Arrays.asList(princVals));
          if (nullPrinc) {
              setPrinc.add(null);
          }
  
          return (new jjjjj.security.auth.Subject(setPrinc));
      }
  
      /**
       * Method to allow creation of a SecureSet that can optionally
       * insert a null reference.
       */
      private static Set<Principal> makeSecSetWithNull(boolean nullPrinc) {
          Set<Principal> setPrinc = new HashSet<>(Arrays.asList(princVals));
          if (nullPrinc) {
              setPrinc.add(null);
          }
  
          jjjjj.security.auth.Subject subj =
              new jjjjj.security.auth.Subject(setPrinc);
  
          return subj.getPrincipals();
      }
  
      /**
       * Construct a subject, and optionally place a null in any one
       * of the three Sets used to initialize a Subject's values
       */
      private static Subject makeSubj(boolean nullPrinc, boolean nullPub,
                               boolean nullPriv) {
          Set<Principal> setPrinc = new HashSet<>(Arrays.asList(princVals));
          Set<String> setPubCreds = new HashSet<>(Arrays.asList(pubVals));
          Set<String> setPrvCreds = new HashSet<>(Arrays.asList(privVals));
  
          if (nullPrinc) {
              setPrinc.add(null);
          }
  
          if (nullPub) {
              setPubCreds.add(null);
          }
  
          if (nullPriv) {
              setPrvCreds.add(null);
          }
  
          return (new Subject(false, setPrinc, setPubCreds, setPrvCreds));
      }
  
      /**
       * Provide a simple interface for abstracting collection-on-collection
       * functions
       */
      public interface Function {
          boolean execCollection(Set<?> subjSet, Collection<?> actorData);
      }
  
      public static final Function methAdd = new Function() {
          @SuppressWarnings("unchecked")
          @Override
          public boolean execCollection(Set<?> subjSet, Collection<?> actorData) {
              return subjSet.addAll((Collection)actorData);
          }
      };
  
      public static final Function methContains = new Function() {
          @Override
          public boolean execCollection(Set<?> subjSet, Collection<?> actorData) {
              return subjSet.containsAll(actorData);
          }
      };
  
      public static final Function methRemove = new Function() {
          @Override
          public boolean execCollection(Set<?> subjSet, Collection<?> actorData) {
              return subjSet.removeAll(actorData);
          }
      };
  
      public static final Function methRetain = new Function() {
          @Override
          public boolean execCollection(Set<?> subjSet, Collection<?> actorData) {
              return subjSet.retainAll(actorData);
          }
      };
  
      /**
       * Run a test using a specified Collection method upon a Subject's
       * SecureSet fields. This method expects NullPointerExceptions
       * to be thrown, and throws RuntimeException when the operation
       * succeeds
       */
      private static void nullTestCollection(Function meth, Set<?> subjSet,
             Collection<?> actorData) {
          try {
              meth.execCollection(subjSet, actorData);
              throw new RuntimeException("Failed to throw NullPointerException");
          } catch (NullPointerException npe) {
              System.out.println("Caught expected NullPointerException [PASS]");
          }
      }
  
      /**
       * Run a test using a specified Collection method upon a Subject's
       * SecureSet fields. This method expects the function and arguments
       * passed in to complete without exception.  It returns false
       * if either an exception occurs or the result of the operation is
       * false.
       */
      private static boolean validTestCollection(Function meth, Set<?> subjSet,
             Collection<?> actorData) {
          boolean result = false;
  
          try {
              result = meth.execCollection(subjSet, actorData);
          } catch (Exception exc) {
              System.out.println("Caught exception " + exc);
          }
  
          return result;
      }
  
      /**
       * Deserialize an object from a byte array.
       *
       * @param type The {@code Class} that the serialized file is supposed
       *             to contain.
       * @param serBuffer The byte array containing the serialized object data
       *
       * @return An object of the type specified in the {@code type} parameter
       */
      private static <T> T deserializeBuffer(Class<T> type, byte[] serBuffer)
              throws IOException, ClassNotFoundException {
  
          ByteArrayInputStream bis = new ByteArrayInputStream(serBuffer);
          ObjectInputStream ois = new ObjectInputStream(bis);
  
          T newObj = type.cast(ois.readObject());
          ois.close();
          bis.close();
  
          return newObj;
      }
  
      private static void testCTOR() {
          System.out.println("------ constructor ------");
  
          try {
              // Case 1: Create a subject with a null principal
              // Expected result: NullPointerException
  