using Nonemm.Core; using Nonemm.Core.Country; namespace Nonemm.Core.Tests.Country; public class CountryFileTests { private const string Sample = """ Sicily: 15: 28: EU: 37.50: -14.00: -1.0: *IT9: IT9,IW9,ID9; Italy: 15: 28: EU: 42.83: -12.83: -1.0: I: I,IK,IZ,=IG9ABC; United States: 05: 08: NA: 37.60: 91.87: 5.0: K: K,W,N,K6(3)[6],=W1AW; Fiji: 32: 56: OC: -17.78: -177.92: -12.0: 3D2: 3D2; """; private static readonly CountryFile File = CountryFile.Parse(Sample); /// The publisher writes the issue date in as a callsign of its own. The /// stations of a multi-operator entry compare it: two issues score the same /// contact differently. [Fact] public void TheIssueDateIsRead() => Assert.Equal( "20260826", CountryFile.Parse(Sample.Replace("3D2;", "3D2,=VER20260826;")).Version); [Fact] public void AFileWithNoIssueDateHasNoVersion() => Assert.Equal("", File.Version); [Fact] public void LongestPrefixWins() => Assert.Equal("IT9", File.Find("IT9ABC")?.Entity.PrimaryPrefix); [Fact] public void ShorterPrefixStillMatches() => Assert.Equal("I", File.Find("IK2XYZ")?.Entity.PrimaryPrefix); [Fact] public void WaeOnlyEntitiesAreMarked() => Assert.True(File.Find("IT9ABC")?.Entity.IsWaeOnly); [Fact] public void WholeCallEntryBeatsThePrefix() => Assert.Equal("I", File.Find("IG9ABC")?.Entity.PrimaryPrefix); [Fact] public void PrefixOverrideChangesTheZone() { CountryLookup? found = File.Find("K6XYZ"); Assert.Equal(3, found?.CqZone); Assert.Equal(6, found?.ItuZone); } [Fact] public void PrefixWithoutOverrideKeepsTheEntityZone() => Assert.Equal(5, File.Find("W1XYZ")?.CqZone); [Fact] public void PortableStationIsLookedUpByItsPortablePrefix() => Assert.Equal("3D2", File.Find("3D2/K1ABC")?.Entity.PrimaryPrefix); [Fact] public void MaritimeMobileBelongsToNoEntity() => Assert.Null(File.Find("K1ABC/MM")); [Fact] public void LongitudeComesBackEastPositive() => Assert.Equal(-91.87, File.Find("W1XYZ")!.Longitude, 2); [Fact] public void UnknownCallHasNoEntity() => Assert.Null(File.Find("XX9ZZZ")); [Theory] [InlineData("")] [InlineData("404 not found")] public void TextThatIsNotACountryFileIsRejected(string text) => Assert.Throws(() => CountryFile.Parse(text)); private const string Russia = """ Asiatic Russia: 17: 30: AS: 55.88: -84.08: -7.0: UA9: # UA9: UA9H(18)[31],UA9J[20], UA9Y(18)[31]; # UA0: UA0F(19)[34],UA0Z(19)[35]; R9,RA9,RM9,RZ9,RC0,UA9,UA0; """; /// The file lists zones by call area and the first letter after the digit /// under UA, and N1MM applies them to every call of the entity. [Theory] [InlineData("UA9YA", 18, 31)] [InlineData("RA9Y", 18, 31)] [InlineData("RZ9YI", 18, 31)] [InlineData("RM9J", 17, 20)] [InlineData("RC0F", 19, 34)] [InlineData("RA9A", 17, 30)] public void TheZoneComesFromTheCallAreaListInTheFile(string call, int cq, int itu) { CountryLookup? found = CountryFile.Parse(Russia).Find(call); Assert.Equal(cq, found?.CqZone); Assert.Equal(itu, found?.ItuZone); } [Fact] public void ACallWhoseOwnPrefixGivesAZoneIsNotChangedByTheList() { CountryFile file = CountryFile.Parse(Russia.Replace("RC0", "RC0(23)[40]")); Assert.Equal(23, file.Find("RC0F")?.CqZone); } }