package org.dcache.auth;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import static org.junit.Assert.*;
/**
* This class provides test-cases for the FQAN class.
*
* From page 6 of
*
* http://www.ogf.org/Public_Comment_Docs/Documents/2009-06/VOMSACv10-editor-1.doc.pdf
*
* "This information is encoded in a Fully Qualified Attribute Name (FQAN),
* in the following format:
*
* <group name>/Role=<role name>/Capability=<capability name>
*
* This syntax means that the user holds the role <role name> in the group
* <group name>. If no specific role is held, the <role name> is NULL. The
* /Capability=<capability name> part is deprecated and will disappear in
* the future: conforming applications SHOULD be able to handle FQANs where
* it is absent and SHOULD NOT rely on its presence.
*
* Future compatibility issue: It is possible that in the future a
* /Role=NULL component may be omitted in its entirety. The same goes for a
* /Capability=NULL part. Conforming applications SHOULD be prepared to
* handle these cases."
*
* @author jans
* @author Paul Millar <paul.millar@desy.de>
*/
public class FQANTest {
/**
* The items that may make up a FQAN. The VO is always
* present, but GROUP, ROLE and CAPABILITY are optional.
*/
public enum FqanElements {
VO, GROUP, ROLE, CAPABILITY
}
/* Main set of data used to build test FQANs */
private static final String VO_NAME = "atlas";
private static final String GROUP_NAME = "higgs";
private static final String ROLE_NAME = "production";
private static final String CAPABILITY_NAME = "some-capability";
/* Alternative non-equal data used for inequality tests */
private static final String OTHER_VO_NAME = "cms";
private static final String OTHER_GROUP_NAME = "LAr";
private static final String OTHER_ROLE_NAME = "observer";
private static final String OTHER_CAPABILITY_NAME = "other-capability";
private static final String EMPTY_STRING = "";
private static final FQAN[] ALL_TYPES = buildFqanArrayOfAllTypes();
private static final String[] INVALID_FQANS = {
null, // null isn't valid
VO_NAME, // lack of initial '/'
"/*", // illegal character of VO
"/-" + VO_NAME, // illegal initial character of VO
"/0" + VO_NAME, // " " " " "
"/A" + VO_NAME, // " " " " "
"/" + VO_NAME + "-", // illegal final character of VO
"/" + VO_NAME + ".", // " " " " "
"/" + VO_NAME + "/", // empty group not allowed
"/" + VO_NAME + "/*", // illegal character in (sub)group
"/" + VO_NAME + "/=" + GROUP_NAME, // illegal character in (sub)group
"/" + VO_NAME + "/" + GROUP_NAME + "=", // illegal character in (sub)group
"/" + VO_NAME + "/" + GROUP_NAME + "=NULL", // illegal character in (sub)group
"/" + VO_NAME + "/Role=", // empty role not allowed
"/" + VO_NAME + "/Role=" + ROLE_NAME + " ", // illegal character in role
"/" + VO_NAME + "/Role= " + ROLE_NAME, // illegal character in role
"/" + VO_NAME + "/Role=" + ROLE_NAME + ".", // illegal character in role
"/" + VO_NAME + "/Role=." + ROLE_NAME, // illegal character in role
"/" + VO_NAME + "/Role=*", // illegal character in role
"/" + VO_NAME + "/Capability=", // empty capability not allowed
"/" + VO_NAME + "/Capability=" + CAPABILITY_NAME + " ", // illegal character in capability
"/" + VO_NAME + "/Capability= " + CAPABILITY_NAME, // illegal character in capability
"/" + VO_NAME + "/Capability=" + CAPABILITY_NAME + ".", // illegal character in capability
"/" + VO_NAME + "/Capability=." + CAPABILITY_NAME, // illegal character in capability
};
@Test(expected=IllegalArgumentException.class)
public void testCreateWithNullNotAllowed() {
new FQAN(null);
}
@Test
public void testTypesEqualsIsReflexive() {
for( FQAN fqan1 : ALL_TYPES) {
assertEquals( fqan1, fqan1);
FQAN fqan2 = new FQAN( fqan1.toString());
assertEquals( fqan1, fqan2);
}
}
@Test
public void testDifferentTypesNotEqual() {
for( int i = 0; i < ALL_TYPES.length; i++) {
FQAN fqan1 = ALL_TYPES[i];
for( int j = 0; j < ALL_TYPES.length; j++) {
FQAN fqan2 = ALL_TYPES[j];
if( i != j) {
assertFalse( fqan1.equals( fqan2));
}
}
}
}
@Test
public void testNotEqualByVO() {
FQAN[] otherVoFqans = buildFqanArrayWithOtherVo( OTHER_VO_NAME);
assertNoneEqual( otherVoFqans);
}
@Test
public void testNotEqualByGroup() {
FQAN[] otherGroupFqans =
buildFqanArrayWithOtherGroup( OTHER_GROUP_NAME);
assertNoneEqual( otherGroupFqans);
}
@Test
public void testNotEqualByRole() {
FQAN[] otherRoleFqans = buildFqanArrayWithOtherRole( OTHER_ROLE_NAME);
assertNoneEqual( otherRoleFqans);
}
@Test
public void testNotEqualByCapability() {
FQAN[] otherCapabilityFqans =
buildFqanArrayWithOtherCapability( OTHER_CAPABILITY_NAME);
assertNoneEqual( otherCapabilityFqans);
}
@Test
public void testGetGroupForFqansWithGroup() {
FQAN[] fqansWithGroup = buildFqanArrayWith( FqanElements.GROUP);
for( FQAN fqanWithGroup : fqansWithGroup) {
String expectedString = "/" + VO_NAME + "/" + GROUP_NAME;
assertEquals( "Testing " + fqanWithGroup, expectedString,
fqanWithGroup.getGroup());
}
}
@Test
public void testGetGroupForFqansWithoutGroup() {
FQAN[] fqansWithoutGroup = buildFqanArrayWithNoneOf( FqanElements.GROUP);
String expectedGroup = "/" + VO_NAME;
for( FQAN fqanWithoutGroup : fqansWithoutGroup) {
assertEquals( "Testing " + fqanWithoutGroup, expectedGroup,
fqanWithoutGroup.getGroup());
}
}
@Test
public void testGetRoleForFqansWithRole() {
FQAN[] fqansWithRole = buildFqanArrayWith( FqanElements.ROLE);
for( FQAN fqanWithRole : fqansWithRole) {
assertEquals( "Testing " + fqanWithRole, ROLE_NAME, fqanWithRole
.getRole());
}
}
@Test
public void testGetRoleForFqansWithoutRole() {
FQAN[] fqansWithoutRole = buildFqanArrayWithNoneOf( FqanElements.ROLE);
for( FQAN fqanWithoutRole : fqansWithoutRole) {
assertEquals( "Testing " + fqanWithoutRole, EMPTY_STRING,
fqanWithoutRole.getRole());
}
}
@Test
public void testGetCapabilityForFqansWithCapability() {
FQAN[] fqansWithCapability =
buildFqanArrayWith( FqanElements.CAPABILITY);
for( FQAN fqanWithCapability : fqansWithCapability) {
assertEquals( "Testing " + fqanWithCapability, CAPABILITY_NAME,
fqanWithCapability.getCapability());
}
}
@Test
public void testGetCapabilityForFqansWithoutCapability() {
FQAN[] fqansWithoutCapability =
buildFqanArrayWithNoneOf( FqanElements.CAPABILITY);
for( FQAN fqanWithoutCapability : fqansWithoutCapability) {
assertEquals( "Testing " + fqanWithoutCapability, EMPTY_STRING,
fqanWithoutCapability.getCapability());
}
}
@Test
public void testHasRoleForFqanWithNoRole() {
FQAN[] fqansWithoutRole =
buildFqanArrayWithNoneOf( FqanElements.ROLE);
for( FQAN fqanWithoutRole : fqansWithoutRole) {
assertFalse( "Testing " + fqanWithoutRole, fqanWithoutRole.hasRole());
}
}
@Test
public void testHasRoleForFqanWithRole() {
FQAN[] fqansWithRole =
buildFqanArrayWith( FqanElements.ROLE);
for( FQAN fqanWithRole : fqansWithRole) {
assertTrue( "Testing " + fqanWithRole, fqanWithRole.hasRole());
}
}
@Test
public void testHasCapabilityForFqanWithNoCapability() {
FQAN[] fqansWithoutCapability =
buildFqanArrayWithNoneOf( FqanElements.CAPABILITY);
for( FQAN fqanWithoutCapability : fqansWithoutCapability) {
assertFalse( "Testing " + fqanWithoutCapability, fqanWithoutCapability.hasCapability());
}
}
@Test
public void testHasCapabilityForFqanWithCapability() {
FQAN[] fqansWithCapability =
buildFqanArrayWith( FqanElements.CAPABILITY);
for( FQAN fqanWithCapability : fqansWithCapability) {
assertTrue( "Testing " + fqanWithCapability, fqanWithCapability.hasCapability());
}
}
/*
* TEST for Role=NULL and Capability=NULL
*/
@Test
public void testRoleNullAndNoCapabilityEqualsWithoutRole() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( EnumSet.of( FqanElements.ROLE, FqanElements.CAPABILITY));
for(FQAN fqan : fqansWithoutRoleOrCapability) {
FQAN fqanWithNullRole = new FQAN(fqan.toString() + "/Role=NULL");
assertTrue("Testing " + fqan + " equals " + fqanWithNullRole, fqan.equals( fqanWithNullRole));
assertTrue("Testing " + fqanWithNullRole + " equals " + fqan, fqanWithNullRole.equals( fqan));
}
}
@Test
public void testRoleNullAndCapabilityEqualsWithoutRole() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( EnumSet.of( FqanElements.ROLE, FqanElements.CAPABILITY));
for(FQAN fqan : fqansWithoutRoleOrCapability) {
String capabilitySuffix = "/Capability=" + CAPABILITY_NAME;
FQAN fqanWithoutNullRole = new FQAN(fqan + capabilitySuffix );
FQAN fqanWithNullRole = new FQAN(fqan + "/Role=NULL" + capabilitySuffix );
assertTrue("Testing " + fqanWithNullRole, fqanWithoutNullRole.equals( fqanWithNullRole));
assertTrue("Testing " + fqanWithNullRole, fqanWithNullRole.equals( fqanWithoutNullRole));
}
}
@Test
public void testCapabilityNullEqualsWithout() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( FqanElements.CAPABILITY);
for(FQAN fqan : fqansWithoutRoleOrCapability) {
FQAN fqanWithNullCapability = new FQAN(fqan.toString() + "/Capability=NULL");
assertTrue("Testing " + fqan, fqan.equals( fqanWithNullCapability));
assertTrue("Testing " + fqan, fqanWithNullCapability.equals( fqan));
}
}
@Test
public void testGetRoleForRoleNull() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( EnumSet.of( FqanElements.ROLE, FqanElements.CAPABILITY));
for(FQAN fqan : fqansWithoutRoleOrCapability) {
FQAN fqanWithNullRole = new FQAN(fqan.toString() + "/Role=NULL");
assertEquals("Checking " + fqanWithNullRole, "", fqanWithNullRole.getRole());
}
}
@Test
public void testGetCapabilityForCapabilityNull() {
FQAN[] fqansWithoutCapability =
buildFqanArrayWithNoneOf( FqanElements.CAPABILITY);
for(FQAN fqan : fqansWithoutCapability) {
FQAN fqanWithNullCapability = new FQAN(fqan + "/Capability=NULL");
assertEquals("Testing " + fqanWithNullCapability, "", fqanWithNullCapability.getCapability());
}
}
@Test
public void testToStringForRoleNullAndNoCapability() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( EnumSet.of( FqanElements.ROLE, FqanElements.CAPABILITY));
for(FQAN fqan : fqansWithoutRoleOrCapability) {
FQAN fqanWithNullRole = new FQAN(fqan.toString() + "/Role=NULL");
assertEquals("Testing " + fqan, fqan.toString(), fqanWithNullRole.toString());
}
}
@Test
public void testToStringForRoleNullAndSomeCapability() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( EnumSet.of( FqanElements.ROLE, FqanElements.CAPABILITY));
for(FQAN fqan : fqansWithoutRoleOrCapability) {
String capabilitySuffix = "/Capability=" + CAPABILITY_NAME;
FQAN fqanWithoutNullRole = new FQAN(fqan + capabilitySuffix );
FQAN fqanWithNullRole = new FQAN(fqan + "/Role=NULL" + capabilitySuffix );
assertEquals("Testing " + fqanWithoutNullRole, fqanWithoutNullRole.toString(), fqanWithNullRole.toString());
}
}
@Test
public void testToStringForCapabilityNull() {
FQAN[] fqansWithoutRoleOrCapability =
buildFqanArrayWithNoneOf( FqanElements.CAPABILITY);
for(FQAN fqan : fqansWithoutRoleOrCapability) {
FQAN fqanWithNullCapability = new FQAN(fqan.toString() + "/Capability=NULL");
assertEquals("Testing " + fqan, fqan.toString(), fqanWithNullCapability.toString());
}
}
@Test
public void testIsValidForValidFqans() {
for( FQAN fqan : ALL_TYPES) {
assertTrue( "Checking " + fqan + " is valid", FQAN.isValid( fqan.toString()));
}
}
@Test
public void testIsValidForInvalidFqans() {
for( String invalidFqan : INVALID_FQANS) {
assertFalse( "Checking " + invalidFqan + " is invalid", FQAN.isValid( invalidFqan));
}
}
private void assertNoneEqual( FQAN[] others) {
for( FQAN fqan1 : ALL_TYPES) {
for( FQAN fqan2 : others) {
assertFalse( "Testing " + fqan1 + " not equal to " + fqan2, fqan1.equals( fqan2));
assertFalse( "Testing " + fqan2 + " not equal to " + fqan1, fqan2.equals( fqan1));
}
}
}
private static FQAN[] buildFqanArrayOfAllTypes() {
return buildFqanArrayOfAllWith( VO_NAME, GROUP_NAME, ROLE_NAME, CAPABILITY_NAME,
EnumSet.allOf( FqanElements.class));
}
private static FQAN[] buildFqanArrayWith( FqanElements allWith) {
return buildFqanArrayOfAllWith( VO_NAME, GROUP_NAME, ROLE_NAME, CAPABILITY_NAME,
EnumSet.of( allWith));
}
private static FQAN[] buildFqanArrayWithNoneOf( FqanElements allWithout) {
return buildFqanArray( VO_NAME, GROUP_NAME, ROLE_NAME, CAPABILITY_NAME,
EnumSet.allOf( FqanElements.class), EnumSet.of( allWithout));
}
private static FQAN[] buildFqanArrayWithNoneOf( Set<FqanElements> allWithout) {
return buildFqanArray( VO_NAME, GROUP_NAME, ROLE_NAME, CAPABILITY_NAME,
EnumSet.allOf( FqanElements.class), allWithout);
}
private static FQAN[] buildFqanArrayWithOtherVo( String voName) {
return buildFqanArrayOfAllWith( voName, GROUP_NAME, ROLE_NAME, CAPABILITY_NAME,
EnumSet.of( FqanElements.VO));
}
private static FQAN[] buildFqanArrayWithOtherGroup( String groupName) {
return buildFqanArrayOfAllWith( VO_NAME, groupName, ROLE_NAME, CAPABILITY_NAME,
EnumSet.of( FqanElements.GROUP));
}
private static FQAN[] buildFqanArrayWithOtherRole( String roleName) {
return buildFqanArrayOfAllWith( VO_NAME, GROUP_NAME, roleName, CAPABILITY_NAME,
EnumSet.of( FqanElements.ROLE));
}
private static FQAN[] buildFqanArrayWithOtherCapability( String capabilityName) {
return buildFqanArrayOfAllWith( VO_NAME, GROUP_NAME, ROLE_NAME, capabilityName,
EnumSet.of( FqanElements.CAPABILITY));
}
private static FQAN[] buildFqanArrayOfAllWith(String voName, String groupName,
String roleName, String capabilityName,
Set<FqanElements> allWith) {
return buildFqanArray( voName, groupName, roleName, capabilityName, allWith,
EnumSet.noneOf( FqanElements.class));
}
/**
* Build an array of FQANs by considering the supplied VO name, group
* name, role name and capability name. The resulting FQANs have the
* form:
*
*<pre>
* "/" voName ["/" groupName] ["/Role=" roleName] ["/Capability=" capabilityName]
*</pre>
*
* The allWith argument is used to control the list of FQANs returned.
* Only those FQANs that include some type corresponding to an element in
* the allWith Set are included in the returned array; for example, specifying
* allWith with ROLE as its single element, {ROLE}, returns an array with
* only those FQANs with a "/Role=" value:
*
*<pre>
* /voName/Role=roleName
* /voName/Role=roleName/Capability=capabilityName
* /voName/groupName/Role=roleName
* /voName/groupName/Role=roleName/Capability=capabilityName
*</pre>
*
* The allWithout argument further controls the output so that the returned array
* of FQANs will not include any that have an FqanElement included in the
* allWithout Set.
*/
private static FQAN[] buildFqanArray( String voName, String groupName,
String roleName, String capabilityName,
Set<FqanElements> allWith,
Set<FqanElements> allWithout) {
List<FQAN> fqans = new ArrayList<>();
String voFqan = "/" + voName;
String voAndGroup = voFqan + "/" + groupName;
String roleSuffix = "/Role=" + roleName;
String capabilitySuffix = "/Capability=" + capabilityName;
if( isIncludeable( allWith, allWithout, EnumSet.of( FqanElements.VO))) {
fqans.add( new FQAN( voFqan));
}
if( isIncludeable( allWith, allWithout, EnumSet.of( FqanElements.VO,
FqanElements.ROLE))) {
fqans.add( new FQAN( voFqan + roleSuffix));
}
if( isIncludeable(allWith, allWithout, EnumSet.of(FqanElements.VO,
FqanElements.CAPABILITY))) {
fqans.add( new FQAN( voFqan + capabilitySuffix));
}
if( isIncludeable( allWith, allWithout, EnumSet.of( FqanElements.VO,
FqanElements.ROLE, FqanElements.CAPABILITY))) {
fqans.add( new FQAN( voFqan + roleSuffix + capabilitySuffix));
}
if( isIncludeable( allWith, allWithout, EnumSet.of( FqanElements.VO,
FqanElements.GROUP))) {
fqans.add( new FQAN( voAndGroup));
}
if( isIncludeable( allWith, allWithout, EnumSet.of( FqanElements.VO,
FqanElements.GROUP, FqanElements.ROLE))) {
fqans.add( new FQAN( voAndGroup + roleSuffix));
}
if( isIncludeable(allWith, allWithout, EnumSet.of(FqanElements.VO,
FqanElements.GROUP, FqanElements.CAPABILITY))) {
fqans.add( new FQAN( voAndGroup + capabilitySuffix));
}
if( isIncludeable( allWith, allWithout, EnumSet.of( FqanElements.VO,
FqanElements.GROUP, FqanElements.ROLE, FqanElements.CAPABILITY))) {
fqans.add( new FQAN( voAndGroup + roleSuffix + capabilitySuffix));
}
return fqans.toArray( new FQAN[fqans.size()]);
}
private static boolean isIncludeable( Set<FqanElements> allWith,
Set<FqanElements> allWithout,
Set<FqanElements> present) {
boolean isIncludeableFromAllWith = !Collections.disjoint( allWith, present);
boolean isIncludeableNotAllWithout = Collections.disjoint( allWithout, present);
return isIncludeableFromAllWith && isIncludeableNotAllWithout;
}
}