diff --git a/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java b/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java index 378bd198..1e4697bf 100644 --- a/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java +++ b/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java @@ -10,7 +10,7 @@ import static ch.jalu.configme.properties.PropertyInitializer.newProperty; public final class DatabaseSettings implements SettingsHolder { @Comment({"What type of database do you want to use?", - "Valid values: sqlite, mysql"}) + "Valid values: SQLITE, MYSQL"}) public static final Property BACKEND = newProperty(DataSourceType.class, "DataSource.backend", DataSourceType.SQLITE); diff --git a/src/test/java/fr/xephi/authme/settings/SettingsConsistencyTest.java b/src/test/java/fr/xephi/authme/settings/SettingsConsistencyTest.java index 88724a84..dc5340ae 100644 --- a/src/test/java/fr/xephi/authme/settings/SettingsConsistencyTest.java +++ b/src/test/java/fr/xephi/authme/settings/SettingsConsistencyTest.java @@ -1,15 +1,25 @@ package fr.xephi.authme.settings; import ch.jalu.configme.configurationdata.ConfigurationData; +import ch.jalu.configme.properties.EnumProperty; import ch.jalu.configme.properties.Property; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multimap; +import fr.xephi.authme.datasource.DataSourceType; import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever; +import fr.xephi.authme.settings.properties.DatabaseSettings; +import fr.xephi.authme.settings.properties.SecuritySettings; import org.junit.BeforeClass; import org.junit.Test; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; +import static fr.xephi.authme.ReflectionTestUtils.getFieldValue; import static org.junit.Assert.fail; /** @@ -22,6 +32,17 @@ public class SettingsConsistencyTest { */ private static final int MAX_COMMENT_LENGTH = 90; + /** + * Exclusions for the enum in comments check. Use {@link Exclude#ALL} + * to skip an entire property from being checked. + */ + private static final Multimap, Enum> EXCLUDED_ENUMS = + ImmutableSetMultimap., Enum>builder() + .put(DatabaseSettings.BACKEND, DataSourceType.FILE) + .put(SecuritySettings.PASSWORD_HASH, Exclude.ALL) + .put(SecuritySettings.LEGACY_HASHES, Exclude.ALL) + .build(); + private static ConfigurationData configurationData; @BeforeClass @@ -66,4 +87,63 @@ public class SettingsConsistencyTest { } } + /** + * Checks that enum properties have all possible enum values listed in their comment + * so the user knows which values are available. + */ + @Test + public void shouldMentionAllEnumValues() { + // given + Map, Enum> invalidEnumProperties = new HashMap<>(); + + for (Property property : configurationData.getProperties()) { + // when + Class> enumClass = getEnumClass(property); + if (enumClass != null) { + String comments = String.join("\n", configurationData.getCommentsForSection(property.getPath())); + Arrays.stream(enumClass.getEnumConstants()) + .filter(e -> !comments.contains(e.name()) && !isExcluded(property, e)) + .findFirst() + .ifPresent(e -> invalidEnumProperties.put(property, e)); + } + } + + // then + if (!invalidEnumProperties.isEmpty()) { + String invalidEnums = invalidEnumProperties.entrySet().stream() + .map(e -> e.getKey() + " does not mention " + e.getValue() + " and possibly others") + .collect(Collectors.joining("\n- ")); + + fail("Found enum properties that do not list all entries in the comments:\n- " + invalidEnums); + } + } + + /** + * Returns the enum class the property holds values for, if applicable. + * + * @param property the property to get the enum class from + * @return the enum class, or null if not available + */ + private static Class> getEnumClass(Property property) { + if (property instanceof EnumProperty) { + return getFieldValue(EnumProperty.class, (EnumProperty) property, "clazz"); + } else if (property instanceof EnumSetProperty) { + return getFieldValue(EnumSetProperty.class, (EnumSetProperty) property, "enumClass"); + } + return null; + } + + private static boolean isExcluded(Property property, Enum enumValue) { + return EXCLUDED_ENUMS.get(property).contains(Exclude.ALL) + || EXCLUDED_ENUMS.get(property).contains(enumValue); + } + + /** + * Dummy enum to specify in the exclusion that all enum values + * should be skipped. See its usages. + */ + private enum Exclude { + ALL + } + }