2023-01-17 04:09:06 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
|
|
|
|
using MfGames.Gallium;
|
|
|
|
using MfGames.Nitride.Tests;
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
using NodaTime;
|
|
|
|
using NodaTime.Testing;
|
|
|
|
|
2023-01-17 04:09:06 +00:00
|
|
|
using Xunit;
|
|
|
|
using Xunit.Abstractions;
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
using YamlDotNet.Serialization;
|
|
|
|
using YamlDotNet.Serialization.NamingConventions;
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
using Zio;
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
namespace MfGames.Nitride.Temporal.Schedules.Tests;
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-21 05:28:41 +00:00
|
|
|
public class PeriodicPathRegexScheduleTest : TemporalSchedulesTestBase
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-21 05:28:41 +00:00
|
|
|
public PeriodicPathRegexScheduleTest(ITestOutputHelper output)
|
2023-01-17 04:09:06 +00:00
|
|
|
: base(output)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
[Fact]
|
2023-01-17 04:10:24 +00:00
|
|
|
public void DeserializedSetupWorks()
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
|
|
|
using TemporalSchedulesTestContext context = this.CreateContext();
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
// Create a numerical series of entities.
|
|
|
|
var input = new List<Entity>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
new Entity().SetAll((UPath)"/chapter-01.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-02.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-03.md", new TestModel()),
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
TestModel model = new DeserializerBuilder()
|
|
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
|
|
.Build()
|
|
|
|
.Deserialize<TestModel>(
|
|
|
|
string.Join(
|
|
|
|
"\n",
|
|
|
|
"---",
|
|
|
|
"access: custom",
|
|
|
|
"schedules:",
|
2023-01-19 04:32:54 +00:00
|
|
|
" - pathRegex: chapter-(\\d+)",
|
|
|
|
" scheduleStart: 2023-01-01",
|
2023-01-19 05:51:37 +00:00
|
|
|
" schedulePeriod: 1 week",
|
2023-01-17 04:10:24 +00:00
|
|
|
" access: public",
|
|
|
|
""));
|
2023-01-21 05:28:41 +00:00
|
|
|
List<TestRegexSchedule>? schedules = model.Schedules!;
|
2023-01-17 04:10:24 +00:00
|
|
|
|
|
|
|
// Create the operation and run it, but treat it as being set after the
|
|
|
|
// second but before the third item.
|
2023-01-21 07:52:52 +00:00
|
|
|
TimeService time = context.Resolve<TimeService>();
|
2023-01-17 04:10:24 +00:00
|
|
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
2023-01-18 00:42:31 +00:00
|
|
|
.WithGetSchedules(_ => schedules);
|
2023-01-17 04:10:24 +00:00
|
|
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
|
|
|
|
|
|
|
time.Clock = new FakeClock(now);
|
|
|
|
|
|
|
|
var actual = op
|
|
|
|
.Run(input)
|
|
|
|
.Select(
|
|
|
|
a => string.Format(
|
|
|
|
"{0} -- {1} -- {2}",
|
|
|
|
a.Get<UPath>().ToString(),
|
|
|
|
a.Has<Instant>()
|
|
|
|
? time
|
|
|
|
.ToDateTime(a.Get<Instant>())
|
|
|
|
.ToString("yyyy-MM-dd")
|
|
|
|
: "none",
|
|
|
|
a.Get<TestModel>().Access))
|
|
|
|
.ToList();
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
var expected = new List<string>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
"/chapter-01.md -- 2023-01-01 -- public",
|
|
|
|
"/chapter-02.md -- 2023-01-08 -- public",
|
|
|
|
"/chapter-03.md -- none -- private",
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
TestHelper.CompareObjects(expected, actual);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Fact]
|
2023-01-17 04:10:24 +00:00
|
|
|
public void ManualSetupWorks()
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
|
|
|
using TemporalSchedulesTestContext context = this.CreateContext();
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
// Create a numerical series of entities.
|
|
|
|
var input = new List<Entity>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
new Entity().SetAll((UPath)"/chapter-01.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-02.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-03.md", new TestModel()),
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
2023-01-21 05:28:41 +00:00
|
|
|
var schedules = new List<TestRegexSchedule>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
new()
|
|
|
|
{
|
|
|
|
ScheduleStart = DateTime.Parse("2023-01-01"),
|
|
|
|
Access = "public",
|
|
|
|
},
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
// Create the operation and run it, but treat it as being set after the
|
|
|
|
// second but before the third item.
|
2023-01-21 07:52:52 +00:00
|
|
|
TimeService time = context.Resolve<TimeService>();
|
2023-01-17 04:10:24 +00:00
|
|
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
2023-01-18 00:42:31 +00:00
|
|
|
.WithGetSchedules(_ => schedules);
|
2023-01-17 04:10:24 +00:00
|
|
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
time.Clock = new FakeClock(now);
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
var actual = op
|
|
|
|
.Run(input)
|
|
|
|
.Select(
|
|
|
|
a => string.Format(
|
|
|
|
"{0} -- {1} -- {2}",
|
|
|
|
a.Get<UPath>().ToString(),
|
|
|
|
a.Has<Instant>()
|
|
|
|
? time
|
|
|
|
.ToDateTime(a.Get<Instant>())
|
|
|
|
.ToString("yyyy-MM-dd")
|
|
|
|
: "none",
|
|
|
|
a.Get<TestModel>().Access))
|
|
|
|
.ToList();
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
var expected = new List<string>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
"/chapter-01.md -- 2023-01-01 -- public",
|
|
|
|
"/chapter-02.md -- 2023-01-08 -- public",
|
|
|
|
"/chapter-03.md -- none -- private",
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
TestHelper.CompareObjects(expected, actual);
|
|
|
|
}
|
|
|
|
|
2023-01-19 05:51:37 +00:00
|
|
|
[Fact]
|
|
|
|
public void ScheduleOffsetWorks()
|
|
|
|
{
|
|
|
|
using TemporalSchedulesTestContext context = this.CreateContext();
|
|
|
|
|
|
|
|
// Create a numerical series of entities.
|
|
|
|
var input = new List<Entity>
|
|
|
|
{
|
|
|
|
new Entity().SetAll((UPath)"/chapter-11.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-12.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-13.md", new TestModel()),
|
|
|
|
};
|
|
|
|
|
2023-01-21 05:28:41 +00:00
|
|
|
var schedules = new List<TestRegexSchedule>
|
2023-01-19 05:51:37 +00:00
|
|
|
{
|
|
|
|
new()
|
|
|
|
{
|
|
|
|
ScheduleStart = DateTime.Parse("2023-01-01"),
|
|
|
|
CaptureOffset = -11,
|
|
|
|
Access = "public",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create the operation and run it, but treat it as being set after the
|
|
|
|
// second but before the third item.
|
2023-01-21 07:52:52 +00:00
|
|
|
TimeService time = context.Resolve<TimeService>();
|
2023-01-19 05:51:37 +00:00
|
|
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
|
|
|
.WithGetSchedules(_ => schedules);
|
|
|
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
|
|
|
|
|
|
|
time.Clock = new FakeClock(now);
|
|
|
|
|
|
|
|
var actual = op
|
|
|
|
.Run(input)
|
|
|
|
.Select(
|
|
|
|
a => string.Format(
|
|
|
|
"{0} -- {1} -- {2}",
|
|
|
|
a.Get<UPath>().ToString(),
|
|
|
|
a.Has<Instant>()
|
|
|
|
? time
|
|
|
|
.ToDateTime(a.Get<Instant>())
|
|
|
|
.ToString("yyyy-MM-dd")
|
|
|
|
: "none",
|
|
|
|
a.Get<TestModel>().Access))
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
var expected = new List<string>
|
|
|
|
{
|
|
|
|
"/chapter-11.md -- 2023-01-01 -- public",
|
|
|
|
"/chapter-12.md -- 2023-01-08 -- public",
|
|
|
|
"/chapter-13.md -- none -- private",
|
|
|
|
};
|
|
|
|
|
|
|
|
TestHelper.CompareObjects(expected, actual);
|
|
|
|
}
|
|
|
|
|
2023-01-17 04:09:06 +00:00
|
|
|
[Fact]
|
2023-01-17 04:10:24 +00:00
|
|
|
public void SequencedScheduleWorks()
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
|
|
|
using TemporalSchedulesTestContext context = this.CreateContext();
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
// Create a numerical series of entities.
|
|
|
|
var input = new List<Entity>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
new Entity().SetAll((UPath)"/chapter-01.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-02.md", new TestModel()),
|
|
|
|
new Entity().SetAll((UPath)"/chapter-03.md", new TestModel()),
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
2023-01-21 05:28:41 +00:00
|
|
|
var schedules = new List<TestRegexSchedule>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
new()
|
|
|
|
{
|
|
|
|
ScheduleStart = DateTime.Parse("2023-01-01"),
|
|
|
|
Access = "subscriber",
|
|
|
|
},
|
|
|
|
new()
|
|
|
|
{
|
|
|
|
ScheduleStart = DateTime.Parse("2023-01-07"),
|
|
|
|
Access = "public",
|
|
|
|
},
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
// Create the operation and run it, but treat it as being set after the
|
|
|
|
// second but before the third item.
|
2023-01-21 07:52:52 +00:00
|
|
|
TimeService time = context.Resolve<TimeService>();
|
2023-01-17 04:10:24 +00:00
|
|
|
ApplySchedules op = context.Resolve<ApplySchedules>()
|
2023-01-18 00:42:31 +00:00
|
|
|
.WithGetSchedules(_ => schedules);
|
2023-01-17 04:10:24 +00:00
|
|
|
var now = Instant.FromUtc(2023, 1, 9, 0, 0);
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
time.Clock = new FakeClock(now);
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
var actual = op
|
|
|
|
.Run(input)
|
|
|
|
.Select(
|
|
|
|
a => string.Format(
|
|
|
|
"{0} -- {1} -- {2}",
|
|
|
|
a.Get<UPath>().ToString(),
|
|
|
|
a.Has<Instant>()
|
|
|
|
? time
|
|
|
|
.ToDateTime(a.Get<Instant>())
|
|
|
|
.ToString("yyyy-MM-dd")
|
|
|
|
: "none",
|
|
|
|
a.Get<TestModel>().Access))
|
|
|
|
.ToList();
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
var expected = new List<string>
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
"/chapter-01.md -- 2023-01-07 -- public",
|
|
|
|
"/chapter-02.md -- 2023-01-08 -- subscriber",
|
|
|
|
"/chapter-03.md -- none -- private",
|
2023-01-17 04:09:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
TestHelper.CompareObjects(expected, actual);
|
|
|
|
}
|
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
public class TestModel
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-17 04:10:24 +00:00
|
|
|
public string? Access { get; set; } = "private";
|
|
|
|
|
2023-01-21 05:28:41 +00:00
|
|
|
public List<TestRegexSchedule>? Schedules { get; set; }
|
2023-01-17 04:09:06 +00:00
|
|
|
}
|
|
|
|
|
2023-01-21 05:28:41 +00:00
|
|
|
public class TestRegexSchedule : PeriodicPathRegexSchedule
|
2023-01-17 04:09:06 +00:00
|
|
|
{
|
2023-01-21 05:28:41 +00:00
|
|
|
public TestRegexSchedule()
|
2023-01-17 04:10:24 +00:00
|
|
|
{
|
2023-01-18 20:27:12 +00:00
|
|
|
this.SchedulePeriod = "1 week";
|
2023-01-17 04:10:24 +00:00
|
|
|
}
|
2023-01-17 04:09:06 +00:00
|
|
|
|
2023-01-17 04:10:24 +00:00
|
|
|
public string? Access { get; set; }
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
protected override Entity Apply(
|
|
|
|
Entity entity,
|
|
|
|
int number,
|
|
|
|
Instant instant)
|
|
|
|
{
|
|
|
|
TestModel model = entity.Get<TestModel>();
|
|
|
|
model.Access = this.Access;
|
|
|
|
return entity.SetAll(instant, model);
|
|
|
|
}
|
2023-01-17 04:09:06 +00:00
|
|
|
}
|
|
|
|
}
|