/*
* 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
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]");
}
@SuppressWarnings("unchecked")
private static void testDeserialize() throws Exception {
System.out.println("------ deserialize -----");
Subject subj = null;
Set<Principal> prin = null;
// Case 1: positive deserialization test of a Subject
// Expected result: well-formed Subject
subj = deserializeBuffer(Subject.class, SUBJ_NO_NULL);
System.out.println("Positive deserialization test (Subject) passed");
// Case 2: positive deserialization test of a SecureSet
// Expected result: well-formed Set
prin = deserializeBuffer(Set.class, PRIN_NO_NULL);
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 = deserializeBuffer(Subject.class, SUBJ_WITH_NULL);
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 = deserializeBuffer(Set.class, PRIN_WITH_NULL);
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<Principal> morePrincs = new HashSet<>(Arrays.asList(tmplAddPrincs));
Set<Object> morePubVals = new HashSet<>(Arrays.asList(tmplAddPubVals));
Set<Object> morePrvVals = new HashSet<>(Arrays.asList(tmplAddPrvVals));
// Run one success test for each Subject family to verify the
// overloaded method works as intended.
Set<Principal> setPrin = mtSubj.getPrincipals();
Set<Object> setPubCreds = mtSubj.getPublicCredentials();
Set<Object> 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<Principal> remPrincs = new HashSet<>();
Set<Object> remPubVals = new HashSet<>();
Set<Object> 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<Principal> setPrin = mtSubj.getPrincipals();
Set<Object> setPubCreds = mtSubj.getPublicCredentials();
Set<Object> 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<Principal> testPrincs = new HashSet<>(Arrays.asList(princVals));
Set<Object> testPubVals = new HashSet<>(Arrays.asList(pubVals));
Set<Object> 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<Principal> remPrincs = new HashSet<>(Arrays.asList(tmplAddPrincs));
Set<Object> remPubVals = new HashSet<>(Arrays.asList(tmplAddPubVals));
Set<Object> 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<Principal> setPrin = mtSubj.getPrincipals();
Set<Object> setPubCreds = mtSubj.getPublicCredentials();
Set<Object> 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);
Subject subjComp = 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<Principal> princs = subj.getPrincipals();
princs.equals(subj.getPrincipals());
// Case 3: Comparison with non-Set type [expect false]
List<Principal> 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<Principal> 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<Principal> inequalSet =
new HashSet<Principal>(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 testSecureSetHashCode() {
System.out.println("------ SecureSet.hashCode() -----");
Subject subj = makeSubj(false, false, false);
// Make sure two other Set types that we know are equal per
// SecureSet.equals() and verify their hashCodes are also the same
Set<Principal> equalHashSet = new HashSet<>(Arrays.asList(princVals));
if (subj.getPrincipals().hashCode() != equalHashSet.hashCode()) {
throw new RuntimeException(
"SecureSet and HashSet hashCodes() differ");
}
System.out.println("SecureSet.hashCode() 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<Object> alSubj = Arrays.asList(subj.getPrincipals().toArray());
List<Principal> 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((Object[])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((Object[])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();
testSecureSetHashCode();
testToArray();
}
}