github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/consensus/dbft/validator/default_test.go (about)

     1  package validator
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/quickchainproject/quickchain/common"
     9  	"github.com/quickchainproject/quickchain/consensus/dbft"
    10  	"github.com/quickchainproject/quickchain/crypto"
    11  )
    12  
    13  var (
    14  	testAddress  = "70524d664ffe731100208a0154e556f9bb679ae6"
    15  	testAddress2 = "b37866a925bccd69cfa98d43b510f1d23d78a851"
    16  )
    17  
    18  func TestValidatorSet(t *testing.T) {
    19  	testNewValidatorSet(t)
    20  	testNormalValSet(t)
    21  	testEmptyValSet(t)
    22  	testStickyProposer(t)
    23  	testAddAndRemoveValidator(t)
    24  }
    25  
    26  func testNewValidatorSet(t *testing.T) {
    27  	var validators []bft.Validator
    28  	const ValCnt = 100
    29  
    30  	// Create 100 validators with random addresses
    31  	b := []byte{}
    32  	for i := 0; i < ValCnt; i++ {
    33  		key, _ := crypto.GenerateKey()
    34  		addr := crypto.PubkeyToAddress(key.PublicKey)
    35  		val := New(addr)
    36  		validators = append(validators, val)
    37  		b = append(b, val.Address().Bytes()...)
    38  	}
    39  
    40  	// Create ValidatorSet
    41  	valSet := NewSet(ExtractValidators(b), bft.RoundRobin)
    42  	if valSet == nil {
    43  		t.Errorf("the validator byte array cannot be parsed")
    44  		t.FailNow()
    45  	}
    46  
    47  	// Check validators sorting: should be in ascending order
    48  	for i := 0; i < ValCnt-1; i++ {
    49  		val := valSet.GetByIndex(uint64(i))
    50  		nextVal := valSet.GetByIndex(uint64(i + 1))
    51  		if strings.Compare(val.String(), nextVal.String()) >= 0 {
    52  			t.Errorf("validator set is not sorted in ascending order")
    53  		}
    54  	}
    55  }
    56  
    57  func testNormalValSet(t *testing.T) {
    58  	b1 := common.Hex2Bytes(testAddress)
    59  	b2 := common.Hex2Bytes(testAddress2)
    60  	addr1 := common.BytesToAddress(b1)
    61  	addr2 := common.BytesToAddress(b2)
    62  	val1 := New(addr1)
    63  	val2 := New(addr2)
    64  
    65  	valSet := newDefaultSet([]common.Address{addr1, addr2}, bft.RoundRobin)
    66  	if valSet == nil {
    67  		t.Errorf("the format of validator set is invalid")
    68  		t.FailNow()
    69  	}
    70  
    71  	// check size
    72  	if size := valSet.Size(); size != 2 {
    73  		t.Errorf("the size of validator set is wrong: have %v, want 2", size)
    74  	}
    75  	// test get by index
    76  	if val := valSet.GetByIndex(uint64(0)); !reflect.DeepEqual(val, val1) {
    77  		t.Errorf("validator mismatch: have %v, want %v", val, val1)
    78  	}
    79  	// test get by invalid index
    80  	if val := valSet.GetByIndex(uint64(2)); val != nil {
    81  		t.Errorf("validator mismatch: have %v, want nil", val)
    82  	}
    83  	// test get by address
    84  	if _, val := valSet.GetByAddress(addr2); !reflect.DeepEqual(val, val2) {
    85  		t.Errorf("validator mismatch: have %v, want %v", val, val2)
    86  	}
    87  	// test get by invalid address
    88  	invalidAddr := common.HexToAddress("0x9535b2e7faaba5288511d89341d94a38063a349b")
    89  	if _, val := valSet.GetByAddress(invalidAddr); val != nil {
    90  		t.Errorf("validator mismatch: have %v, want nil", val)
    91  	}
    92  	// test get proposer
    93  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
    94  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
    95  	}
    96  	// test calculate proposer
    97  	lastProposer := addr1
    98  	valSet.CalcProposer(lastProposer, uint64(0))
    99  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   100  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   101  	}
   102  	valSet.CalcProposer(lastProposer, uint64(3))
   103  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   104  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   105  	}
   106  	// test empty last proposer
   107  	lastProposer = common.Address{}
   108  	valSet.CalcProposer(lastProposer, uint64(3))
   109  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   110  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   111  	}
   112  }
   113  
   114  func testEmptyValSet(t *testing.T) {
   115  	valSet := NewSet(ExtractValidators([]byte{}), bft.RoundRobin)
   116  	if valSet == nil {
   117  		t.Errorf("validator set should not be nil")
   118  	}
   119  }
   120  
   121  func testAddAndRemoveValidator(t *testing.T) {
   122  	valSet := NewSet(ExtractValidators([]byte{}), bft.RoundRobin)
   123  	if !valSet.AddValidator(common.StringToAddress(string(2))) {
   124  		t.Error("the validator should be added")
   125  	}
   126  	if valSet.AddValidator(common.StringToAddress(string(2))) {
   127  		t.Error("the existing validator should not be added")
   128  	}
   129  	valSet.AddValidator(common.StringToAddress(string(1)))
   130  	valSet.AddValidator(common.StringToAddress(string(0)))
   131  	if len(valSet.List()) != 3 {
   132  		t.Error("the size of validator set should be 3")
   133  	}
   134  
   135  	for i, v := range valSet.List() {
   136  		expected := common.StringToAddress(string(i))
   137  		if v.Address() != expected {
   138  			t.Errorf("the order of validators is wrong: have %v, want %v", v.Address().Hex(), expected.Hex())
   139  		}
   140  	}
   141  
   142  	if !valSet.RemoveValidator(common.StringToAddress(string(2))) {
   143  		t.Error("the validator should be removed")
   144  	}
   145  	if valSet.RemoveValidator(common.StringToAddress(string(2))) {
   146  		t.Error("the non-existing validator should not be removed")
   147  	}
   148  	if len(valSet.List()) != 2 {
   149  		t.Error("the size of validator set should be 2")
   150  	}
   151  	valSet.RemoveValidator(common.StringToAddress(string(1)))
   152  	if len(valSet.List()) != 1 {
   153  		t.Error("the size of validator set should be 1")
   154  	}
   155  	valSet.RemoveValidator(common.StringToAddress(string(0)))
   156  	if len(valSet.List()) != 0 {
   157  		t.Error("the size of validator set should be 0")
   158  	}
   159  }
   160  
   161  func testStickyProposer(t *testing.T) {
   162  	b1 := common.Hex2Bytes(testAddress)
   163  	b2 := common.Hex2Bytes(testAddress2)
   164  	addr1 := common.BytesToAddress(b1)
   165  	addr2 := common.BytesToAddress(b2)
   166  	val1 := New(addr1)
   167  	val2 := New(addr2)
   168  
   169  	valSet := newDefaultSet([]common.Address{addr1, addr2}, bft.Sticky)
   170  
   171  	// test get proposer
   172  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   173  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   174  	}
   175  	// test calculate proposer
   176  	lastProposer := addr1
   177  	valSet.CalcProposer(lastProposer, uint64(0))
   178  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   179  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   180  	}
   181  
   182  	valSet.CalcProposer(lastProposer, uint64(1))
   183  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   184  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   185  	}
   186  	// test empty last proposer
   187  	lastProposer = common.Address{}
   188  	valSet.CalcProposer(lastProposer, uint64(3))
   189  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   190  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   191  	}
   192  }