OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-tps / scenes / test / terrain_probe_selftest.gd

38 lines · gd ref:
extends SceneTree
## Headless gate for TerrainProbe's PURE metric functions.
##
##   godot --headless --path . --script res://scenes/test/terrain_probe_selftest.gd
##
## It cannot measure terrain -- there is no GPU and no physics here, and on a
## heightfield map the CPU field is a different world anyway. What it CAN do is
## prove the maths behind the report: that a flat grid reads flat, a 30 degree
## hillside reads as slope and NOT as roughness, a 1 m spike is seen, a hole is
## counted, and a vertical triangle reads 90 degrees. Those are exactly the
## discriminations the live report's conclusions rest on.
##
## Exit code 0 = every case passed. Non-zero = the instrument is broken and any
## report it produced is not evidence (hyper-games #50 section 6).

func _initialize() -> void:
	var st: Dictionary = TerrainProbe.selftest()
	for c in st["cases"]:
		print("%s  %s   (%s)" % ["PASS" if c[1] else "FAIL", c[0], c[2]])
	print("SELFTEST: %s" % ("PASS" if st["pass"] else "FAIL"))

	# THE GATE MUST ALSO CATCH A BROKEN GATE. A selftest that only ever runs
	# correct data cannot tell a working check from one that returns "pass"
	# unconditionally, so feed the metric a case whose answer it must get WRONG
	# if it is not looking: a grid that is flat except for a step, asserted to
	# read as flat. If this "fails", the metric is alive.
	var n := 9
	var g := PackedFloat32Array()
	g.resize(n * n)
	g.fill(10.0)
	g[40] = 10.5
	var m: Dictionary = TerrainProbe.height_metrics(g, n, 0.25)
	var alive: bool = float(m["max_step"]) > 0.4
	print("%s  negative control: a 0.5 m step must NOT read as flat   (max_step=%.4f)"
			% ["PASS" if alive else "FAIL", m["max_step"]])

	quit(0 if (bool(st["pass"]) and alive) else 1)