using System; using System.Collections.Generic; using System.Data; using System.Linq; using SabreTools.RedumpLib.Data; using Xunit; namespace MPF.Test.RedumpLib { // TODO: Add tests for string-to-enum conversion public class ExtensionsTests { #region Cross-Enumeration /// /// DiscType values that map to MediaType /// private static readonly DiscType?[] _mappableDiscTypes = new DiscType?[] { DiscType.BD25, DiscType.BD33, DiscType.BD50, DiscType.BD66, DiscType.BD100, DiscType.BD128, DiscType.CD, DiscType.DVD5, DiscType.DVD9, DiscType.GDROM, DiscType.HDDVDSL, DiscType.HDDVDDL, DiscType.NintendoGameCubeGameDisc, DiscType.NintendoWiiOpticalDiscSL, DiscType.NintendoWiiOpticalDiscDL, DiscType.NintendoWiiUOpticalDiscSL, DiscType.UMDSL, DiscType.UMDDL, }; /// /// MediaType values that map to DiscType /// private static readonly MediaType?[] _mappableMediaTypes = new MediaType?[] { MediaType.BluRay, MediaType.CDROM, MediaType.DVD, MediaType.GDROM, MediaType.HDDVD, MediaType.NintendoGameCubeGameDisc, MediaType.NintendoWiiOpticalDisc, MediaType.NintendoWiiUOpticalDisc, MediaType.UMD, }; /// /// Check that every supported system has some set of MediaTypes supported /// /// RedumpSystem value to check [Theory] [MemberData(nameof(GenerateRedumpSystemMappingTestData))] public void MediaTypesTest(RedumpSystem? redumpSystem) { var actual = redumpSystem.MediaTypes(); Assert.NotEmpty(actual); } /// /// Check that both mappable and unmappable media types output correctly /// /// MediaType value to check /// True to expect a null mapping, false otherwise [Theory] [MemberData(nameof(GenerateMediaTypeMappingTestData))] public void ToDiscTypeTest(MediaType? mediaType, bool expectNull) { DiscType? actual = mediaType.ToDiscType(); Assert.Equal(expectNull, actual == null); } /// /// Check that DiscType values all map to something appropriate /// /// DiscType value to check /// True to expect a null mapping, false otherwise [Theory] [MemberData(nameof(GenerateDiscTypeMappingTestData))] public void ToMediaTypeTest(DiscType? discType, bool expectNull) { MediaType? actual = discType.ToMediaType(); Assert.Equal(expectNull, actual == null); } /// /// Generate a test set of DiscType values /// /// MemberData-compatible list of DiscType values public static List GenerateDiscTypeMappingTestData() { var testData = new List() { new object[] { null, true } }; foreach (DiscType? discType in Enum.GetValues(typeof(DiscType))) { if (_mappableDiscTypes.Contains(discType)) testData.Add(new object[] { discType, false }); else testData.Add(new object[] { discType, true }); } return testData; } /// /// Generate a test set of RedumpSystem values /// /// MemberData-compatible list of RedumpSystem values public static List GenerateRedumpSystemMappingTestData() { var testData = new List() { new object[] { null } }; foreach (RedumpSystem? redumpSystem in Enum.GetValues(typeof(RedumpSystem))) { testData.Add(new object[] { redumpSystem }); } return testData; } /// /// Generate a test set of mappable media types /// /// MemberData-compatible list of MediaTypes public static List GenerateMediaTypeMappingTestData() { var testData = new List() { new object[] { null, true } }; foreach (MediaType? mediaType in Enum.GetValues(typeof(MediaType))) { if (_mappableMediaTypes.Contains(mediaType)) testData.Add(new object[] { mediaType, false }); else testData.Add(new object[] { mediaType, true }); } return testData; } #endregion #region Disc Category /// /// Check that every DiscCategory has a long name provided /// /// DiscCategory value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateDiscCategoryTestData))] public void DiscCategoryLongNameTest(DiscCategory? discCategory, bool expectNull) { string actual = discCategory.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of DiscCategory values /// /// MemberData-compatible list of DiscCategory values public static List GenerateDiscCategoryTestData() { var testData = new List() { new object[] { null, true } }; foreach (DiscCategory? discCategory in Enum.GetValues(typeof(DiscCategory))) { testData.Add(new object[] { discCategory, false }); } return testData; } #endregion #region Disc Type /// /// Check that every DiscType has a long name provided /// /// DiscType value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateDiscTypeTestData))] public void DiscTypeLongNameTest(DiscType? discType, bool expectNull) { string actual = discType.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of DiscType values /// /// MemberData-compatible list of DiscType values public static List GenerateDiscTypeTestData() { var testData = new List() { new object[] { null, true } }; foreach (DiscType? discType in Enum.GetValues(typeof(DiscType))) { if (discType == DiscType.NONE) testData.Add(new object[] { discType, true }); else testData.Add(new object[] { discType, false }); } return testData; } #endregion #region Language /// /// Check that every Language has a long name provided /// /// Language value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateLanguageTestData))] public void LanguageLongNameTest(Language? language, bool expectNull) { string actual = language.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Check that every Language has a short name provided /// /// Language value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateLanguageTestData))] public void LanguageShortNameTest(Language? language, bool expectNull) { string actual = language.ShortName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Ensure that every Language that has an ISO 639-1 code is unique /// [Fact] public void LanguageNoDuplicateTwoLetterCodeTest() { var fullLanguages = Enum.GetValues(typeof(Language)).Cast().ToList(); var filteredLanguages = new Dictionary(); int totalCount = 0; foreach (Language? language in fullLanguages) { string code = language.TwoLetterCode(); if (string.IsNullOrWhiteSpace(code)) continue; // Throw if the code already exists if (filteredLanguages.ContainsKey(code)) throw new DuplicateNameException($"Code {code} already in dictionary"); filteredLanguages[code] = language; totalCount++; } Assert.Equal(totalCount, filteredLanguages.Count); } /// /// Ensure that every Language that has a standard/bibliographic ISO 639-2 code is unique /// [Fact] public void LanguageNoDuplicateThreeLetterCodeTest() { var fullLanguages = Enum.GetValues(typeof(Language)).Cast().ToList(); var filteredLanguages = new Dictionary(); int totalCount = 0; foreach (Language? language in fullLanguages) { string code = language.ThreeLetterCode(); if (string.IsNullOrWhiteSpace(code)) continue; // Throw if the code already exists if (filteredLanguages.ContainsKey(code)) throw new DuplicateNameException($"Code {code} already in dictionary"); filteredLanguages[code] = language; totalCount++; } Assert.Equal(totalCount, filteredLanguages.Count); } /// /// Ensure that every Language that has a terminology ISO 639-2 code is unique /// [Fact] public void LanguageNoDuplicateThreeLetterCodeAltTest() { var fullLanguages = Enum.GetValues(typeof(Language)).Cast().ToList(); var filteredLanguages = new Dictionary(); int totalCount = 0; foreach (Language? language in fullLanguages) { string code = language.ThreeLetterCodeAlt(); if (string.IsNullOrWhiteSpace(code)) continue; // Throw if the code already exists if (filteredLanguages.ContainsKey(code)) throw new DuplicateNameException($"Code {code} already in dictionary"); filteredLanguages[code] = language; totalCount++; } Assert.Equal(totalCount, filteredLanguages.Count); } /// /// Generate a test set of Language values /// /// MemberData-compatible list of Language values public static List GenerateLanguageTestData() { var testData = new List() { new object[] { null, true } }; foreach (Language? language in Enum.GetValues(typeof(Language))) { testData.Add(new object[] { language, false }); } return testData; } #endregion #region Language Selection /// /// Check that every LanguageSelection has a long name provided /// /// LanguageSelection value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateLanguageSelectionTestData))] public void LanguageSelectionLongNameTest(LanguageSelection? languageSelection, bool expectNull) { string actual = languageSelection.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of LanguageSelection values /// /// MemberData-compatible list of LanguageSelection values public static List GenerateLanguageSelectionTestData() { var testData = new List() { new object[] { null, true } }; foreach (LanguageSelection? languageSelection in Enum.GetValues(typeof(LanguageSelection))) { testData.Add(new object[] { languageSelection, false }); } return testData; } #endregion #region Media Type /// /// Check that every MediaType has a long name provided /// /// MediaType value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateMediaTypeTestData))] public void MediaTypeLongNameTest(MediaType? mediaType, bool expectNull) { string actual = mediaType.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Check that every MediaType has a short name provided /// /// MediaType value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateMediaTypeTestData))] public void MediaTypeShortNameTest(MediaType? mediaType, bool expectNull) { string actual = mediaType.ShortName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of MediaType values /// /// MemberData-compatible list of MediaType values public static List GenerateMediaTypeTestData() { var testData = new List() { new object[] { null, true } }; foreach (MediaType? mediaType in Enum.GetValues(typeof(MediaType))) { testData.Add(new object[] { mediaType, false }); } return testData; } #endregion #region Region /// /// Check that every Region has a long name provided /// /// Region value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateRegionTestData))] public void RegionLongNameTest(Region? region, bool expectNull) { string actual = region.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Check that every Region has a short name provided /// /// Region value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateRegionTestData))] public void RegionShortNameTest(Region? region, bool expectNull) { string actual = region.ShortName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Ensure that every Language that has an ISO 639-1 code is unique /// [Fact] public void RegionNoDuplicateShortNameTest() { var fullRegions = Enum.GetValues(typeof(Region)).Cast().ToList(); var filteredRegions = new Dictionary(); int totalCount = 0; foreach (Region? region in fullRegions) { string code = region.ShortName(); if (string.IsNullOrWhiteSpace(code)) continue; // Throw if the code already exists if (filteredRegions.ContainsKey(code)) throw new DuplicateNameException($"Code {code} already in dictionary"); filteredRegions[code] = region; totalCount++; } Assert.Equal(totalCount, filteredRegions.Count); } /// /// Generate a test set of Region values /// /// MemberData-compatible list of Region values public static List GenerateRegionTestData() { var testData = new List() { new object[] { null, true } }; foreach (Region? region in Enum.GetValues(typeof(Region))) { testData.Add(new object[] { region, false }); } return testData; } #endregion #region Site Code /// /// Check that every SiteCode has a long name provided /// /// SiteCode value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateSiteCodeTestData))] public void SiteCodeLongNameTest(SiteCode? siteCode, bool expectNull) { string actual = siteCode.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Check that every SiteCode has a short name provided /// /// SiteCode value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateSiteCodeTestData))] public void SiteCodeShortNameTest(SiteCode? siteCode, bool expectNull) { string actual = siteCode.ShortName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of SiteCode values /// /// MemberData-compatible list of SiteCode values public static List GenerateSiteCodeTestData() { var testData = new List() { new object[] { null, true } }; foreach (SiteCode? siteCode in Enum.GetValues(typeof(SiteCode))) { testData.Add(new object[] { siteCode, false }); } return testData; } #endregion #region System /// /// Check that every RedumpSystem has a long name provided /// /// RedumpSystem value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateRedumpSystemTestData))] public void RedumpSystemLongNameTest(RedumpSystem? redumpSystem, bool expectNull) { string actual = redumpSystem.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } // TODO: Re-enable the following test once non-Redump systems are accounted for /// /// Check that every RedumpSystem has a short name provided /// /// RedumpSystem value to check /// True to expect a null value, false otherwise //[Theory] //[MemberData(nameof(GenerateRedumpSystemTestData))] //public void RedumpSystemShortNameTest(RedumpSystem? redumpSystem, bool expectNull) //{ // string actual = redumpSystem.ShortName(); // if (expectNull) // Assert.Null(actual); // else // Assert.NotNull(actual); //} // TODO: Test the other attributes as well // Most are bool checks so they're not as interesting to have unit tests around // SystemCategory always returns something as well, so is it worth testing? /// /// Generate a test set of RedumpSystem values /// /// MemberData-compatible list of RedumpSystem values public static List GenerateRedumpSystemTestData() { var testData = new List() { new object[] { null, true } }; foreach (RedumpSystem? redumpSystem in Enum.GetValues(typeof(RedumpSystem))) { // We want to skip all markers for this if (redumpSystem.IsMarker()) continue; testData.Add(new object[] { redumpSystem, false }); } return testData; } #endregion #region System Category /// /// Check that every SystemCategory has a long name provided /// /// SystemCategory value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateSystemCategoryTestData))] public void SystemCategoryLongNameTest(SystemCategory? systemCategory, bool expectNull) { string actual = systemCategory.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of SystemCategory values /// /// MemberData-compatible list of SystemCategory values public static List GenerateSystemCategoryTestData() { var testData = new List() { new object[] { null, true } }; foreach (SystemCategory? systemCategory in Enum.GetValues(typeof(SystemCategory))) { if (systemCategory == SystemCategory.NONE) testData.Add(new object[] { systemCategory, true }); else testData.Add(new object[] { systemCategory, false }); } return testData; } #endregion #region Yes/No /// /// Check that every YesNo has a long name provided /// /// YesNo value to check /// True to expect a null value, false otherwise [Theory] [MemberData(nameof(GenerateYesNoTestData))] public void YesNoLongNameTest(YesNo? yesNo, bool expectNull) { string actual = yesNo.LongName(); if (expectNull) Assert.Null(actual); else Assert.NotNull(actual); } /// /// Generate a test set of YesNo values /// /// MemberData-compatible list of YesNo values public static List GenerateYesNoTestData() { var testData = new List() { new object[] { null, false } }; foreach (YesNo? yesNo in Enum.GetValues(typeof(YesNo))) { testData.Add(new object[] { yesNo, false }); } return testData; } #endregion } }