using System.Collections.Generic; using System.Linq; using FluentAssertions; using Xunit; namespace PKHeX.Core.Tests.Util; public class StringQualityTests { [Theory] [InlineData("ja")] [InlineData("en")] [InlineData("it")] [InlineData("de")] [InlineData("fr")] [InlineData("es")] [InlineData("ko")] [InlineData("zh")] [InlineData("zh2")] public void HasNoDuplicates(string language) { CheckMetLocations(language); CheckItemNames(language); CheckMoveNames(language); CheckSpeciesNames(language); } /// /// Checks for duplicate hashes in the species list. /// /// /// Uses hashes instead of strings as other logic uses dictionaries of hashes. /// private static void CheckSpeciesNames(string language) { var strings = GameInfo.GetStrings(language); var arr = strings.specieslist; var hashset = new HashSet(arr.Length); var duplicates = new List(0); foreach (var line in arr) { var hash = line.GetHashCode(); if (!hashset.Add(hash)) duplicates.Add(line); } duplicates.Count.Should().Be(0, "expected no duplicate strings."); } private static void CheckMoveNames(string language) { var strings = GameInfo.GetStrings(language); var arr = strings.movelist; var duplicates = GetDuplicates(arr); duplicates.Count.Should().Be(0, "expected no duplicate strings."); } private static void CheckItemNames(string language) { var strings = GameInfo.GetStrings(language); var arr = strings.itemlist; var duplicates = GetDuplicates(arr); var questionmarks = arr[129]; duplicates.RemoveAll(z => z == questionmarks); duplicates.Count.Should().Be(0, "expected no duplicate strings."); } private static List GetDuplicates(string[] arr) { var hs = new HashSet(); var duplicates = new List(); foreach (var line in arr) { if (line.Length == 0) continue; if (hs.Contains(line)) duplicates.Add(line); hs.Add(line); } return duplicates; } private static void CheckMetLocations(string language) { var strings = GameInfo.GetStrings(language); var sets = typeof(GameStrings).GetFields() .Where(z => typeof(ILocationSet).IsAssignableFrom(z.FieldType)); bool iterated = false; var duplicates = new List(0); foreach (var setField in sets) { iterated = true; var name = setField.Name; var group = setField.GetValue(strings) as ILocationSet; Assert.NotNull(group); foreach (var (bank, arr) in group.GetAll()) { var hs = new HashSet(arr.Length); bool sm0 = bank == 0 && name == nameof(GameStrings.Gen7); for (int index = 0; index < arr.Length; index++) { var line = arr[index]; if (line.Length == 0) continue; if (sm0 && index % 2 != 0) continue; if (hs.Contains(line)) duplicates.Add($"{name}\t{index}\t{line}"); hs.Add(line); } } if (duplicates.Count != 0) Assert.Fail($"Found duplicates for {name}. Debug this test to inspect the list of duplicate location IDs."); } iterated.Should().BeTrue(); } }