Skip to content

Commit 2666c7f

Browse files
committed
add validation rule and tests
1 parent 3c4861d commit 2666c7f

File tree

3 files changed

+118
-7
lines changed

3 files changed

+118
-7
lines changed

src/LEGO.AsyncAPI/Validation/Rules/AsyncApiDocumentRules.cs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace LEGO.AsyncAPI.Validation.Rules
44
{
5+
using System;
56
using System.Linq;
67
using System.Text.RegularExpressions;
78
using LEGO.AsyncAPI.Models;
@@ -10,10 +11,12 @@ namespace LEGO.AsyncAPI.Validation.Rules
1011
[AsyncApiRule]
1112
public static class AsyncApiDocumentRules
1213
{
14+
private static TimeSpan RegexTimeout = TimeSpan.FromSeconds(1);
1315
/// <summary>
1416
/// The key regex.
1517
/// </summary>
16-
public static Regex KeyRegex = new Regex(@"^[a-zA-Z0-9\.\-_]+$");
18+
public static Regex KeyRegex = new Regex(@"^[a-zA-Z0-9\.\-_]+$", RegexOptions.None, RegexTimeout);
19+
public static Regex ChannelKeyUriTemplateRegex = new Regex(@"^(?:(?:[^\x00-\x20""'<>%\\^`{|}]|%[0-9a-f]{2})|\{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|\*)?)*\})*$", RegexOptions.IgnoreCase, RegexTimeout);
1720

1821
public static ValidationRule<AsyncApiDocument> DocumentRequiredFields =>
1922
new ValidationRule<AsyncApiDocument>(
@@ -30,14 +33,30 @@ public static class AsyncApiDocumentRules
3033
context.Exit();
3134

3235
context.Enter("channels");
33-
if (document.Channels == null || !document.Channels.Keys.Any())
36+
try
3437
{
35-
context.CreateError(
36-
nameof(DocumentRequiredFields),
37-
string.Format(Resource.Validation_FieldRequired, "channels", "document"));
38-
}
38+
if (document.Channels == null || !document.Channels.Keys.Any())
39+
{
40+
context.CreateError(
41+
nameof(DocumentRequiredFields),
42+
string.Format(Resource.Validation_FieldRequired, "channels", "document"));
43+
return;
44+
}
3945

40-
context.Exit();
46+
foreach (var key in document.Channels.Keys)
47+
{
48+
if (!ChannelKeyUriTemplateRegex.IsMatch(key))
49+
{
50+
context.CreateError(
51+
"ChannelKeys",
52+
string.Format(Resource.Validation_KeyMustMatchRegularExpr, key, "channels", KeyRegex.ToString()));
53+
}
54+
}
55+
}
56+
finally
57+
{
58+
context.Exit();
59+
}
4160
});
4261

4362
public static ValidationRule<AsyncApiDocument> KeyMustBeRegularExpression =>
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) The LEGO Group. All rights reserved.
2+
3+
namespace LEGO.AsyncAPI.Tests.Validation
4+
{
5+
using FluentAssertions;
6+
using LEGO.AsyncAPI.Readers;
7+
using LEGO.AsyncAPI.Validations;
8+
using NUnit.Framework;
9+
using System.Linq;
10+
11+
public class ValidationRuleTests
12+
{
13+
[Test]
14+
[TestCase("chat-{person-id}")]
15+
public void ChannelKey_WithInvalidParameter_DiagnosticsError(string channelKey)
16+
{
17+
var input =
18+
$"""
19+
asyncapi: 2.6.0
20+
info:
21+
title: Chat Application
22+
version: 1.0.0
23+
servers:
24+
testing:
25+
url: test.mosquitto.org:1883
26+
protocol: mqtt
27+
description: Test broker
28+
channels:
29+
{channelKey}:
30+
publish:
31+
operationId: onMessageReceieved
32+
message:
33+
name: text
34+
payload:
35+
type: string
36+
subscribe:
37+
operationId: sendMessage
38+
message:
39+
name: text
40+
payload:
41+
type: string
42+
""";
43+
44+
var document = new AsyncApiStringReader().Read(input, out var diagnostic);
45+
diagnostic.Errors.First().Message.Should().Be($"The key '{channelKey}' in 'channels' MUST match the regular expression '^[a-zA-Z0-9\\.\\-_]+$'.");
46+
diagnostic.Errors.First().Pointer.Should().Be("#/channels");
47+
}
48+
49+
[Test]
50+
[TestCase("chat")]
51+
[TestCase("chat-{personId}")]
52+
[TestCase("chat-{person_id}")]
53+
[TestCase("chat-{person%2Did}")]
54+
[TestCase("chat-{personId2}")]
55+
public void ChannelKey_WithValidKey_Success(string channelKey)
56+
{
57+
var input =
58+
$"""
59+
asyncapi: 2.6.0
60+
info:
61+
title: Chat Application
62+
version: 1.0.0
63+
servers:
64+
testing:
65+
url: test.mosquitto.org:1883
66+
protocol: mqtt
67+
description: Test broker
68+
channels:
69+
{channelKey}:
70+
publish:
71+
operationId: onMessageReceieved
72+
message:
73+
name: text
74+
payload:
75+
type: string
76+
subscribe:
77+
operationId: sendMessage
78+
message:
79+
name: text
80+
payload:
81+
type: string
82+
""";
83+
84+
var document = new AsyncApiStringReader().Read(input, out var diagnostic);
85+
diagnostic.Errors.Should().BeEmpty();
86+
}
87+
}
88+
89+
}

test/LEGO.AsyncAPI.Tests/Validation/ValidationRulesetTests.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace LEGO.AsyncAPI.Tests.Validation
44
{
5+
using FluentAssertions;
6+
using LEGO.AsyncAPI.Readers;
57
using LEGO.AsyncAPI.Validations;
68
using NUnit.Framework;
9+
using System.Linq;
710

811
public class ValidationRuleSetTests
912
{

0 commit comments

Comments
 (0)