chore: scaffold tracks and tooling

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-28 23:34:21 +01:00
co-authored by Claude Opus 5.5
parent 6dc5bdde9e
commit e150b7fefb
27 changed files with 282 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Compile Include="Util.fs" />
</ItemGroup>
</Project>
+2
View File
@@ -0,0 +1,2 @@
/// Placeholder; replaced by the m01 utilities.
module Snake.Util
+9
View File
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Compile Include="Util.fs" />
</ItemGroup>
</Project>
+2
View File
@@ -0,0 +1,2 @@
/// Placeholder; replaced by the m01 utilities.
module Snake.Util
Executable
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Usage: ./test.sh [MNN] (no arg = all tests)
set -euo pipefail
cd "$(dirname "$0")"
export PATH="$HOME/.dotnet:$PATH"
export DOTNET_NOLOGO=1 DOTNET_CLI_TELEMETRY_OPTOUT=1
if [ $# -ge 1 ]; then
exec dotnet run --project tests -- --filter-test-list "$1"
else
exec dotnet run --project tests
fi
+21
View File
@@ -0,0 +1,21 @@
/// Loads shared fixtures from ../../fixtures/<name>.json.
/// Typed decoders (point, direction, status, action, state, opt) arrive with the model (Task 13).
module Snake.Tests.Fixtures
open System.IO
open System.Text.Json
let private dir =
Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "..", "fixtures"))
let load (name: string) : JsonElement =
use doc = JsonDocument.Parse(File.ReadAllText(Path.Combine(dir, name + ".json")))
doc.RootElement.Clone()
/// The cases array of a fixture.
let cases (name: string) : JsonElement list =
(load name).GetProperty("cases").EnumerateArray() |> List.ofSeq
/// Decode a nullable JSON value into an Option.
let opt (f: JsonElement -> 'a) (v: JsonElement) : 'a option =
if v.ValueKind = JsonValueKind.Null then None else Some(f v)
+23
View File
@@ -0,0 +1,23 @@
module Snake.Tests.M00Sanity
open System.Text.Json
open Expecto
open Snake.Tests
[<Tests>]
let tests =
testList "M00 sanity" [
test "arithmetic" { Expect.equal (1 + 1) 2 "1 + 1" }
test "fixture loads and cases hold" {
Expect.equal ((Fixtures.load "m00-sanity").GetProperty("function").GetString()) "sanity" "function"
for c in Fixtures.cases "m00-sanity" do
let a = c.GetProperty("args").EnumerateArray() |> Seq.map (fun e -> e.GetInt32()) |> List.ofSeq
Expect.equal (List.sum a) (c.GetProperty("expected").GetInt32()) (c.GetProperty("name").GetString())
}
test "opt decodes null" {
use d = JsonDocument.Parse("null")
Expect.isNone (Fixtures.opt (fun e -> e.GetInt32()) d.RootElement) "null"
}
]
+6
View File
@@ -0,0 +1,6 @@
module Snake.Tests.Main
open Expecto
[<EntryPoint>]
let main argv = runTestsInAssemblyWithCLIArgs [] argv
+17
View File
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Fixtures.fs" />
<Compile Include="M00Sanity.fs" />
<Compile Include="Main.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Expecto" Version="11.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../src/Snake.fsproj" />
</ItemGroup>
</Project>