import XCTest
@testable import Physarum
import PhysarumEngine
final class RandomizeTests: XCTestCase {
func testEveryScalarStrategySamplesWithinDescriptorRange() {
var g = SeededGenerator(seed: 42)
for d in ParamRegistry.all {
let strat = RandomizeProfiles.strategy(for: d.id)
for _ in 0..<200 {
let v = strat.sample(using: &g)
XCTAssertGreaterThanOrEqual(v, d.range.lowerBound - 1e-9, "\(d.idKey) below range")
XCTAssertLessThanOrEqual(v, d.range.upperBound + 1e-9, "\(d.idKey) above range")
}
}
}
func testMostlyZeroEmitsZeroAndNonZero() {
var g = SeededGenerator(seed: 7)
let strat = RandomStrategy.mostlyZero(zeroProb: 0.7, 0.1...0.6)
var zeros = 0, nonzeros = 0
for _ in 0..<500 { strat.sample(using: &g) == 0 ? (zeros += 1) : (nonzeros += 1) }
XCTAssertGreaterThan(zeros, 0)
XCTAssertGreaterThan(nonzeros, 0)
}
func testRandomizeRespectsLocks() {
let state = AppState()
let d = ParamRegistry.all.first { $0.id == .moveSpeed(0) }!
state.toggleLock(.moveSpeed(0))
let locked = d.get(state.edited)
var g = SeededGenerator(seed: 99)
state.randomize(using: &g)
XCTAssertEqual(d.get(state.edited), locked, accuracy: 1e-4, "locked param must not change")
}
func testRandomizeKeepsAllScalarsInRange() {
let state = AppState()
var g = SeededGenerator(seed: 3)
state.randomize(using: &g)
for d in ParamRegistry.all {
let v = d.get(state.edited)
XCTAssertGreaterThanOrEqual(v, d.range.lowerBound - 0.5, "\(d.idKey)")
XCTAssertLessThanOrEqual(v, d.range.upperBound + 0.5, "\(d.idKey)")
}
}
func testRandomizePushesOneUndoSnapshot() {
let state = AppState()
let before = state.undoStack.count
var g = SeededGenerator(seed: 5)
state.randomize(using: &g)
XCTAssertEqual(state.undoStack.count, before + 1)
// undo returns to the pre-randomize state
let preMove = ParamRegistry.all.first { $0.id == .moveSpeed(0) }!.get(state.baseline)
state.undoEdit()
XCTAssertEqual(ParamRegistry.all.first { $0.id == .moveSpeed(0) }!.get(state.edited),
preMove, accuracy: 1e-4)
}
func testRandomizeIsDeterministicForSameSeed() {
let a = AppState(); var g1 = SeededGenerator(seed: 1234); a.randomize(using: &g1)
let b = AppState(); var g2 = SeededGenerator(seed: 1234); b.randomize(using: &g2)
XCTAssertTrue(paramsEqual(a.edited, b.edited), "same seed → same result")
}
}