-
-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensure that schedule is a valid Cron expression
I've added the framework to perform additional validation on a field, and implemented a Cron expression validator for the scraping schedule. Each field can have a collection of zero or more validators that implement `IFieldValidator`, and the validator uses the error reporter to report any validation errors. Fixes #1103
- Loading branch information
1 parent
5d6291e
commit 1f87405
Showing
12 changed files
with
209 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
...itor.Core.Scraping/Configuration/Serialization/FieldValidators/CronExpressionValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System.Collections.Generic; | ||
using Cronos; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Core.Scraping.Configuration.Serialization.FieldValidators | ||
{ | ||
/// <summary> | ||
/// Ensures that a field is a valid Cron expression. | ||
/// </summary> | ||
public class CronExpressionValidator : IFieldValidator | ||
{ | ||
/// <inheritdoc /> | ||
public void Validate(string value, KeyValuePair<YamlNode, YamlNode> fieldNodes, IErrorReporter errorReporter) | ||
{ | ||
if (!string.IsNullOrEmpty(value)) | ||
{ | ||
if (!IsValidStandardExpression(value) && !IsValidExpressionWithSeconds(value)) | ||
{ | ||
errorReporter.ReportError(fieldNodes.Value, $"'{value}' is not a valid value for '{fieldNodes.Key}'. The value must be a valid Cron expression."); | ||
} | ||
} | ||
} | ||
|
||
private static bool IsValidStandardExpression(string value) | ||
{ | ||
try | ||
{ | ||
CronExpression.Parse(value); | ||
return true; | ||
} | ||
catch (CronFormatException) | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
private static bool IsValidExpressionWithSeconds(string value) | ||
{ | ||
try | ||
{ | ||
CronExpression.Parse(value, CronFormat.IncludeSeconds); | ||
return true; | ||
} | ||
catch (CronFormatException) | ||
{ | ||
return false; | ||
} | ||
} | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/Promitor.Core.Scraping/Configuration/Serialization/FieldValidators/IFieldValidator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System.Collections.Generic; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Core.Scraping.Configuration.Serialization.FieldValidators | ||
{ | ||
/// <summary> | ||
/// Provides validation for a yaml field. | ||
/// </summary> | ||
public interface IFieldValidator | ||
{ | ||
/// <summary> | ||
/// Validates a field, reporting any errors via the error reporter. | ||
/// </summary> | ||
/// <param name="value">The value of the field.</param> | ||
/// <param name="fieldNodes">A KeyValuePair where the Key is the field name, and the Value is its value.</param> | ||
/// <param name="errorReporter">The error reporter.</param> | ||
void Validate(string value, KeyValuePair<YamlNode, YamlNode> fieldNodes, IErrorReporter errorReporter); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/Promitor.Tests.Unit/Serialization/FieldValidators/CronExpressionValidatorTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using System.Linq; | ||
using Moq; | ||
using Promitor.Core.Scraping.Configuration.Serialization; | ||
using Promitor.Core.Scraping.Configuration.Serialization.FieldValidators; | ||
using Xunit; | ||
using YamlDotNet.RepresentationModel; | ||
|
||
namespace Promitor.Tests.Unit.Serialization.FieldValidators | ||
{ | ||
public class CronExpressionValidatorTests | ||
{ | ||
private readonly CronExpressionValidator _validator = new CronExpressionValidator(); | ||
|
||
[Fact] | ||
public void Validate_InvalidExpression_ReportsError() | ||
{ | ||
AssertExpressionIsNotValid("invalid-expression"); | ||
} | ||
|
||
[Fact] | ||
public void Validate_ValidExpression_DoesNotReportError() | ||
{ | ||
AssertExpressionIsValid("*/5 * * * *"); | ||
} | ||
|
||
[Fact] | ||
public void Validate_ValidExpressionWithSeconds_DoesNotReportError() | ||
{ | ||
AssertExpressionIsValid("* */5 * * * *"); | ||
} | ||
|
||
[Fact] | ||
public void Validate_EmptyString_DoesNotReportError() | ||
{ | ||
AssertExpressionIsValid(string.Empty); | ||
} | ||
|
||
private void AssertExpressionIsNotValid(string cronExpression) | ||
{ | ||
// Arrange | ||
var fieldNodes = YamlUtils | ||
.CreateYamlNode($"schedule: '{cronExpression}'") | ||
.Children | ||
.First(); | ||
var errorReporter = new Mock<IErrorReporter>(); | ||
|
||
// Act | ||
_validator.Validate(fieldNodes.Value.ToString(), fieldNodes, errorReporter.Object); | ||
|
||
// Assert | ||
errorReporter.Verify( | ||
e => e.ReportError(fieldNodes.Value, $"'{cronExpression}' is not a valid value for 'schedule'. The value must be a valid Cron expression.")); | ||
} | ||
|
||
private void AssertExpressionIsValid(string cronExpression) | ||
{ | ||
// Arrange | ||
var fieldNodes = YamlUtils | ||
.CreateYamlNode($"schedule: '{cronExpression}'") | ||
.Children | ||
.First(); | ||
var errorReporter = new Mock<IErrorReporter>(); | ||
|
||
// Act | ||
_validator.Validate(fieldNodes.Value.ToString(), fieldNodes, errorReporter.Object); | ||
|
||
// Assert | ||
errorReporter.Verify( | ||
e => e.ReportError(It.IsAny<YamlNode>(), It.IsAny<string>()), Times.Never); | ||
} | ||
} | ||
} |