package net.socialgamer.cah; import static org.junit.Assert.fail; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import net.socialgamer.cah.Constants.DuplicationAllowed; import org.junit.Test; public class ConstantsTest { /** * Test to make sure that no two over-the-wire message constants use the same value. In theory, we * only need to make sure that it's only unique in a particular enum, but it doesn't hurt to * ensure global uniqueness. */ @Test public void ensureNoDuplicateValues() throws Exception { final Map allFields = new HashMap(); final Class[] classes = Constants.class.getClasses(); for (final Class c : classes) { // We only care about enums. if (!c.isEnum()) { continue; } final Map fields = getEnumValues(c); for (final Map.Entry entry : fields.entrySet()) { if (allFields.containsKey(entry.getValue())) { fail(String.format("Value '%s' defined for %s.%s, already defined for %s.", entry.getValue(), c.getName(), entry.getKey(), allFields.get(entry.getValue()))); } allFields.put(entry.getValue(), c.getName() + "." + entry.getKey()); } } } /** * Return a map of enum values in an Enum class, with the enum field names as keys and the values * of toString() as the values. * * Completely ignores enum values annotated with DuplicationAllowed. * * @param enumClass * The Enum to examine. * @return Map of field name -> toString values. * @throws IllegalArgumentException * Thrown if {@code enumClass} isn't actually an enum. * @throws IllegalAccessException * If the value was unable to be retrieved. */ private static Map getEnumValues(final Class enumClass) throws IllegalArgumentException, IllegalAccessException { if (!enumClass.isEnum()) { throw new IllegalArgumentException(enumClass.getName() + " is not an enum"); } final Field[] flds = enumClass.getDeclaredFields(); final HashMap enumMap = new HashMap(); for (final Field f : flds) { if (f.isEnumConstant() && !f.isAnnotationPresent(DuplicationAllowed.class)) { enumMap.put(f.getName(), f.get(null).toString()); } } return enumMap; } }