Commit 390150d5 authored by Michael Lynch's avatar Michael Lynch Committed by GitHub

refactor(challenger): rewrite unit tests for converting gindex to Position (#8782)

* refactor(challenger): rewrite unit tests for converting gindex to Position

* Update

* refactor: replace single-use named structs with anonymous structs

* refactor(challenger): refactor TestAttack and TestDefend tests

* Update op-challenger/game/fault/types/position.go
Co-authored-by: default avatarrefcell.eth <abigger87@gmail.com>

* Remove example from spec

* Remove Equal method

* Move treeNodes into TestTraceIndex

* Get rid of extra function docstring

---------
Co-authored-by: default avatarrefcell.eth <abigger87@gmail.com>
parent 7a678883
...@@ -25,6 +25,7 @@ func NewPosition(depth int, indexAtDepth *big.Int) Position { ...@@ -25,6 +25,7 @@ func NewPosition(depth int, indexAtDepth *big.Int) Position {
} }
} }
// NewPositionFromGIndex creates a new Position given a generalized index.
func NewPositionFromGIndex(x *big.Int) Position { func NewPositionFromGIndex(x *big.Int) Position {
depth := bigMSB(x) depth := bigMSB(x)
withoutMSB := new(big.Int).Not(new(big.Int).Lsh(big.NewInt(1), uint(depth))) withoutMSB := new(big.Int).Not(new(big.Int).Lsh(big.NewInt(1), uint(depth)))
......
...@@ -39,63 +39,58 @@ func TestBigMSB(t *testing.T) { ...@@ -39,63 +39,58 @@ func TestBigMSB(t *testing.T) {
} }
} }
var treeNodes = []struct { func TestGindexPositionConversions(t *testing.T) {
GIndex *big.Int tests := []struct {
Depth int gindex *big.Int
MaxDepth int expectedPosition Position
IndexAtDepth *big.Int }{
TraceIndex *big.Int {bi(1), NewPosition(0, bi(0))},
AttackGIndex *big.Int // 0 indicates attack is not possible from this node
DefendGIndex *big.Int // 0 indicates defend is not possible from this node {bi(2), NewPosition(1, bi(0))},
}{ {bi(3), NewPosition(1, bi(1))},
{GIndex: bi(1), Depth: 0, MaxDepth: 4, IndexAtDepth: bi(0), TraceIndex: bi(15), AttackGIndex: bi(2)},
{GIndex: bi(2), Depth: 1, MaxDepth: 4, IndexAtDepth: bi(0), TraceIndex: bi(7), AttackGIndex: bi(4), DefendGIndex: bi(6)},
{GIndex: bi(3), Depth: 1, MaxDepth: 4, IndexAtDepth: bi(1), TraceIndex: bi(15), AttackGIndex: bi(6)},
{GIndex: bi(4), Depth: 2, MaxDepth: 4, IndexAtDepth: bi(0), TraceIndex: bi(3), AttackGIndex: bi(8), DefendGIndex: bi(10)},
{GIndex: bi(5), Depth: 2, MaxDepth: 4, IndexAtDepth: bi(1), TraceIndex: bi(7), AttackGIndex: bi(10)},
{GIndex: bi(6), Depth: 2, MaxDepth: 4, IndexAtDepth: bi(2), TraceIndex: bi(11), AttackGIndex: bi(12), DefendGIndex: bi(14)},
{GIndex: bi(7), Depth: 2, MaxDepth: 4, IndexAtDepth: bi(3), TraceIndex: bi(15), AttackGIndex: bi(14)},
{GIndex: bi(8), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(0), TraceIndex: bi(1), AttackGIndex: bi(16), DefendGIndex: bi(18)},
{GIndex: bi(9), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(1), TraceIndex: bi(3), AttackGIndex: bi(18)},
{GIndex: bi(10), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(2), TraceIndex: bi(5), AttackGIndex: bi(20), DefendGIndex: bi(22)},
{GIndex: bi(11), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(3), TraceIndex: bi(7), AttackGIndex: bi(22)},
{GIndex: bi(12), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(4), TraceIndex: bi(9), AttackGIndex: bi(24), DefendGIndex: bi(26)},
{GIndex: bi(13), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(5), TraceIndex: bi(11), AttackGIndex: bi(26)},
{GIndex: bi(14), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(6), TraceIndex: bi(13), AttackGIndex: bi(28), DefendGIndex: bi(30)},
{GIndex: bi(15), Depth: 3, MaxDepth: 4, IndexAtDepth: bi(7), TraceIndex: bi(15), AttackGIndex: bi(30)},
{GIndex: bi(16), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(0), TraceIndex: bi(0)},
{GIndex: bi(17), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(1), TraceIndex: bi(1)},
{GIndex: bi(18), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(2), TraceIndex: bi(2)},
{GIndex: bi(19), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(3), TraceIndex: bi(3)},
{GIndex: bi(20), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(4), TraceIndex: bi(4)},
{GIndex: bi(21), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(5), TraceIndex: bi(5)},
{GIndex: bi(22), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(6), TraceIndex: bi(6)},
{GIndex: bi(23), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(7), TraceIndex: bi(7)},
{GIndex: bi(24), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(8), TraceIndex: bi(8)},
{GIndex: bi(25), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(9), TraceIndex: bi(9)},
{GIndex: bi(26), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(10), TraceIndex: bi(10)},
{GIndex: bi(27), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(11), TraceIndex: bi(11)},
{GIndex: bi(28), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(12), TraceIndex: bi(12)},
{GIndex: bi(29), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(13), TraceIndex: bi(13)},
{GIndex: bi(30), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(14), TraceIndex: bi(14)},
{GIndex: bi(31), Depth: 4, MaxDepth: 4, IndexAtDepth: bi(15), TraceIndex: bi(15)},
{GIndex: bi(0).Mul(bi(math.MaxInt64), bi(2)), Depth: 63, MaxDepth: 64, IndexAtDepth: bi(9223372036854775806), TraceIndex: bi(0).Sub(bi(0).Mul(bi(math.MaxInt64), bi(2)), bi(1))},
}
// TestGINConversions does To & From the generalized index on the treeNodesMaxDepth4 data {bi(4), NewPosition(2, bi(0))},
func TestGINConversions(t *testing.T) { {bi(5), NewPosition(2, bi(1))},
for _, test := range treeNodes { {bi(6), NewPosition(2, bi(2))},
from := NewPositionFromGIndex(test.GIndex) {bi(7), NewPosition(2, bi(3))},
pos := NewPosition(test.Depth, test.IndexAtDepth)
require.EqualValuesf(t, pos.Depth(), from.Depth(), "From GIndex %v vs pos %v", from.Depth(), pos.Depth()) {bi(8), NewPosition(3, bi(0))},
require.Zerof(t, pos.IndexAtDepth().Cmp(from.IndexAtDepth()), "From GIndex %v vs pos %v", from.IndexAtDepth(), pos.IndexAtDepth()) {bi(9), NewPosition(3, bi(1))},
to := pos.ToGIndex() {bi(10), NewPosition(3, bi(2))},
require.Equal(t, test.GIndex, to) {bi(11), NewPosition(3, bi(3))},
{bi(12), NewPosition(3, bi(4))},
{bi(13), NewPosition(3, bi(5))},
{bi(14), NewPosition(3, bi(6))},
{bi(15), NewPosition(3, bi(7))},
{bi(16), NewPosition(4, bi(0))},
{bi(17), NewPosition(4, bi(1))},
{bi(18), NewPosition(4, bi(2))},
{bi(19), NewPosition(4, bi(3))},
{bi(20), NewPosition(4, bi(4))},
{bi(21), NewPosition(4, bi(5))},
{bi(22), NewPosition(4, bi(6))},
{bi(23), NewPosition(4, bi(7))},
{bi(24), NewPosition(4, bi(8))},
{bi(25), NewPosition(4, bi(9))},
{bi(26), NewPosition(4, bi(10))},
{bi(27), NewPosition(4, bi(11))},
{bi(28), NewPosition(4, bi(12))},
{bi(29), NewPosition(4, bi(13))},
{bi(30), NewPosition(4, bi(14))},
{bi(31), NewPosition(4, bi(15))},
{bi(1023), NewPosition(9, bi(511))},
{bi(1024), NewPosition(10, bi(0))},
}
for _, test := range tests {
t.Run(fmt.Sprintf("convert gindex=%s to Position", test.gindex.String()), func(t *testing.T) {
positionActual := NewPositionFromGIndex(test.gindex)
require.EqualValuesf(t, test.expectedPosition.Depth(), positionActual.Depth(), "expected depth=%s, got=%s", test.expectedPosition.Depth(), positionActual.Depth())
require.Zerof(t, test.expectedPosition.IndexAtDepth().Cmp(positionActual.IndexAtDepth()), "expected indexAtDepth=%s, got=%s", test.expectedPosition.IndexAtDepth(), positionActual.IndexAtDepth())
gindex := positionActual.ToGIndex()
require.Truef(t, gindex.Cmp(test.gindex) == 0, "expected gindex=%s, got=%s", test.gindex.String(), gindex.String())
})
} }
} }
...@@ -106,34 +101,102 @@ func TestTraceIndexOfRootWithLargeDepth(t *testing.T) { ...@@ -106,34 +101,102 @@ func TestTraceIndexOfRootWithLargeDepth(t *testing.T) {
require.Equal(t, traceIdx, actual) require.Equal(t, traceIdx, actual)
} }
// TestTraceIndex creates the position & then tests the trace index function on the treeNodesMaxDepth4 data // TestTraceIndex creates the position & then tests the trace index function.
func TestTraceIndex(t *testing.T) { func TestTraceIndex(t *testing.T) {
for _, test := range treeNodes { tests := []struct {
pos := NewPosition(test.Depth, test.IndexAtDepth) depth int
result := pos.TraceIndex(test.MaxDepth) indexAtDepth *big.Int
require.Equal(t, test.TraceIndex, result) maxDepth int
traceIndexExpected *big.Int
}{
{depth: 0, indexAtDepth: bi(0), maxDepth: 4, traceIndexExpected: bi(15)},
{depth: 1, indexAtDepth: bi(0), maxDepth: 4, traceIndexExpected: bi(7)},
{depth: 1, indexAtDepth: bi(1), maxDepth: 4, traceIndexExpected: bi(15)},
{depth: 2, indexAtDepth: bi(0), maxDepth: 4, traceIndexExpected: bi(3)},
{depth: 2, indexAtDepth: bi(1), maxDepth: 4, traceIndexExpected: bi(7)},
{depth: 2, indexAtDepth: bi(2), maxDepth: 4, traceIndexExpected: bi(11)},
{depth: 2, indexAtDepth: bi(3), maxDepth: 4, traceIndexExpected: bi(15)},
{depth: 3, indexAtDepth: bi(0), maxDepth: 4, traceIndexExpected: bi(1)},
{depth: 3, indexAtDepth: bi(1), maxDepth: 4, traceIndexExpected: bi(3)},
{depth: 3, indexAtDepth: bi(2), maxDepth: 4, traceIndexExpected: bi(5)},
{depth: 3, indexAtDepth: bi(3), maxDepth: 4, traceIndexExpected: bi(7)},
{depth: 3, indexAtDepth: bi(4), maxDepth: 4, traceIndexExpected: bi(9)},
{depth: 3, indexAtDepth: bi(5), maxDepth: 4, traceIndexExpected: bi(11)},
{depth: 3, indexAtDepth: bi(6), maxDepth: 4, traceIndexExpected: bi(13)},
{depth: 3, indexAtDepth: bi(7), maxDepth: 4, traceIndexExpected: bi(15)},
{depth: 4, indexAtDepth: bi(0), maxDepth: 4, traceIndexExpected: bi(0)},
{depth: 4, indexAtDepth: bi(1), maxDepth: 4, traceIndexExpected: bi(1)},
{depth: 4, indexAtDepth: bi(2), maxDepth: 4, traceIndexExpected: bi(2)},
{depth: 4, indexAtDepth: bi(3), maxDepth: 4, traceIndexExpected: bi(3)},
{depth: 4, indexAtDepth: bi(4), maxDepth: 4, traceIndexExpected: bi(4)},
{depth: 4, indexAtDepth: bi(5), maxDepth: 4, traceIndexExpected: bi(5)},
{depth: 4, indexAtDepth: bi(6), maxDepth: 4, traceIndexExpected: bi(6)},
{depth: 4, indexAtDepth: bi(7), maxDepth: 4, traceIndexExpected: bi(7)},
{depth: 4, indexAtDepth: bi(8), maxDepth: 4, traceIndexExpected: bi(8)},
{depth: 4, indexAtDepth: bi(9), maxDepth: 4, traceIndexExpected: bi(9)},
{depth: 4, indexAtDepth: bi(10), maxDepth: 4, traceIndexExpected: bi(10)},
{depth: 4, indexAtDepth: bi(11), maxDepth: 4, traceIndexExpected: bi(11)},
{depth: 4, indexAtDepth: bi(12), maxDepth: 4, traceIndexExpected: bi(12)},
{depth: 4, indexAtDepth: bi(13), maxDepth: 4, traceIndexExpected: bi(13)},
{depth: 4, indexAtDepth: bi(14), maxDepth: 4, traceIndexExpected: bi(14)},
{depth: 4, indexAtDepth: bi(15), maxDepth: 4, traceIndexExpected: bi(15)},
{depth: 63, indexAtDepth: bi(9223372036854775806), maxDepth: 64, traceIndexExpected: bi(0).Sub(bi(0).Mul(bi(math.MaxInt64), bi(2)), bi(1))},
}
for _, test := range tests {
require.Equal(t, test.traceIndexExpected, NewPosition(test.depth, test.indexAtDepth).TraceIndex(test.maxDepth))
} }
} }
func TestAttack(t *testing.T) { func TestAttack(t *testing.T) {
for _, test := range treeNodes { tests := []struct {
if test.AttackGIndex == nil || test.AttackGIndex.Cmp(big.NewInt(0)) == 0 { startGIndex *big.Int
continue attackGIndex *big.Int
} }{
pos := NewPosition(test.Depth, test.IndexAtDepth) {bi(1), bi(2)},
{bi(2), bi(4)},
{bi(3), bi(6)},
{bi(4), bi(8)},
{bi(5), bi(10)},
{bi(6), bi(12)},
{bi(7), bi(14)},
{bi(8), bi(16)},
{bi(9), bi(18)},
{bi(10), bi(20)},
{bi(11), bi(22)},
{bi(12), bi(24)},
{bi(13), bi(26)},
{bi(14), bi(28)},
{bi(15), bi(30)},
}
for _, test := range tests {
pos := NewPositionFromGIndex(test.startGIndex)
result := pos.Attack() result := pos.Attack()
require.Equalf(t, test.AttackGIndex, result.ToGIndex(), "Attack from GIndex %v", pos.ToGIndex()) require.Equalf(t, test.attackGIndex, result.ToGIndex(), "attacking GIndex %s, expected=%s, got=%s", test.startGIndex, test.attackGIndex, result.ToGIndex())
} }
} }
func TestDefend(t *testing.T) { func TestDefend(t *testing.T) {
for _, test := range treeNodes { tests := []struct {
if test.DefendGIndex == nil || test.DefendGIndex.Cmp(big.NewInt(0)) == 0 { startGIndex *big.Int
continue defendGIndex *big.Int
} }{
pos := NewPosition(test.Depth, test.IndexAtDepth) {bi(2), bi(6)},
{bi(4), bi(10)},
{bi(6), bi(14)},
{bi(8), bi(18)},
{bi(10), bi(22)},
{bi(12), bi(26)},
{bi(14), bi(30)},
}
for _, test := range tests {
pos := NewPositionFromGIndex(test.startGIndex)
result := pos.Defend() result := pos.Defend()
require.Equalf(t, test.DefendGIndex, result.ToGIndex(), "Defend from GIndex %v", pos.ToGIndex()) require.Equalf(t, test.defendGIndex, result.ToGIndex(), "defending GIndex %s, expected=%s, got=%s", test.startGIndex, test.defendGIndex, result.ToGIndex())
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment