package util_test import ( "fmt" "math" "testing" "galaxy/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestShortDistance(t *testing.T) { for i, tc := range []struct { w, h uint32 x1, y1, x2, y2, d float64 }{ {10, 10, 0, 0, 5, 5, 7.071}, {10, 10, 0, 0, 5.01, 5.01, 7.057}, {10, 10, 2, 2, 8, 2, 4.}, {10, 10, 8, 7, 1, 7, 3.}, } { t.Run(fmt.Sprint(i), func(t *testing.T) { d := util.ShortDistance(tc.w, tc.h, tc.x1, tc.y1, tc.x2, tc.y2) assert.Equal(t, tc.d, util.Fixed3(d)) }) } } func TestNextTravelCoord(t *testing.T) { for i, tc := range []struct { w, h uint32 ox, oy, dx, dy, delta float64 tx, ty float64 arrived bool }{ {w: 10, h: 10, ox: 0.0, oy: 0.0, dx: 2.0, dy: 0.0, delta: 1.0, tx: 1.0, ty: 0.0, arrived: false}, {w: 10, h: 10, ox: 0.0, oy: 0.0, dx: 0.0, dy: 2.0, delta: 1.0, tx: 0.0, ty: 1.0, arrived: false}, {w: 10, h: 10, ox: 1.0, oy: 1.0, dx: 9.0, dy: 1.0, delta: 1.0, tx: 0.0, ty: 1.0, arrived: false}, {w: 10, h: 10, ox: 1.0, oy: 9.5, dx: 1.0, dy: 1.0, delta: 1.0, tx: 1.0, ty: 0.5, arrived: false}, {w: 10, h: 10, ox: 1.0, oy: 1.0, dx: 5.0, dy: 5.0, delta: 2.0, tx: 2.414, ty: 2.414, arrived: false}, {w: 10, h: 10, ox: 1.0, oy: 1.0, dx: 9.0, dy: 9.0, delta: 2.0, tx: 9.586, ty: 9.586, arrived: false}, {w: 10, h: 10, ox: 5.0, oy: 5.0, dx: 9.0, dy: 9.0, delta: 6.0, tx: 9.0, ty: 9.0, arrived: true}, {w: 10, h: 10, ox: 6.0, oy: 6.0, dx: 10.0, dy: 10.0, delta: 6.0, tx: 10.0, ty: 10.0, arrived: true}, {w: 10, h: 10, ox: 1.0, oy: 2.0, dx: 7.0, dy: 8.0, delta: 6.0, tx: 7.0, ty: 8.0, arrived: true}, } { t.Run(fmt.Sprint(i), func(t *testing.T) { tx, ty, arrived := util.NextTravelCoord(tc.w, tc.h, tc.ox, tc.oy, tc.dx, tc.dy, tc.delta) assert.Equal(t, tc.arrived, arrived) assert.Equal(t, tc.tx, util.Fixed3(tx)) assert.Equal(t, tc.ty, util.Fixed3(ty)) }) } } func TestWrapF(t *testing.T) { t.Parallel() tests := []struct { name string value float64 size int want float64 }{ { name: "already in range integer", value: 3, size: 10, want: 3, }, { name: "already in range fractional", value: 3.25, size: 10, want: 3.25, }, { name: "positive overflow integer", value: 12, size: 10, want: 2, }, { name: "positive overflow fractional", value: 12.75, size: 10, want: 2.75, }, { name: "negative small fractional", value: -0.25, size: 10, want: 9.75, }, { name: "negative overflow integer", value: -12, size: 10, want: 8, }, { name: "negative overflow fractional", value: -12.75, size: 10, want: 7.25, }, { name: "exact multiple positive", value: 20, size: 10, want: 0, }, { name: "exact multiple negative", value: -20, size: 10, want: 0, }, { name: "size one wraps into [0,1)", value: 123.456, size: 1, want: math.Mod(123.456, 1), }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() got := util.WrapF(tt.value, tt.size) require.InDelta(t, tt.want, got, 1e-12) require.GreaterOrEqual(t, got, 0.0) require.Less(t, got, float64(tt.size)) }) } } // TestWrapF_NaNAndInf verifies IEEE 754 behavior inherited from math.Mod. func TestWrapF_NaNAndInf(t *testing.T) { t.Parallel() require.True(t, math.IsNaN(util.WrapF(math.NaN(), 10))) require.True(t, math.IsNaN(util.WrapF(math.Inf(1), 10))) require.True(t, math.IsNaN(util.WrapF(math.Inf(-1), 10))) }