using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; // ReSharper disable CollectionNeverUpdated.Global // ReSharper disable ClassNeverInstantiated.Global namespace IRCSharp.Tests.Tokenization; public class Parser { [Test] [YamlDataGenerator("Tokenization/Data/msg-split.yaml")] [ArgumentDisplayFormatter] public async Task Split(TestCase test) { var atoms = test.Atoms; var line = new Line(test.Input); await Assert.That(line.Command).IsEqualTo(atoms.Verb.ToUpperInvariant()) .Because($"command failed on: '{test.Input}'"); await Assert.That(line.Source).IsEqualTo(atoms.Source) .Because($"source failed on: '{test.Input}'"); await Assert.That(line.Params).IsEquivalentTo(atoms.Params ?? []) .Because($"params failed on: '{test.Input}'"); if (atoms.Tags is null) { await Assert.That(line.Tags).IsNull() .Because("tags should be null"); } else { await Assert.That(line.Tags).IsEquivalentTo(atoms.Tags) .Because($"tags failed on: '{test.Input}'"); } } [Test] [YamlDataGenerator("Tokenization/Data/msg-join.yaml")] [ArgumentDisplayFormatter] public async Task Join(TestCase test) { var atoms = test.Atoms; var line = new Line { Command = atoms.Verb, Params = atoms.Params, Source = atoms.Source, Tags = atoms.Tags }; await Assert.That(test.Matches).Contains(line.Format()).Because(test.Description); } } public class YamlDataGeneratorAttribute(string yamlPath) : AsyncDataSourceGeneratorAttribute where T : class { private readonly IDeserializer _deserializer = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); protected override async IAsyncEnumerable>> GenerateDataSourcesAsync( DataGeneratorMetadata dataGeneratorMetadata) { foreach (var item in _deserializer.Deserialize>(await File.ReadAllTextAsync(yamlPath))) yield return () => Task.FromResult(item); } } public class TestCase : ArgumentDisplayFormatter { [YamlMember(Alias = "desc")] public string Description { get; set; } public Atoms Atoms { get; set; } public List Matches { get; set; } public string Input { get; set; } public override bool CanHandle(object value) => value is TestCase; public override string FormatValue(object value) { var testCase = (TestCase)value!; return testCase.Input ?? testCase.Description; } } public class Atoms { public Dictionary Tags { get; set; } public string Source { get; set; } public string Verb { get; set; } public List Params { get; set; } }