133 lines
4.5 KiB
C#
133 lines
4.5 KiB
C#
using System.Text.Json.Nodes;
|
|
using StellaOps.TaskRunner.Core.Execution;
|
|
using StellaOps.TaskRunner.Core.Planning;
|
|
using StellaOps.TaskRunner.Infrastructure.Execution;
|
|
|
|
using StellaOps.TestKit;
|
|
namespace StellaOps.TaskRunner.Tests;
|
|
|
|
public sealed class FilePackRunStateStoreTests
|
|
{
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public async Task SaveAndGetAsync_RoundTripsState()
|
|
{
|
|
var directory = CreateTempDirectory();
|
|
try
|
|
{
|
|
var store = new FilePackRunStateStore(directory);
|
|
var original = CreateState("run:primary");
|
|
|
|
await store.SaveAsync(original, CancellationToken.None);
|
|
|
|
var reloaded = await store.GetAsync("run:primary", CancellationToken.None);
|
|
Assert.NotNull(reloaded);
|
|
Assert.Equal(original.RunId, reloaded!.RunId);
|
|
Assert.Equal(original.PlanHash, reloaded.PlanHash);
|
|
Assert.Equal(original.FailurePolicy, reloaded.FailurePolicy);
|
|
Assert.Equal(original.Steps.Count, reloaded.Steps.Count);
|
|
var step = Assert.Single(reloaded.Steps);
|
|
Assert.Equal("step-a", step.Key);
|
|
Assert.Equal(original.Steps["step-a"], step.Value);
|
|
}
|
|
finally
|
|
{
|
|
TryDelete(directory);
|
|
}
|
|
}
|
|
|
|
[Trait("Category", TestCategories.Unit)]
|
|
[Fact]
|
|
public async Task ListAsync_ReturnsStatesInDeterministicOrder()
|
|
{
|
|
var directory = CreateTempDirectory();
|
|
try
|
|
{
|
|
var store = new FilePackRunStateStore(directory);
|
|
var stateB = CreateState("run-b");
|
|
var stateA = CreateState("run-a");
|
|
|
|
await store.SaveAsync(stateB, CancellationToken.None);
|
|
await store.SaveAsync(stateA, CancellationToken.None);
|
|
|
|
var states = await store.ListAsync(CancellationToken.None);
|
|
|
|
Assert.Collection(states,
|
|
first => Assert.Equal("run-a", first.RunId),
|
|
second => Assert.Equal("run-b", second.RunId));
|
|
}
|
|
finally
|
|
{
|
|
TryDelete(directory);
|
|
}
|
|
}
|
|
|
|
private static PackRunState CreateState(string runId)
|
|
{
|
|
var failurePolicy = new TaskPackPlanFailurePolicy(MaxAttempts: 3, BackoffSeconds: 30, ContinueOnError: false);
|
|
var metadata = new TaskPackPlanMetadata("sample", "1.0.0", null, Array.Empty<string>());
|
|
var parameters = new Dictionary<string, TaskPackPlanParameterValue>(StringComparer.Ordinal);
|
|
var stepPlan = new TaskPackPlanStep(
|
|
Id: "step-a",
|
|
TemplateId: "run/image",
|
|
Name: "Run step",
|
|
Type: "run",
|
|
Enabled: true,
|
|
Uses: "builtin/run",
|
|
Parameters: parameters,
|
|
ApprovalId: null,
|
|
GateMessage: null,
|
|
Children: Array.Empty<TaskPackPlanStep>());
|
|
var plan = new TaskPackPlan(
|
|
metadata,
|
|
new Dictionary<string, JsonNode?>(StringComparer.Ordinal),
|
|
new[] { stepPlan },
|
|
"hash-123",
|
|
Array.Empty<TaskPackPlanApproval>(),
|
|
Array.Empty<TaskPackPlanSecret>(),
|
|
Array.Empty<TaskPackPlanOutput>(),
|
|
failurePolicy);
|
|
var steps = new Dictionary<string, PackRunStepStateRecord>(StringComparer.Ordinal)
|
|
{
|
|
["step-a"] = new PackRunStepStateRecord(
|
|
StepId: "step-a",
|
|
Kind: PackRunStepKind.Run,
|
|
Enabled: true,
|
|
ContinueOnError: false,
|
|
MaxParallel: null,
|
|
ApprovalId: null,
|
|
GateMessage: null,
|
|
Status: PackRunStepExecutionStatus.Pending,
|
|
Attempts: 1,
|
|
LastTransitionAt: DateTimeOffset.UtcNow,
|
|
NextAttemptAt: null,
|
|
StatusReason: null)
|
|
};
|
|
|
|
var timestamp = DateTimeOffset.UtcNow;
|
|
return PackRunState.Create(runId, "hash-123", plan, failurePolicy, timestamp, steps, timestamp);
|
|
}
|
|
|
|
private static string CreateTempDirectory()
|
|
{
|
|
var path = Path.Combine(Path.GetTempPath(), "stellaops-taskrunner-tests", Guid.NewGuid().ToString("N"));
|
|
Directory.CreateDirectory(path);
|
|
return path;
|
|
}
|
|
|
|
private static void TryDelete(string directory)
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(directory))
|
|
{
|
|
Directory.Delete(directory, recursive: true);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// Swallow cleanup errors to avoid masking test assertions.
|
|
}
|
|
}
|
|
}
|