package helper import ( "image/color" "math" "slices" ) func TestDistance[T tester[T], C color.Color](t T, alpha bool, midpoint func(c0, c1 C) C, f func(c0, c1 C) float64, m color.Model) { colors := slices.Collect(EnumColor[C](alpha, false, m)) for i, c0 := range colors { // a colour should have a distance of zero to itself. if d := f(c0, c0); !EqFloat64Fuzzy(d, 0) { t.Errorf("Distance(%#+v, %#+v) = %f, want 0", c0, c0, d) return } for j := i + 1; j < len(colors); j++ { c1 := colors[j] d, d2 := f(c0, c1), f(c1, c0) switch { case math.IsNaN(d) || math.IsInf(d, 0): t.Errorf("Distance(%#+v, %#+v) = %f, want finite", c0, c1, d) return case d < 0 || EqFloat64Fuzzy(d, 0): t.Errorf("Distance(%#+v, %#+v) = %f, want > 0", c0, c1, d) return case !EqFloat64Fuzzy(d, d2): t.Errorf("Distance(%#+v, %#+v) != Distance(%#+v, %#+v), want %f == %f", c1, c0, c0, c1, d, d2) return } // traveling from c0 to c1 via mid can't possibly be // shorter than traveling from c0 to c1 directly. mid := midpoint(c0, c1) if cumulative := f(c0, mid) + f(mid, c1); !(d < cumulative || EqFloat64Fuzzy(d, cumulative)) { t.Errorf("Distance(%#+v, %#+v)+Distance(%#+v, %#+v) < Distance(%#+v, %#+v), want %f >= %f", c0, mid, mid, c1, c0, c1, cumulative, d) return } } } }