--- /dev/null 2014-06-05 10:26:57.847434336 -0700 +++ new/test/javax/security/auth/Subject/SubjectNullTests.java 2014-06-06 15:02:26.181255134 -0700 @@ -0,0 +1,783 @@ +/* + * 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 + * @summary javax.security.auth.Subject.toString() throws NPE + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.ObjectInputStream; +import java.io.IOException; +import java.lang.Exception; +import java.security.Principal; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.TreeSet; +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"}; + + /** + * 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 setPrinc = + new HashSet(Arrays.asList(princVals)); + Set setPubCreds = new HashSet(Arrays.asList(pubVals)); + Set 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() { + public boolean execCollection(Set subjSet, Collection actorData) { + return subjSet.addAll((Collection)actorData); + } + }; + + public static final Function methContains = new Function() { + public boolean execCollection(Set subjSet, Collection actorData) { + return subjSet.containsAll(actorData); + } + }; + + public static final Function methRemove = new Function() { + public boolean execCollection(Set subjSet, Collection actorData) { + return subjSet.removeAll(actorData); + } + }; + + public static final Function methRetain = new Function() { + 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 file. + * + * @param type The {@code Class} that the serialized file is supposed + * to contain. + * @param fileName The name of the file to be deserialized. + * + * @return An object of the type specified in the {@code type} parameter + */ + private static T deserializeFile(Class type, String fileName) + throws IOException, ClassNotFoundException { + File fileObj = new File(System.getProperty("test.src", "."), fileName); + FileInputStream fis = new FileInputStream(fileObj); + ObjectInputStream ois = new ObjectInputStream(fis); + + T newObj = (T)ois.readObject(); + ois.close(); + fis.close(); + + return newObj; + } + + private static void testCTOR() { + System.out.println("------ constructor ------"); + + try { + // Case 1: Create a subject with a null principal + // Expected result: NullPointerException + Subject mtSubj = makeSubj(true, false, false); + throw new RuntimeException( + "constructor [principal w/ null]: Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println("constructor [principal w/ null]: " + + "NullPointerException [PASS]"); + } + + try { + // Case 2: Create a subject with a null public credential element + // Expected result: NullPointerException + Subject mtSubj = makeSubj(false, true, false); + throw new RuntimeException( + "constructor [pub cred w/ null]: Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println("constructor [pub cred w/ null]: " + + "NullPointerException [PASS]"); + } + + try { + // Case 3: Create a subject with a null private credential element + // Expected result: NullPointerException + Subject mtSubj = makeSubj(false, false, true); + throw new RuntimeException( + "constructor [priv cred w/ null]: Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println("constructor [priv cred w/ null]: " + + "NullPointerException [PASS]"); + } + + // Case 4: Create a new subject using the principals, public + // and private credentials from another well-formed subject + // Expected result: Successful construction + Subject srcSubj = makeSubj(false, false, false); + Subject mtSubj = new Subject(false, srcSubj.getPrincipals(), + srcSubj.getPublicCredentials(), + srcSubj.getPrivateCredentials()); + System.out.println("Construction from another well-formed Subject's " + + "principals/creds [PASS]"); + } + + private static void testDeserialize() throws Exception { + System.out.println("------ deserialize -----"); + + Subject subj = null; + Set prin = null; + + // Case 1: positive deserialization test of a Subject + // Expected result: well-formed Subject + subj = deserializeFile(Subject.class, "SubjNoNull.bin"); + System.out.println("Positive deserialization test (Subject) passed"); + + // Case 2: positive deserialization test of a SecureSet + // Expected result: well-formed Set + prin = deserializeFile(Set.class, "PrinNoNull.bin"); + System.out.println("Positive deserialization test (SecureSet) passed"); + + System.out.println( + "* Testing deserialization with null-poisoned objects"); + // Case 3: deserialization test of a null-poisoned Subject + // Expected result: NullPointerException + try { + subj = deserializeFile(Subject.class, "SubjWithNull.bin"); + throw new RuntimeException("Failed to throw NullPointerException"); + } catch (NullPointerException npe) { + System.out.println("Caught expected NullPointerException [PASS]"); + } + + // Case 4: deserialization test of a null-poisoned SecureSet + // Expected result: NullPointerException + try { + prin = deserializeFile(Set.class, "PrinWithNull.bin"); + throw new RuntimeException("Failed to throw NullPointerException"); + } catch (NullPointerException npe) { + System.out.println("Caught expected NullPointerException [PASS]"); + } + } + + private static void testAdd() { + System.out.println("------ add() ------"); + // Create a well formed subject + Subject mtSubj = makeSubj(false, false, false); + + try { + // Case 1: Attempt to add null values to principal + // Expected result: NullPointerException + mtSubj.getPrincipals().add(null); + throw new RuntimeException( + "PRINCIPAL add(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PRINCIPAL add(null): NullPointerException [PASS]"); + } + + try { + // Case 2: Attempt to add null into the public creds + // Expected result: NullPointerException + mtSubj.getPublicCredentials().add(null); + throw new RuntimeException( + "PUB CRED add(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PUB CRED add(null): NullPointerException [PASS]"); + } + + try { + // Case 3: Attempt to add null into the private creds + // Expected result: NullPointerException + mtSubj.getPrivateCredentials().add(null); + throw new RuntimeException( + "PRIV CRED add(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PRIV CRED add(null): NullPointerException [PASS]"); + } + } + + private static void testRemove() { + System.out.println("------ remove() ------"); + // Create a well formed subject + Subject mtSubj = makeSubj(false, false, false); + + try { + // Case 1: Attempt to remove null values from principal + // Expected result: NullPointerException + mtSubj.getPrincipals().remove(null); + throw new RuntimeException( + "PRINCIPAL remove(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PRINCIPAL remove(null): NullPointerException [PASS]"); + } + + try { + // Case 2: Attempt to remove null from the public creds + // Expected result: NullPointerException + mtSubj.getPublicCredentials().remove(null); + throw new RuntimeException( + "PUB CRED remove(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PUB CRED remove(null): NullPointerException [PASS]"); + } + + try { + // Case 3: Attempt to remove null from the private creds + // Expected result: NullPointerException + mtSubj.getPrivateCredentials().remove(null); + throw new RuntimeException( + "PRIV CRED remove(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PRIV CRED remove(null): NullPointerException [PASS]"); + } + } + + private static void testContains() { + System.out.println("------ contains() ------"); + // Create a well formed subject + Subject mtSubj = makeSubj(false, false, false); + + try { + // Case 1: Attempt to check for null values in principals + // Expected result: NullPointerException + mtSubj.getPrincipals().contains(null); + throw new RuntimeException( + "PRINCIPAL contains(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PRINCIPAL contains(null): NullPointerException [PASS]"); + } + + try { + // Case 2: Attempt to check for null in public creds + // Expected result: NullPointerException + mtSubj.getPublicCredentials().contains(null); + throw new RuntimeException( + "PUB CRED contains(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PUB CRED contains(null): NullPointerException [PASS]"); + } + + try { + // Case 3: Attempt to check for null in private creds + // Expected result: NullPointerException + mtSubj.getPrivateCredentials().contains(null); + throw new RuntimeException( + "PRIV CRED contains(null): Failed to throw NPE"); + } catch (NullPointerException npe) { + System.out.println( + "PRIV CRED contains(null): NullPointerException [PASS]"); + } + } + + private static void testAddAll() { + // Create a well formed subject and additional collections + Subject mtSubj = makeSubj(false, false, false); + Set morePrincs = new HashSet<>(Arrays.asList(tmplAddPrincs)); + Set morePubVals = new HashSet<>(Arrays.asList(tmplAddPubVals)); + Set morePrvVals = new HashSet<>(Arrays.asList(tmplAddPrvVals)); + + // Run one success test for each Subject family to verify the + // overloaded method works as intended. + Set setPrin = mtSubj.getPrincipals(); + Set setPubCreds = mtSubj.getPublicCredentials(); + Set setPrvCreds = mtSubj.getPrivateCredentials(); + int prinOrigSize = setPrin.size(); + int pubOrigSize = setPubCreds.size(); + int prvOrigSize = setPrvCreds.size(); + + System.out.println("------ addAll() -----"); + + // Add the new members, then check the resulting size of the + // Subject attributes to verify they've increased by the proper + // amounts. + if ((validTestCollection(methAdd, setPrin, morePrincs) != true) || + (setPrin.size() != prinOrigSize + morePrincs.size())) + { + throw new RuntimeException("Failed addAll() on principals"); + } + if ((validTestCollection(methAdd, setPubCreds, + morePubVals) != true) || + (setPubCreds.size() != pubOrigSize + morePubVals.size())) + { + throw new RuntimeException("Failed addAll() on public creds"); + } + if ((validTestCollection(methAdd, setPrvCreds, + morePrvVals) != true) || + (setPrvCreds.size() != prvOrigSize + morePrvVals.size())) + { + throw new RuntimeException("Failed addAll() on private creds"); + } + System.out.println("Positive addAll() test passed"); + + // Now add null elements into each container, then retest + morePrincs.add(null); + morePubVals.add(null); + morePrvVals.add(null); + + System.out.println("* Testing addAll w/ null values on Principals"); + nullTestCollection(methAdd, mtSubj.getPrincipals(), null); + nullTestCollection(methAdd, mtSubj.getPrincipals(), morePrincs); + + System.out.println("* Testing addAll w/ null values on Public Creds"); + nullTestCollection(methAdd, mtSubj.getPublicCredentials(), null); + nullTestCollection(methAdd, mtSubj.getPublicCredentials(), + morePubVals); + + System.out.println("* Testing addAll w/ null values on Private Creds"); + nullTestCollection(methAdd, mtSubj.getPrivateCredentials(), null); + nullTestCollection(methAdd, mtSubj.getPrivateCredentials(), + morePrvVals); + } + + private static void testRemoveAll() { + // Create a well formed subject and additional collections + Subject mtSubj = makeSubj(false, false, false); + Set remPrincs = new HashSet<>(); + Set remPubVals = new HashSet<>(); + Set remPrvVals = new HashSet<>(); + + remPrincs.add(new KerberosPrincipal("mtwain/author@LITERATURE.US")); + remPubVals.add("mtwain"); + remPrvVals.add("5Cl3M3nz"); + + // Run one success test for each Subject family to verify the + // overloaded method works as intended. + Set setPrin = mtSubj.getPrincipals(); + Set setPubCreds = mtSubj.getPublicCredentials(); + Set setPrvCreds = mtSubj.getPrivateCredentials(); + int prinOrigSize = setPrin.size(); + int pubOrigSize = setPubCreds.size(); + int prvOrigSize = setPrvCreds.size(); + + System.out.println("------ removeAll() -----"); + + // Remove the specified members, then check the resulting size of the + // Subject attributes to verify they've decreased by the proper + // amounts. + if ((validTestCollection(methRemove, setPrin, remPrincs) != true) || + (setPrin.size() != prinOrigSize - remPrincs.size())) + { + throw new RuntimeException("Failed removeAll() on principals"); + } + if ((validTestCollection(methRemove, setPubCreds, + remPubVals) != true) || + (setPubCreds.size() != pubOrigSize - remPubVals.size())) + { + throw new RuntimeException("Failed removeAll() on public creds"); + } + if ((validTestCollection(methRemove, setPrvCreds, + remPrvVals) != true) || + (setPrvCreds.size() != prvOrigSize - remPrvVals.size())) + { + throw new RuntimeException("Failed removeAll() on private creds"); + } + System.out.println("Positive removeAll() test passed"); + + // Now add null elements into each container, then retest + remPrincs.add(null); + remPubVals.add(null); + remPrvVals.add(null); + + System.out.println("* Testing removeAll w/ null values on Principals"); + nullTestCollection(methRemove, mtSubj.getPrincipals(), null); + nullTestCollection(methRemove, mtSubj.getPrincipals(), remPrincs); + + System.out.println( + "* Testing removeAll w/ null values on Public Creds"); + nullTestCollection(methRemove, mtSubj.getPublicCredentials(), null); + nullTestCollection(methRemove, mtSubj.getPublicCredentials(), + remPubVals); + + System.out.println( + "* Testing removeAll w/ null values on Private Creds"); + nullTestCollection(methRemove, mtSubj.getPrivateCredentials(), null); + nullTestCollection(methRemove, mtSubj.getPrivateCredentials(), + remPrvVals); + } + + private static void testContainsAll() { + // Create a well formed subject and additional collections + Subject mtSubj = makeSubj(false, false, false); + Set testPrincs = new HashSet<>(Arrays.asList(princVals)); + Set testPubVals = new HashSet<>(Arrays.asList(pubVals)); + Set testPrvVals = new HashSet<>(Arrays.asList(privVals)); + + System.out.println("------ containsAll() -----"); + + // Run one success test for each Subject family to verify the + // overloaded method works as intended. + if ((validTestCollection(methContains, mtSubj.getPrincipals(), + testPrincs) == false) && + (validTestCollection(methContains, mtSubj.getPublicCredentials(), + testPubVals) == false) && + (validTestCollection(methContains, + mtSubj.getPrivateCredentials(), testPrvVals) == false)) { + throw new RuntimeException("Valid containsAll() check failed"); + } + System.out.println("Positive containsAll() test passed"); + + // Now let's add a null into each collection and watch the fireworks. + testPrincs.add(null); + testPubVals.add(null); + testPrvVals.add(null); + + System.out.println( + "* Testing containsAll w/ null values on Principals"); + nullTestCollection(methContains, mtSubj.getPrincipals(), null); + nullTestCollection(methContains, mtSubj.getPrincipals(), testPrincs); + + System.out.println( + "* Testing containsAll w/ null values on Public Creds"); + nullTestCollection(methContains, mtSubj.getPublicCredentials(), + null); + nullTestCollection(methContains, mtSubj.getPublicCredentials(), + testPubVals); + + System.out.println( + "* Testing containsAll w/ null values on Private Creds"); + nullTestCollection(methContains, mtSubj.getPrivateCredentials(), + null); + nullTestCollection(methContains, mtSubj.getPrivateCredentials(), + testPrvVals); + } + + private static void testRetainAll() { + // Create a well formed subject and additional collections + Subject mtSubj = makeSubj(false, false, false); + Set remPrincs = new HashSet<>(Arrays.asList(tmplAddPrincs)); + Set remPubVals = new HashSet<>(Arrays.asList(tmplAddPubVals)); + Set remPrvVals = new HashSet<>(Arrays.asList(tmplAddPrvVals)); + + // Add in values that exist within the Subject + remPrincs.add(princVals[2]); + remPubVals.add(pubVals[2]); + remPrvVals.add(privVals[2]); + + // Run one success test for each Subject family to verify the + // overloaded method works as intended. + Set setPrin = mtSubj.getPrincipals(); + Set setPubCreds = mtSubj.getPublicCredentials(); + Set setPrvCreds = mtSubj.getPrivateCredentials(); + int prinOrigSize = setPrin.size(); + int pubOrigSize = setPubCreds.size(); + int prvOrigSize = setPrvCreds.size(); + + System.out.println("------ retainAll() -----"); + + // Retain the specified members (those that exist in the Subject) + // and validate the results. + if (validTestCollection(methRetain, setPrin, remPrincs) == false || + setPrin.size() != 1 || setPrin.contains(princVals[2]) == false) + { + throw new RuntimeException("Failed retainAll() on principals"); + } + + if (validTestCollection(methRetain, setPubCreds, + remPubVals) == false || + setPubCreds.size() != 1 || + setPubCreds.contains(pubVals[2]) == false) + { + throw new RuntimeException("Failed retainAll() on public creds"); + } + if (validTestCollection(methRetain, setPrvCreds, + remPrvVals) == false || + setPrvCreds.size() != 1 || + setPrvCreds.contains(privVals[2]) == false) + { + throw new RuntimeException("Failed retainAll() on private creds"); + } + System.out.println("Positive retainAll() test passed"); + + // Now add null elements into each container, then retest + remPrincs.add(null); + remPubVals.add(null); + remPrvVals.add(null); + + System.out.println("* Testing retainAll w/ null values on Principals"); + nullTestCollection(methRetain, mtSubj.getPrincipals(), null); + nullTestCollection(methRetain, mtSubj.getPrincipals(), remPrincs); + + System.out.println( + "* Testing retainAll w/ null values on Public Creds"); + nullTestCollection(methRetain, mtSubj.getPublicCredentials(), null); + nullTestCollection(methRetain, mtSubj.getPublicCredentials(), + remPubVals); + + System.out.println( + "* Testing retainAll w/ null values on Private Creds"); + nullTestCollection(methRetain, mtSubj.getPrivateCredentials(), null); + nullTestCollection(methRetain, mtSubj.getPrivateCredentials(), + remPrvVals); + } + + private static void testIsEmpty() { + Subject populatedSubj = makeSubj(false, false, false); + Subject emptySubj = new Subject(); + + System.out.println("------ isEmpty() -----"); + + if (populatedSubj.getPrincipals().isEmpty()) { + throw new RuntimeException( + "Populated Subject Principals incorrectly returned empty"); + } + if (emptySubj.getPrincipals().isEmpty() == false) { + throw new RuntimeException( + "Empty Subject Principals incorrectly returned non-empty"); + } + System.out.println("isEmpty() test passed"); + } + + private static void testSecureSetEquals() { + System.out.println("------ SecureSet.equals() -----"); + + Subject subj = makeSubj(false, false, false); + + // Case 1: null comparison [expect false] + if (subj.getPublicCredentials().equals(null) != false) { + throw new RuntimeException( + "equals(null) incorrectly returned true"); + } + + // Case 2: Self-comparison [expect true] + Set princs = subj.getPrincipals(); + princs.equals(subj.getPrincipals()); + + // Case 3: Comparison with non-Set type [expect false] + List listPrinc = + new LinkedList(Arrays.asList(princVals)); + if (subj.getPublicCredentials().equals(listPrinc) != false) { + throw new RuntimeException( + "equals([Non-Set]) incorrectly returned true"); + } + + // Case 4: SecureSets of differing sizes [expect false] + Subject subj1princ = new Subject(); + Subject subj2princ = new Subject(); + subj1princ.getPrincipals().add( + new X500Principal("CN=Tom Sawyer, ST=Missouri, C=US")); + subj1princ.getPrincipals().add( + new X500Principal("CN=John Doe, O=Bogus Corp.")); + subj2princ.getPrincipals().add( + new X500Principal("CN=Tom Sawyer, ST=Missouri, C=US")); + if (subj1princ.getPrincipals().equals( + subj2princ.getPrincipals()) != false) { + throw new RuntimeException( + "equals([differing sizes]) incorrectly returned true"); + } + + // Case 5: Content equality test [expect true] + Set equalSet = + new HashSet(Arrays.asList(princVals)); + if (subj.getPrincipals().equals(equalSet) != true) { + throw new RuntimeException( + "equals([equivalent set]) incorrectly returned false"); + } + + // Case 5: Content inequality test [expect false] + + // Note: to not fall into the size inequality check the two + // sets need to have the same number of elements. + Set inequalSet = + new HashSet(Arrays.asList(tmplAddPrincs)); + inequalSet.add(new JMXPrincipal("Samuel Clemens")); + + if (subj.getPrincipals().equals(inequalSet) != false) { + throw new RuntimeException( + "equals([equivalent set]) incorrectly returned false"); + } + System.out.println("SecureSet.equals() tests passed"); + } + + private static void testToArray() { + System.out.println("------ toArray() -----"); + + Subject subj = makeSubj(false, false, false); + + // Case 1: no-parameter toArray with equality comparison + // Expected result: true + List alSubj = Arrays.asList(subj.getPrincipals().toArray()); + List alPrincs = Arrays.asList(princVals); + + if (alSubj.size() != alPrincs.size() || + alSubj.containsAll(alPrincs) != true) { + throw new RuntimeException( + "Unexpected inequality on returned toArray()"); + } + + // Case 2: generic-type toArray where passed array is of sufficient + // size. + // Expected result: returned Array is reference-equal to input param + // and content equal to data used to construct the originating Subject. + Principal[] pBlock = new Principal[3]; + Principal[] pBlockRef = subj.getPrincipals().toArray(pBlock); + alSubj = Arrays.asList(pBlockRef); + + if (pBlockRef != pBlock) { + throw new RuntimeException( + "Unexpected reference-inequality on returned toArray(T[])"); + } else if (alSubj.size() != alPrincs.size() || + alSubj.containsAll(alPrincs) != true) { + throw new RuntimeException( + "Unexpected content-inequality on returned toArray(T[])"); + } + + // Case 3: generic-type toArray where passed array is of + // insufficient size. + // Expected result: returned Array is not reference-equal to + // input param but is content equal to data used to construct the + // originating Subject. + pBlock = new Principal[1]; + pBlockRef = subj.getPrincipals().toArray(pBlock); + alSubj = Arrays.asList(pBlockRef); + + if (pBlockRef == pBlock) { + throw new RuntimeException( + "Unexpected reference-equality on returned toArray(T[])"); + } else if (alSubj.size() != alPrincs.size() || + alSubj.containsAll(alPrincs) != true) { + throw new RuntimeException( + "Unexpected content-inequality on returned toArray(T[])"); + } + System.out.println("toArray() tests passed"); + } + + public static void main(String[] args) throws Exception { + + testCTOR(); + + testDeserialize(); + + testAdd(); + + testRemove(); + + testContains(); + + testAddAll(); + + testRemoveAll(); + + testContainsAll(); + + testRetainAll(); + + testIsEmpty(); + + testSecureSetEquals(); + + testToArray(); + } +}