92 lines
4.8 KiB
FSharp
92 lines
4.8 KiB
FSharp
#load "bootstrap.fsx"
|
|
|
|
open System
|
|
open System.IO
|
|
open System.Runtime.InteropServices
|
|
open System.Security.Cryptography
|
|
open System.Text
|
|
open Bootstrap
|
|
|
|
let check condition message = if not condition then failwith message
|
|
let root = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))
|
|
let paths = { Data = root + "/data"; State = root + "/state"; Backups = root + "/backups"; Files = root + "/files" }
|
|
let salt = Encoding.UTF8.GetBytes "delivered saltatory"
|
|
let saltHash = SHA256.HashData salt |> Convert.ToHexString |> _.ToLowerInvariant()
|
|
let config = { Paths = paths; PasswordPath = root + "/password"; Eula = "TRUE"; Args = "libraries/loader/unix_args.txt"; Saltatory = saltHash }
|
|
let mutable downloads = 0
|
|
let data = System.Collections.Generic.Dictionary<string, byte[]>()
|
|
let put key (value: string) = data[key] <- Encoding.UTF8.GetBytes value
|
|
let hash (value: byte[]) = SHA256.HashData value |> Convert.ToHexString |> _.ToLowerInvariant()
|
|
|
|
let manifests =
|
|
[ "mods", "mods.sha256"; "config", "config.sha256"; "defaultconfigs", "defaultconfigs.sha256"
|
|
"kubejs", "kubejs.sha256"; "libraries", "libraries.sha256"; "libraries-integratedscripting", "libraries-integratedscripting.sha256"
|
|
"settings", "settings.sha256"; "tools", "tools.sha256"
|
|
"world/datapacks", "world-datapacks.sha256"; "world/serverconfig", "world-serverconfig.sha256" ]
|
|
|> Map.ofList
|
|
|
|
let manifest name =
|
|
let prefix = manifests |> Map.toSeq |> Seq.find (fun (_, inventory) -> inventory = name) |> fst
|
|
data
|
|
|> Seq.filter (fun item -> item.Key.StartsWith(prefix + "/"))
|
|
|> Seq.map (fun item -> hash item.Value + " " + item.Key.Substring(prefix.Length + 1))
|
|
|> String.concat "\n"
|
|
|
|
let fetch key expected path =
|
|
if not (File.Exists path) || digest path <> expected then
|
|
downloads <- downloads + 1
|
|
File.WriteAllBytes(path, data[key])
|
|
check (digest path = expected) "fixture hash"
|
|
|
|
let fetchSaltatory expected path =
|
|
if not (File.Exists path) || digest path <> expected then
|
|
downloads <- downloads + 1
|
|
File.WriteAllBytes(path, salt)
|
|
check (digest path = expected) "saltatory hash"
|
|
|
|
let load () = run config Architecture.X64 manifest fetch fetchSaltatory
|
|
|
|
try
|
|
Directory.CreateDirectory paths.Files |> ignore
|
|
text (paths.Files + "/server.properties") "level-seed=123"
|
|
text config.PasswordPath "synthetic-password"
|
|
put "mods/old.jar" "old"
|
|
put "mods/saltatory-0.42.1.jar" "pack saltatory"
|
|
put "config/sample.toml" "config"
|
|
put "config/chunky/tasks/minecraft/overworld.properties" "artifact task state"
|
|
put "libraries/loader/unix_args.txt" "loader args"
|
|
put "settings/user_jvm_args.txt" "-Xmx1G"
|
|
put "tools/amd64/mc-server-runner" "runner"
|
|
put "tools/amd64/mc-monitor" "monitor"
|
|
put "world/serverconfig/ftbranks/ranks.snbt" "ranks"
|
|
load ()
|
|
let first = downloads
|
|
check (first = 8) "initial downloads"
|
|
check (not (File.Exists(paths.Data + "/config/chunky/tasks/minecraft/overworld.properties"))) "artifact task state copied"
|
|
check (Directory.Exists(paths.State + "/world/data/chunky")) "mutable task directory missing"
|
|
check (digest (paths.Data + "/mods/saltatory.jar") = saltHash) "delivered saltatory missing"
|
|
check (not (File.Exists(paths.Data + "/mods/saltatory-0.42.1.jar"))) "pack saltatory retained"
|
|
check (File.ReadAllText(paths.Data + "/server.properties") = "level-seed=123\nrcon.password=synthetic-password\n") "properties"
|
|
check (File.ReadAllText(paths.Data + "/server_args.txt") = "loader args") "loader args"
|
|
text (paths.State + "/ops.json") "operators"
|
|
text (paths.State + "/banned-players.json") "banned"
|
|
text (paths.State + "/world/serverconfig/ftbranks/players.snbt") "players"
|
|
text (paths.State + "/world/data/chunky/checkpoint") "task progress"
|
|
Directory.Delete(paths.Data, true)
|
|
load ()
|
|
check (downloads = first) "cached files re-downloaded"
|
|
check (File.ReadAllText(paths.State + "/ops.json") = "operators") "operators changed"
|
|
check (File.ReadAllText(paths.State + "/banned-players.json") = "banned") "bans changed"
|
|
check (File.ReadAllText(paths.State + "/world/serverconfig/ftbranks/players.snbt") = "players") "player state changed"
|
|
check (File.ReadAllText(paths.State + "/world/data/chunky/checkpoint") = "task progress") "task progress changed"
|
|
data.Remove "mods/old.jar" |> ignore
|
|
put "mods/new.jar" "new"
|
|
text (paths.State + "/cache/config/sample.toml") "corrupt"
|
|
load ()
|
|
check (downloads = first + 2) "changed or corrupt files not fetched"
|
|
check (not (File.Exists(paths.State + "/cache/mods/old.jar"))) "stale cache file"
|
|
check (not (File.Exists(paths.Data + "/mods/old.jar"))) "stale runtime mod"
|
|
check (File.ReadAllText(paths.State + "/cache/mods/new.jar") = "new") "new mod missing"
|
|
printfn "bootstrap tests passed"
|
|
finally
|
|
if Directory.Exists root then Directory.Delete(root, true)
|