增加异常定义。完成初步测试
This commit is contained in:
parent
f3096745e3
commit
d93af99a15
|
@ -1,4 +1,5 @@
|
|||
using Falcon.SugarApi.TimedBackgroundTask;
|
||||
using Microsoft.AspNetCore.Mvc.TagHelpers;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
|
||||
|
@ -84,5 +85,139 @@ namespace Falcon.SugarApi.Test
|
|||
}
|
||||
|
||||
private string? DateToString(DateTime? date) => date?.ToString("yyyyMMddHHmmss");
|
||||
|
||||
|
||||
//-----------------------------
|
||||
// 基础语法解析测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestBasicWildcard() {
|
||||
var cron = new CronExpression("* * * * * * *");
|
||||
Assert.AreEqual(60,cron.Seconds.Count,"秒字段应包含0-59");
|
||||
Assert.AreEqual(12,cron.Months.Count,"月字段应包含1-12");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestFixedValue() {
|
||||
var cron = new CronExpression("5 10 3 15 6 2 2026");
|
||||
Assert.IsTrue(cron.Seconds.Contains(5));
|
||||
Assert.IsTrue(cron.Minutes.Contains(10));
|
||||
Assert.IsTrue(cron.Hours.Contains(3));
|
||||
Assert.IsTrue(cron.DaysOfMonth.Contains(15));
|
||||
Assert.IsTrue(cron.Months.Contains(6));
|
||||
Assert.IsTrue(cron.DaysOfWeek.Contains(2));
|
||||
Assert.IsTrue(cron.Years.Contains(2026));
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 复杂语法测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestRangeAndStep() {
|
||||
//var cron = new CronExpression("0-30/15 10,20,30 * 1-5 */3 * *");
|
||||
//CollectionAssert.AreEqual(new[] { 0,15,30 },cron.Seconds);
|
||||
//CollectionAssert.AreEqual(new[] { 10,20,30 },cron.Minutes);
|
||||
//CollectionAssert.AreEqual(new[] { 1,2,3,4,5 },cron.DaysOfMonth);
|
||||
//CollectionAssert.AreEqual(new[] { 1,4,7,10 },cron.Months);
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 字段省略测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestPartialExpression() {
|
||||
var cron = new CronExpression("30 15 4");
|
||||
Assert.AreEqual(1,cron.Seconds.Count);
|
||||
Assert.AreEqual(1,cron.Minutes.Count);
|
||||
Assert.AreEqual(1,cron.Hours.Count);
|
||||
Assert.AreEqual(31,cron.DaysOfMonth.Count); // 默认1-31
|
||||
Assert.AreEqual(12,cron.Months.Count); // 默认1-12
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 边界值测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestBoundaryValues() {
|
||||
// 最大最小值测试
|
||||
var cron = new CronExpression("59 59 23 31 12 6 2026");
|
||||
Assert.IsTrue(cron.Seconds.Contains(59));
|
||||
Assert.IsTrue(cron.DaysOfMonth.Contains(31));
|
||||
Assert.IsTrue(cron.Months.Contains(12));
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 错误处理测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestInvalidCharacter() {
|
||||
try {
|
||||
var _ = new CronExpression("5a * * * * *");
|
||||
}
|
||||
catch(CronAdjustNullException) { }
|
||||
catch(CronException) { }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestOutOfRangeValue() {
|
||||
try {
|
||||
var _ = new CronExpression("70 * * * * *");
|
||||
}
|
||||
catch(CronAdjustNullException) { }
|
||||
catch(CronException) { }
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 下次执行时间计算测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestNextOccurrence_Basic() {
|
||||
var baseTime = new DateTime(2025,10,1,12,30,15);
|
||||
var cron = new CronExpression("30 * * * * * *");
|
||||
|
||||
// 下一个30秒
|
||||
var expected = new DateTime(2025,10,1,12,30,30);
|
||||
var actual = cron.GetNextOccurrence(baseTime);
|
||||
Assert.AreEqual(expected,actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void TestNextOccurrence_MonthRollover() {
|
||||
var baseTime = new DateTime(2024,12,31,23,59,59);
|
||||
var cron = new CronExpression("* * * 1 * * *"); // 每月1号
|
||||
|
||||
var expected = new DateTime(2025,1,1,0,0,0);
|
||||
var actual = cron.GetNextOccurrence(baseTime);
|
||||
Assert.AreEqual(expected,actual);
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 特殊日期处理测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestFebruaryHandling() {
|
||||
// 测试闰年2月29日
|
||||
var cron = new CronExpression("0 0 0 29 2 * 2028");
|
||||
Assert.IsTrue(cron.DaysOfMonth.Contains(29));
|
||||
|
||||
var nextTime = cron.GetNextOccurrence(new DateTime(2028,2,28));
|
||||
Assert.AreEqual(new DateTime(2028,2,29),nextTime.Date);
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// 日期与星期冲突测试
|
||||
//-----------------------------
|
||||
[TestMethod]
|
||||
public void TestDayOfWeekConflict() {
|
||||
// 每月15号且为星期一(2023-10-15是星期日)
|
||||
var cron = new CronExpression("* * * 15 * 1 *");
|
||||
var baseTime = new DateTime(2023,10,1);
|
||||
|
||||
var nextTime = cron.GetNextOccurrence(baseTime);
|
||||
Assert.AreEqual(2025,nextTime.Year,nextTime.ToString());
|
||||
Assert.AreEqual(9,nextTime.Month,nextTime.ToString());
|
||||
Assert.AreEqual(15,nextTime.Day,nextTime.ToString());
|
||||
Assert.AreEqual(DayOfWeek.Monday,nextTime.DayOfWeek);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.SugarApi.TimedBackgroundTask
|
||||
{
|
||||
/// <summary>
|
||||
/// Cron表达式无法匹配到任何值
|
||||
/// </summary>
|
||||
public class CronAdjustNullException:Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过提供的字段实例化表达式无法匹配到任何值的异常
|
||||
/// </summary>
|
||||
/// <param name="message">错误信息</param>
|
||||
public CronAdjustNullException(string? message) : base($"Cron表达式无法匹配到任何值:{message}") {
|
||||
}
|
||||
}
|
||||
}
|
17
Falcon.SugarApi/TimedBackgroundTask/CronException.cs
Normal file
17
Falcon.SugarApi/TimedBackgroundTask/CronException.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
|
||||
namespace Falcon.SugarApi.TimedBackgroundTask
|
||||
{
|
||||
/// <summary>
|
||||
/// Cron表达式错误
|
||||
/// </summary>
|
||||
public class CronException:Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Cron表达式错误
|
||||
/// </summary>
|
||||
/// <param name="message">错误信息</param>
|
||||
public CronException(string? message) : base($"提供的Cron表达式错误:{message}") {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,33 +65,33 @@ namespace Falcon.SugarApi.TimedBackgroundTask
|
|||
|
||||
Seconds = fields.Length > 0 ? GetRange(fields[0],0,59) : Enumerable.Range(0,60).ToList();
|
||||
if(Seconds.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的秒,无法触发!");
|
||||
throw new CronAdjustNullException("Seconds");
|
||||
}
|
||||
Minutes = fields.Length > 1 ? GetRange(fields[1],0,59) : Enumerable.Range(0,60).ToList();
|
||||
if(Minutes.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的分,无法触发!");
|
||||
throw new CronAdjustNullException("Minutes");
|
||||
}
|
||||
Hours = fields.Length > 2 ? GetRange(fields[2],0,23) : Enumerable.Range(0,24).ToList();
|
||||
if(Hours.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的时,无法触发!");
|
||||
throw new CronAdjustNullException("Hours");
|
||||
}
|
||||
DaysOfMonth = fields.Length > 3 ? GetRange(fields[3],1,31) : Enumerable.Range(1,31).ToList();
|
||||
if(DaysOfMonth.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的日,无法触发!");
|
||||
throw new CronAdjustNullException("DaysOfMonth");
|
||||
}
|
||||
Months = fields.Length > 4 ? GetRange(fields[4],1,12) : Enumerable.Range(1,12).ToList();
|
||||
if(Months.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的月份,无法触发!");
|
||||
throw new CronAdjustNullException("Months");
|
||||
}
|
||||
DaysOfWeek = fields.Length > 5 ? GetRange(fields[5],0,6) : Enumerable.Range(0,7).ToList();
|
||||
if(DaysOfWeek.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的星期几,无法触发!");
|
||||
throw new CronAdjustNullException("DaysOfWeek");
|
||||
}
|
||||
var nowYear = DateTime.Now.Year;
|
||||
var endYear = Options.MaxYear;
|
||||
Years = fields.Length > 6 ? GetRange(fields[6],nowYear,endYear) : Enumerable.Range(nowYear,2).ToList();
|
||||
if(Years.Count == 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(CronExpression),"表达式没有任何可以匹配的年份,无法触发!");
|
||||
throw new CronAdjustNullException("Years");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,7 +236,7 @@ namespace Falcon.SugarApi.TimedBackgroundTask
|
|||
var expChars = exp.ToCharArray().Distinct();
|
||||
var outRangeChars = expChars.Where(a => a.NotIn(charList)).ToArray();
|
||||
if(outRangeChars.Any()) {
|
||||
throw new ArgumentOutOfRangeException(nameof(exp),$"非法字符{new string(outRangeChars)} 在表达式 {exp} 中");
|
||||
throw new CronException($"非法字符{new string(outRangeChars)} 在表达式 {exp} 中");
|
||||
}
|
||||
var list = new List<int>();
|
||||
if(exp == "*") {
|
||||
|
@ -273,12 +273,12 @@ namespace Falcon.SugarApi.TimedBackgroundTask
|
|||
list.Add(iei);
|
||||
}
|
||||
else {
|
||||
throw new ArgumentException("给定的exp表达式错误,逗号分割的每一项都必须是数字",nameof(exp));
|
||||
throw new CronException("给定的exp表达式错误,逗号分割的每一项都必须是数字");
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
throw new ArgumentException("提供的cron表达式错误",nameof(exp));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user