-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b08bc01
commit e2adcf1
Showing
5 changed files
with
180 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,101 @@ | ||
package builder | ||
|
||
import ( | ||
"bytes" | ||
"crypto/ed25519" | ||
"testing" | ||
|
||
"github.com/gordian-engine/gordian/gcrypto" | ||
"github.com/gordian-engine/gordian/gturbine" | ||
"github.com/gordian-engine/gordian/tm/tmconsensus" | ||
) | ||
|
||
func TestHelpers(t *testing.T) { | ||
makeTree := func() *gturbine.Tree { | ||
b := NewTreeBuilder(2) | ||
validators := []gturbine.Validator{ | ||
{PubKey: ed25519.PublicKey{1}, Stake: 100}, | ||
{PubKey: ed25519.PublicKey{2}, Stake: 200}, | ||
{PubKey: ed25519.PublicKey{3}, Stake: 300}, | ||
{PubKey: ed25519.PublicKey{4}, Stake: 400}, | ||
{PubKey: ed25519.PublicKey{5}, Stake: 500}, | ||
func makeTestTree(validatorCount int) *gturbine.Tree { | ||
b := NewTreeBuilder(200) | ||
validators := make([]tmconsensus.Validator, validatorCount) | ||
|
||
for i := 0; i < validatorCount; i++ { | ||
pubKey := ed25519.PublicKey(make([]byte, ed25519.PublicKeySize)) | ||
pubKey[0] = byte(i % 255) | ||
pubKey[1] = byte(i / 255) | ||
validators[i] = tmconsensus.Validator{ | ||
PubKey: gcrypto.Ed25519PubKey(pubKey), | ||
Power: uint64((validatorCount - i) * 100), | ||
} | ||
tree, _ := b.BuildTree(validators, 1, 0) | ||
return tree | ||
} | ||
|
||
t.Run("find position", func(t *testing.T) { | ||
tree := makeTree() | ||
|
||
layer, idx := FindLayerPosition(tree, []byte{1}) | ||
tree, _ := b.BuildTree(validators, 1, 0) | ||
return tree | ||
} | ||
|
||
func TestHelpers(t *testing.T) { | ||
t.Run("find position in large tree", func(t *testing.T) { | ||
tree := makeTestTree(500) | ||
|
||
// Test finding root validator | ||
searchKey := make([]byte, ed25519.PublicKeySize) | ||
searchKey[0] = byte(0 % 255) | ||
searchKey[1] = byte(0 / 255) | ||
layer, idx := FindLayerPosition(tree, searchKey) | ||
if layer == nil { | ||
t.Fatal("validator not found") | ||
} | ||
|
||
// Verify the found validator has our search key | ||
foundKey := layer.Validators[idx].PubKey.PubKeyBytes() | ||
if !bytes.Equal(searchKey, foundKey) { | ||
t.Errorf("found wrong validator: want %v, got %v", searchKey, foundKey) | ||
} | ||
|
||
// Test finding last layer validator | ||
searchKey[0] = byte(499 % 255) | ||
searchKey[1] = byte(499 / 255) | ||
layer, idx = FindLayerPosition(tree, searchKey) | ||
if layer == nil { | ||
t.Fatal("validator not found") | ||
} | ||
if idx == -1 { | ||
t.Error("invalid index returned") | ||
foundKey = layer.Validators[idx].PubKey.PubKeyBytes() | ||
if !bytes.Equal(searchKey, foundKey) { | ||
t.Errorf("found wrong validator: want %v, got %v", searchKey, foundKey) | ||
} | ||
|
||
// Test unknown validator | ||
layer, idx = FindLayerPosition(tree, []byte{99}) | ||
// Test non-existent validator | ||
badKey := make([]byte, ed25519.PublicKeySize) | ||
badKey[0] = 255 | ||
badKey[1] = 255 | ||
layer, idx = FindLayerPosition(tree, badKey) | ||
if layer != nil || idx != -1 { | ||
t.Error("found non-existent validator") | ||
} | ||
}) | ||
|
||
t.Run("get children", func(t *testing.T) { | ||
tree := makeTree() | ||
t.Run("children distribution in large tree", func(t *testing.T) { | ||
tree := makeTestTree(500) | ||
|
||
// Root validator should have children | ||
children := GetChildren(tree, tree.Root.Validators[0].PubKey) | ||
if len(children) == 0 { | ||
t.Error("root validator should have children") | ||
// Root layer validators should each get 1 child | ||
for i, v := range tree.Root.Validators { | ||
children := GetChildren(tree, v.PubKey.PubKeyBytes()) | ||
expectedCount := 1 // 200 validators divided by 200 fanout | ||
if len(children) != expectedCount { | ||
t.Errorf("validator %d: expected %d children, got %d", i, expectedCount, len(children)) | ||
} | ||
} | ||
|
||
// Last layer validator should have no children | ||
lastLayer := tree.Root.Children[0].Children[0] | ||
leafChildren := GetChildren(tree, lastLayer.Validators[0].PubKey) | ||
if len(leafChildren) != 0 { | ||
t.Error("leaf validator should have no children") | ||
// Middle layer validators should each get 0 or 1 child | ||
for i, v := range tree.Root.Children[0].Validators { | ||
children := GetChildren(tree, v.PubKey.PubKeyBytes()) | ||
if len(children) > 1 { | ||
t.Errorf("middle layer validator %d has too many children: %d", i, len(children)) | ||
} | ||
} | ||
|
||
// Check distribution | ||
rootChildren := GetChildren(tree, tree.Root.Validators[0].PubKey) | ||
if len(rootChildren) != 1 { | ||
t.Errorf("expected 1 child for first root validator, got %d", len(rootChildren)) | ||
// Last layer validators should have no children | ||
lastLayer := tree.Root.Children[0].Children[0] | ||
for i, v := range lastLayer.Validators { | ||
children := GetChildren(tree, v.PubKey.PubKeyBytes()) | ||
if len(children) != 0 { | ||
t.Errorf("last layer validator %d has children when it shouldn't: %d", i, len(children)) | ||
} | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.