SchemaTests.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System.Globalization;
  2. using System.Text.Json;
  3. using Json.Schema;
  4. using YamlDotNet.RepresentationModel;
  5. namespace Tests.Yaml;
  6. public class SchemaConformanceTests {
  7. private static JsonSchema LoadSchema(int version) {
  8. var schemaText = File.ReadAllText($"schemas/schema.v{version}.json");
  9. return JsonSchema.FromText(schemaText);
  10. }
  11. private static JsonElement ConvertYamlToJsonElement(string yaml) {
  12. // Load YAML into YAML DOM
  13. var yamlStream = new YamlStream();
  14. yamlStream.Load(new StringReader(yaml));
  15. YamlNode root = yamlStream.Documents[0].RootNode;
  16. // Convert YAML node → JSON string
  17. var json = ConvertYamlNodeToJson(root);
  18. using var document = JsonDocument.Parse(json);
  19. return document.RootElement.Clone();
  20. }
  21. private static string ConvertYamlNodeToJson(YamlNode node) {
  22. if (node is YamlScalarNode scalar) {
  23. // Try numeric
  24. if (int.TryParse(scalar.Value, out var i))
  25. return i.ToString();
  26. if (double.TryParse(scalar.Value, out var d))
  27. return d.ToString(CultureInfo.InvariantCulture);
  28. if (bool.TryParse(scalar.Value, out var b))
  29. return b.ToString().ToLowerInvariant();
  30. // Otherwise string
  31. return JsonSerializer.Serialize(scalar.Value);
  32. }
  33. if (node is YamlSequenceNode sequence) {
  34. IEnumerable<string> items = sequence.Children
  35. .Select(ConvertYamlNodeToJson);
  36. return "[" + string.Join(",", items) + "]";
  37. }
  38. if (node is YamlMappingNode mapping) {
  39. IEnumerable<string> props = mapping.Children
  40. .Select(kvp =>
  41. JsonSerializer.Serialize(((YamlScalarNode)kvp.Key).Value)
  42. + ":"
  43. + ConvertYamlNodeToJson(kvp.Value));
  44. return "{" + string.Join(",", props) + "}";
  45. }
  46. return "null";
  47. }
  48. [Theory]
  49. [InlineData(1)]
  50. [InlineData(2)]
  51. [InlineData(3)]
  52. [InlineData(4)]
  53. public void All_yaml_files_conform_to_schema(int version) {
  54. // Arrange
  55. JsonSchema schema = LoadSchema(version);
  56. var yamlFolder = Path.Combine(
  57. AppContext.BaseDirectory,
  58. "TestConfigs",
  59. $"v{version}");
  60. var yamlFiles = Directory
  61. .EnumerateFiles(yamlFolder, "*.yaml", SearchOption.AllDirectories)
  62. .ToList();
  63. Assert.NotEmpty(yamlFiles);
  64. var failures = new List<string>();
  65. // Act
  66. foreach (var file in yamlFiles) {
  67. var yaml = File.ReadAllText(file);
  68. JsonElement jsonNode = ConvertYamlToJsonElement(yaml);
  69. var options = new EvaluationOptions {
  70. OutputFormat = OutputFormat.Hierarchical
  71. };
  72. EvaluationResults result = schema.Evaluate(jsonNode, options);
  73. if (!result.IsValid) {
  74. var errors = new List<string>();
  75. void CollectErrors(EvaluationResults node) {
  76. if (node.Errors != null)
  77. foreach (KeyValuePair<string, string> error in node.Errors)
  78. errors.Add($"{error.Key}: {error.Value}");
  79. if (node.Details != null)
  80. foreach (EvaluationResults child in node.Details)
  81. CollectErrors(child);
  82. }
  83. CollectErrors(result);
  84. failures.Add(
  85. $"File: {file}{Environment.NewLine}" +
  86. string.Join(Environment.NewLine, errors));
  87. }
  88. }
  89. // Assert
  90. if (failures.Any()) {
  91. var message = string.Join(
  92. $"{Environment.NewLine}--------------------{Environment.NewLine}",
  93. failures);
  94. Assert.Fail(message);
  95. }
  96. }
  97. }