SchemaTests.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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. public void All_yaml_files_conform_to_schema(int version) {
  53. // Arrange
  54. JsonSchema schema = LoadSchema(version);
  55. var yamlFolder = Path.Combine(
  56. AppContext.BaseDirectory,
  57. "TestConfigs",
  58. $"v{version}");
  59. var yamlFiles = Directory
  60. .EnumerateFiles(yamlFolder, "*.yaml", SearchOption.AllDirectories)
  61. .ToList();
  62. Assert.NotEmpty(yamlFiles);
  63. var failures = new List<string>();
  64. // Act
  65. foreach (var file in yamlFiles) {
  66. var yaml = File.ReadAllText(file);
  67. JsonElement jsonNode = ConvertYamlToJsonElement(yaml);
  68. var options = new EvaluationOptions {
  69. OutputFormat = OutputFormat.Hierarchical
  70. };
  71. EvaluationResults result = schema.Evaluate(jsonNode, options);
  72. if (!result.IsValid) {
  73. var errors = new List<string>();
  74. void CollectErrors(EvaluationResults node) {
  75. if (node.Errors != null)
  76. foreach (KeyValuePair<string, string> error in node.Errors)
  77. errors.Add($"{error.Key}: {error.Value}");
  78. if (node.Details != null)
  79. foreach (EvaluationResults child in node.Details)
  80. CollectErrors(child);
  81. }
  82. CollectErrors(result);
  83. failures.Add(
  84. $"File: {file}{Environment.NewLine}" +
  85. string.Join(Environment.NewLine, errors));
  86. }
  87. }
  88. // Assert
  89. if (failures.Any()) {
  90. var message = string.Join(
  91. $"{Environment.NewLine}--------------------{Environment.NewLine}",
  92. failures);
  93. Assert.Fail(message);
  94. }
  95. }
  96. }