From 1743aad851a1df8ed9a2d519b623e1295ed20bae Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 9 Jun 2022 20:54:18 -0500 Subject: [PATCH] Add Api Enum Unit tests --- .../apiObjects/enums/DhApiEnumAssembly.java | 31 +++++ .../lod/core/enums/CoreEnumAssembly.java | 37 ++++++ .../enums/config/CoreConfigEnumAssembly.java | 31 +++++ .../rendering/CoreRenderingEnumAssembly.java | 31 +++++ .../com/seibel/lod/core/util/EnumUtil.java | 35 ++++-- src/test/java/ApiEnumSyncTests.java | 114 +++++++++++++---- src/test/java/EnumTestHelper.java | 116 ++++++++++++++++++ 7 files changed, 361 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/seibel/lod/core/api/external/apiObjects/enums/DhApiEnumAssembly.java create mode 100644 src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java create mode 100644 src/main/java/com/seibel/lod/core/enums/config/CoreConfigEnumAssembly.java create mode 100644 src/main/java/com/seibel/lod/core/enums/rendering/CoreRenderingEnumAssembly.java create mode 100644 src/test/java/EnumTestHelper.java diff --git a/src/main/java/com/seibel/lod/core/api/external/apiObjects/enums/DhApiEnumAssembly.java b/src/main/java/com/seibel/lod/core/api/external/apiObjects/enums/DhApiEnumAssembly.java new file mode 100644 index 000000000..e46e84c28 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/api/external/apiObjects/enums/DhApiEnumAssembly.java @@ -0,0 +1,31 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.core.api.external.apiObjects.enums; + +/** + * Assembly classes are used to reference the package they are in. + * + * @author James Seibel + * @version 2022-6-9 + */ +public class DhApiEnumAssembly +{ + public static final String API_ENUM_PREFIX = "DhApi"; +} diff --git a/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java b/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java new file mode 100644 index 000000000..50dca2c4c --- /dev/null +++ b/src/main/java/com/seibel/lod/core/enums/CoreEnumAssembly.java @@ -0,0 +1,37 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.core.enums; + +import com.seibel.lod.core.enums.config.CoreConfigEnumAssembly; +import com.seibel.lod.core.enums.rendering.CoreRenderingEnumAssembly; + +/** + * Assembly classes are used to reference the package they are in. + * + * @author James Seibel + * @version 2022-6-9 + */ +public class CoreEnumAssembly +{ + // These variables are added in order to load each package into the JVM's class loader. + // This is done so they can be found via reflection. + private static final CoreRenderingEnumAssembly renderingAssembly = new CoreRenderingEnumAssembly(); + private static final CoreConfigEnumAssembly configAssembly = new CoreConfigEnumAssembly(); +} diff --git a/src/main/java/com/seibel/lod/core/enums/config/CoreConfigEnumAssembly.java b/src/main/java/com/seibel/lod/core/enums/config/CoreConfigEnumAssembly.java new file mode 100644 index 000000000..b3de49624 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/enums/config/CoreConfigEnumAssembly.java @@ -0,0 +1,31 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.core.enums.config; + +/** + * Assembly classes are used to reference the package they are in. + * + * @author James Seibel + * @version 2022-6-9 + */ +public class CoreConfigEnumAssembly +{ + +} diff --git a/src/main/java/com/seibel/lod/core/enums/rendering/CoreRenderingEnumAssembly.java b/src/main/java/com/seibel/lod/core/enums/rendering/CoreRenderingEnumAssembly.java new file mode 100644 index 000000000..85e9b71b6 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/enums/rendering/CoreRenderingEnumAssembly.java @@ -0,0 +1,31 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.lod.core.enums.rendering; + +/** + * Assembly classes are used to reference the package they are in. + * + * @author James Seibel + * @version 2022-6-9 + */ +public class CoreRenderingEnumAssembly +{ + +} diff --git a/src/main/java/com/seibel/lod/core/util/EnumUtil.java b/src/main/java/com/seibel/lod/core/util/EnumUtil.java index 952cd8f4d..5716c2316 100644 --- a/src/main/java/com/seibel/lod/core/util/EnumUtil.java +++ b/src/main/java/com/seibel/lod/core/util/EnumUtil.java @@ -1,3 +1,22 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + package com.seibel.lod.core.util; import java.io.InvalidObjectException; @@ -41,10 +60,10 @@ public class EnumUtil * Example output:
* "NEAR, FAR, NEAR_AND_FAR" */ - public static > String createEnumCsv(Class enumType) + public static String createEnumCsv(Class> enumType) { StringBuilder str = new StringBuilder(); - T[] enumValues = enumType.getEnumConstants(); + Enum[] enumValues = enumType.getEnumConstants(); for (int i = 0; i < enumValues.length; i++) { @@ -63,10 +82,10 @@ public class EnumUtil } /** Returns true if both enums contain the same values. */ - public static , Tb extends Enum> EnumComparisonResult compareEnumsByValues(Class alphaEnum, Class betaEnum) + public static EnumComparisonResult compareEnumClassesByValues(Class> alphaEnum, Class> betaEnum) { - Ta[] alphaValues = alphaEnum.getEnumConstants(); - Tb[] betaValues = betaEnum.getEnumConstants(); + Enum[] alphaValues = alphaEnum.getEnumConstants(); + Enum[] betaValues = betaEnum.getEnumConstants(); // compare the number of enum values if (alphaValues.length != betaValues.length) @@ -75,10 +94,10 @@ public class EnumUtil } // check that each value exists in both enums - for(Ta alphaVal : alphaValues) + for(Enum alphaVal : alphaValues) { boolean valueFoundInBothEnums = false; - for(Tb betaVal : betaValues) + for(Enum betaVal : betaValues) { if (alphaVal.name().equals(betaVal.name())) { @@ -98,7 +117,7 @@ public class EnumUtil return new EnumComparisonResult(true, ""); } /** helper method */ - public static , Tb extends Enum> String createFailMessageHeader(Class alphaEnum, Class betaEnum) + public static String createFailMessageHeader(Class> alphaEnum, Class> betaEnum) { return "The enums [" + alphaEnum.getSimpleName() + "] and [" + betaEnum.getSimpleName() + "] aren't equal: "; } diff --git a/src/test/java/ApiEnumSyncTests.java b/src/test/java/ApiEnumSyncTests.java index aebcdacf6..bb298e9c6 100644 --- a/src/test/java/ApiEnumSyncTests.java +++ b/src/test/java/ApiEnumSyncTests.java @@ -1,22 +1,43 @@ -import com.seibel.lod.core.api.external.apiObjects.enums.DhApiFogDistance; -import com.seibel.lod.core.api.external.apiObjects.enums.DhApiVerticalQuality; +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +import com.seibel.lod.core.api.external.apiObjects.enums.DhApiEnumAssembly; +import com.seibel.lod.core.api.external.apiObjects.enums.DhApiFogDrawMode; +import com.seibel.lod.core.enums.CoreEnumAssembly; import com.seibel.lod.core.enums.config.VerticalQuality; import com.seibel.lod.core.util.EnumUtil; import org.junit.Test; import org.junit.Assert; +import java.util.ArrayList; + /** * These tests were primary created to confirm that the * API enums are properly synced with their Core variants. * - * * @author James Seibel - * @version 2022-6-6 + * @version 2022-6-9 */ public class ApiEnumSyncTests { - /** This is just a quick example to confirm the testing system is set up correctly. */ + /** This is just a quick demo to confirm the testing system is set up correctly. */ @Test public void ExampleTests() { @@ -28,38 +49,79 @@ public class ApiEnumSyncTests @Test public void ConfirmEnumsAreSynced() { - //================================// - // base case tests to make sure // - // the tests are set up correctly // - //================================// + //=================// + // test validation // + //=================// - // this should always succeed (comparing the same enum to itself) - AssertEnumsValuesAreEqual(VerticalQuality.class, VerticalQuality.class, true); + // this should always succeed (comparing an enum to itself) + AssertEnumsValuesAreEqual(EnumUtil.compareEnumClassesByValues(VerticalQuality.class, VerticalQuality.class), true); // this should always fail (two completely different enums) - AssertEnumsValuesAreEqual(VerticalQuality.class, DhApiFogDistance.class, false); + AssertEnumsValuesAreEqual(EnumUtil.compareEnumClassesByValues(VerticalQuality.class, DhApiFogDrawMode.class), false); - //=========================// - // actual enum comparisons // - //=========================// - // TODO using reflection I should be able to automatically find and compare each enum in the Api to its corresponding Core object - AssertEnumsValuesAreEqual(VerticalQuality.class, DhApiVerticalQuality.class); + //================// + // Api enum Setup // + //================// + + // make sure the enum packages are loaded + new DhApiEnumAssembly(); + new CoreEnumAssembly(); + + // get the list of API enums + ArrayList>> apiEnumClassList = new ArrayList<>(); + ArrayList apiEnumPackageNames = EnumTestHelper.findPackageNamesStartingWith(DhApiEnumAssembly.class.getPackage().getName()); + for (String apiEnumPackageName : apiEnumPackageNames) + { + apiEnumClassList.addAll(EnumTestHelper.getAllEnumsFromPackage(apiEnumPackageName)); + } + + // get the list of core enums + ArrayList>> coreEnumClassList = new ArrayList<>(); + ArrayList coreEnumPackageNames = EnumTestHelper.findPackageNamesStartingWith(CoreEnumAssembly.class.getPackage().getName()); + for (String coreEnumPackageName : coreEnumPackageNames) + { + coreEnumClassList.addAll(EnumTestHelper.getAllEnumsFromPackage(coreEnumPackageName)); + } + + + //======================// + // Api enum comparisons // + //======================// + + // compare each API enum to its corresponding Core enum + for (Class> apiEnumClass : apiEnumClassList) + { + String coreEnumName = apiEnumClass.getSimpleName().substring(DhApiEnumAssembly.API_ENUM_PREFIX.length()); + boolean coreEnumFound = false; + + // find the core enum to compare against + for (Class> coreEnumClass : coreEnumClassList) + { + if (coreEnumClass.getSimpleName().equals(coreEnumName)) + { + AssertEnumsValuesAreEqual(EnumUtil.compareEnumClassesByValues(coreEnumClass, apiEnumClass), true); + coreEnumFound = true; + break; + } + } + + if (!coreEnumFound) + { + Assert.fail("API enum [" + coreEnumName + "] not found in Core."); + } + } + + } - - private , Tb extends Enum> void AssertEnumsValuesAreEqual(Class alphaEnum, Class betaEnum) + /** Helper method to make enum comparisons a little cleaner */ + private void AssertEnumsValuesAreEqual(EnumUtil.EnumComparisonResult comparisonResult, boolean assertEqual) { - AssertEnumsValuesAreEqual(alphaEnum, betaEnum, true); - } - private , Tb extends Enum> void AssertEnumsValuesAreEqual(Class alphaEnum, Class betaEnum, boolean shouldBeEqual) - { - EnumUtil.EnumComparisonResult comparisonResult = EnumUtil.compareEnumsByValues(alphaEnum, betaEnum); - - if (shouldBeEqual) + if (assertEqual) { Assert.assertTrue(comparisonResult.failMessage, comparisonResult.success); } diff --git a/src/test/java/EnumTestHelper.java b/src/test/java/EnumTestHelper.java new file mode 100644 index 000000000..59fe3fbb7 --- /dev/null +++ b/src/test/java/EnumTestHelper.java @@ -0,0 +1,116 @@ +/* + * This file is part of the Distant Horizons mod (formerly the LOD Mod), + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2022 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +import org.junit.Assert; + +import java.io.File; +import java.io.FilenameFilter; +import java.net.URL; +import java.util.ArrayList; + +/** + * A list of methods related to the Enum unit tests. + * + * @author James Seibel + * @version 6-9-2022 + */ +public class EnumTestHelper +{ + + /** + * Returns a list of every Enum in the package with the given full name. + * + * @param packageFullName includes the package path + */ + @SuppressWarnings("unchecked") + public static ArrayList>> getAllEnumsFromPackage(String packageFullName) + { + ArrayList>> enumList = new ArrayList<>(); + URL packageRoot = Thread.currentThread().getContextClassLoader().getResource(packageFullName.replace(".", "/")); + + // find all .class files in the package folder + Assert.assertNotNull("No enums found in the package [" + packageFullName + "].", packageRoot); // asserts can be used since this method should only ever be used in the context of unit tests + File[] files = new File(packageRoot.getFile()).listFiles(new FilenameFilter() + { + public boolean accept(File dir, String name) + { + return name.endsWith(".class"); + } + }); + + // get the enums from each file + Assert.assertNotNull("No files found in the package [" + packageFullName + "].", files); + for (File file : files) + { + String className = file.getName().replaceAll(".class$", ""); + + // ignore internal classes + if (!className.contains("$")) + { + String fullClassName = packageFullName + "." + className; + try + { + // attempt to parse the file's class into an enum + Class enumClass = Class.forName(fullClassName); + if (Enum.class.isAssignableFrom(enumClass)) + { + enumList.add((Class>) enumClass); + } + else + { + System.out.println("The Class [" + fullClassName + "] isn't an enum."); + } + } + catch (ClassNotFoundException e) + { + System.out.println("No enum found with the full name [" + fullClassName + "]."); + } + } + } + + return enumList; + } + + /** + * Returns every loaded package that begins with the given string. + * + * Note: this will only search packages that have been loaded + * at some point during the JVM's lifetime. + * To Make sure the package(s) you want to find are loaded you can + * initialize an object from that package to load it. + */ + public static ArrayList findPackageNamesStartingWith(String packagePrefix) + { + ArrayList nestedPackages = new ArrayList<>(); + + // search all the loaded packages + Package[] packageArray = Package.getPackages(); + for (Package pack : packageArray) + { + String packageName = pack.getName(); + if (packageName.startsWith(packagePrefix)) + { + nestedPackages.add(packageName); + } + } + + return nestedPackages; + } + +}