OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / protocol / orphan_manage_test.go
diff --git a/protocol/orphan_manage_test.go b/protocol/orphan_manage_test.go
new file mode 100644 (file)
index 0000000..0434745
--- /dev/null
@@ -0,0 +1,349 @@
+package protocol
+
+import (
+       "testing"
+       "time"
+
+       "github.com/vapor/protocol/bc"
+       "github.com/vapor/protocol/bc/types"
+       "github.com/vapor/testutil"
+)
+
+var testBlocks = []*types.Block{
+       &types.Block{BlockHeader: types.BlockHeader{
+               PreviousBlockHash: bc.Hash{V0: 1},
+               Timestamp:         0,
+       }},
+       &types.Block{BlockHeader: types.BlockHeader{
+               PreviousBlockHash: bc.Hash{V0: 1},
+               Timestamp:         1,
+       }},
+       &types.Block{BlockHeader: types.BlockHeader{
+               PreviousBlockHash: bc.Hash{V0: 2},
+               Timestamp:         3,
+       }},
+}
+
+var blockHashes = []bc.Hash{}
+
+func init() {
+       for _, block := range testBlocks {
+               blockHashes = append(blockHashes, block.Hash())
+       }
+}
+
+func TestDeleteLRU(t *testing.T) {
+       now := time.Now()
+       cases := []struct {
+               before *OrphanManage
+               after  *OrphanManage
+       }{
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], now},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan:      map[bc.Hash]*orphanBlock{},
+                               prevOrphans: map[bc.Hash][]*bc.Hash{},
+                       },
+               },
+               {
+                       before: &OrphanManage{
+                               orphan:      map[bc.Hash]*orphanBlock{},
+                               prevOrphans: map[bc.Hash][]*bc.Hash{},
+                       },
+                       after: &OrphanManage{
+                               orphan:      map[bc.Hash]*orphanBlock{},
+                               prevOrphans: map[bc.Hash][]*bc.Hash{},
+                       },
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], now.Add(2)},
+                                       blockHashes[1]: &orphanBlock{testBlocks[1], now.Add(1)},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0], &blockHashes[1]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], now.Add(2)},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+               },
+       }
+
+       for i, c := range cases {
+               c.before.deleteLRU()
+               if !testutil.DeepEqual(c.before, c.after) {
+                       t.Errorf("case %d: got %v want %v", i, c.before, c.after)
+               }
+       }
+}
+
+func TestOrphanManageAdd(t *testing.T) {
+       cases := []struct {
+               before    *OrphanManage
+               after     *OrphanManage
+               addOrphan *types.Block
+       }{
+               {
+                       before: &OrphanManage{
+                               orphan:      map[bc.Hash]*orphanBlock{},
+                               prevOrphans: map[bc.Hash][]*bc.Hash{},
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       addOrphan: testBlocks[0],
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       addOrphan: testBlocks[0],
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                                       blockHashes[1]: &orphanBlock{testBlocks[1], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0], &blockHashes[1]},
+                               },
+                       },
+                       addOrphan: testBlocks[1],
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                                       blockHashes[2]: &orphanBlock{testBlocks[2], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                                       bc.Hash{V0: 2}: []*bc.Hash{&blockHashes[2]},
+                               },
+                       },
+                       addOrphan: testBlocks[2],
+               },
+       }
+
+       for i, c := range cases {
+               c.before.Add(c.addOrphan)
+               for _, orphan := range c.before.orphan {
+                       orphan.expiration = time.Time{}
+               }
+               if !testutil.DeepEqual(c.before, c.after) {
+                       t.Errorf("case %d: got %v want %v", i, c.before, c.after)
+               }
+       }
+}
+
+func TestOrphanManageDelete(t *testing.T) {
+       cases := []struct {
+               before *OrphanManage
+               after  *OrphanManage
+               remove *bc.Hash
+       }{
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       remove: &blockHashes[1],
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan:      map[bc.Hash]*orphanBlock{},
+                               prevOrphans: map[bc.Hash][]*bc.Hash{},
+                       },
+                       remove: &blockHashes[0],
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                                       blockHashes[1]: &orphanBlock{testBlocks[1], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0], &blockHashes[1]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{testBlocks[0], time.Time{}},
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       remove: &blockHashes[1],
+               },
+       }
+
+       for i, c := range cases {
+               c.before.delete(c.remove)
+               if !testutil.DeepEqual(c.before, c.after) {
+                       t.Errorf("case %d: got %v want %v", i, c.before, c.after)
+               }
+       }
+}
+
+func TestOrphanManageExpire(t *testing.T) {
+       cases := []struct {
+               before *OrphanManage
+               after  *OrphanManage
+       }{
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{
+                                               testBlocks[0],
+                                               time.Unix(1633479700, 0),
+                                       },
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan:      map[bc.Hash]*orphanBlock{},
+                               prevOrphans: map[bc.Hash][]*bc.Hash{},
+                       },
+               },
+               {
+                       before: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{
+                                               testBlocks[0],
+                                               time.Unix(1633479702, 0),
+                                       },
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+                       after: &OrphanManage{
+                               orphan: map[bc.Hash]*orphanBlock{
+                                       blockHashes[0]: &orphanBlock{
+                                               testBlocks[0],
+                                               time.Unix(1633479702, 0),
+                                       },
+                               },
+                               prevOrphans: map[bc.Hash][]*bc.Hash{
+                                       bc.Hash{V0: 1}: []*bc.Hash{&blockHashes[0]},
+                               },
+                       },
+               },
+       }
+
+       for i, c := range cases {
+               c.before.orphanExpire(time.Unix(1633479701, 0))
+               if !testutil.DeepEqual(c.before, c.after) {
+                       t.Errorf("case %d: got %v want %v", i, c.before, c.after)
+               }
+       }
+}
+
+func TestOrphanManageNumLimit(t *testing.T) {
+       cases := []struct {
+               addOrphanBlockNum    int
+               expectOrphanBlockNum int
+       }{
+               {
+                       addOrphanBlockNum:    10,
+                       expectOrphanBlockNum: 10,
+               },
+               {
+                       addOrphanBlockNum:    numOrphanBlockLimit,
+                       expectOrphanBlockNum: numOrphanBlockLimit,
+               },
+               {
+                       addOrphanBlockNum:    numOrphanBlockLimit + 1,
+                       expectOrphanBlockNum: numOrphanBlockLimit,
+               },
+               {
+                       addOrphanBlockNum:    numOrphanBlockLimit + 10,
+                       expectOrphanBlockNum: numOrphanBlockLimit,
+               },
+       }
+
+       for i, c := range cases {
+               orphanManage := &OrphanManage{
+                       orphan:      map[bc.Hash]*orphanBlock{},
+                       prevOrphans: map[bc.Hash][]*bc.Hash{},
+               }
+               for num := 0; num < c.addOrphanBlockNum; num++ {
+                       orphanManage.Add(&types.Block{BlockHeader: types.BlockHeader{Height: uint64(num)}})
+               }
+               if len(orphanManage.orphan) != c.expectOrphanBlockNum {
+                       t.Errorf("case %d: got %d want %d", i, len(orphanManage.orphan), c.expectOrphanBlockNum)
+               }
+       }
+}