github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/vecmt/median_time_test.go (about)

     1  package vecmt
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/assert"
     7  	"github.com/unicornultrafoundation/go-helios/native/idx"
     8  	"github.com/unicornultrafoundation/go-helios/vecfc"
     9  
    10  	"github.com/unicornultrafoundation/go-helios/hash"
    11  	"github.com/unicornultrafoundation/go-helios/native/dag"
    12  	"github.com/unicornultrafoundation/go-helios/native/dag/tdag"
    13  	"github.com/unicornultrafoundation/go-helios/native/pos"
    14  	"github.com/unicornultrafoundation/go-helios/u2udb/memorydb"
    15  
    16  	"github.com/unicornultrafoundation/go-u2u/native"
    17  )
    18  
    19  func TestMedianTimeOnIndex(t *testing.T) {
    20  	nodes := tdag.GenNodes(5)
    21  	weights := []pos.Weight{5, 4, 3, 2, 1}
    22  	validators := pos.ArrayToValidators(nodes, weights)
    23  
    24  	vi := NewIndex(func(err error) { panic(err) }, LiteConfig())
    25  	vi.Reset(validators, memorydb.New(), nil)
    26  
    27  	assertar := assert.New(t)
    28  	{ // seq=0
    29  		e := hash.ZeroEvent
    30  		// validator indexes are sorted by weight amount
    31  		before := NewHighestBefore(idx.Validator(validators.Len()))
    32  
    33  		before.VSeq.Set(0, vecfc.BranchSeq{Seq: 0})
    34  		before.VTime.Set(0, 100)
    35  
    36  		before.VSeq.Set(1, vecfc.BranchSeq{Seq: 0})
    37  		before.VTime.Set(1, 100)
    38  
    39  		before.VSeq.Set(2, vecfc.BranchSeq{Seq: 1})
    40  		before.VTime.Set(2, 10)
    41  
    42  		before.VSeq.Set(3, vecfc.BranchSeq{Seq: 1})
    43  		before.VTime.Set(3, 10)
    44  
    45  		before.VSeq.Set(4, vecfc.BranchSeq{Seq: 1})
    46  		before.VTime.Set(4, 10)
    47  
    48  		vi.SetHighestBefore(e, before)
    49  		assertar.Equal(native.Timestamp(1), vi.MedianTime(e, 1))
    50  	}
    51  
    52  	{ // fork seen = true
    53  		e := hash.ZeroEvent
    54  		// validator indexes are sorted by weight amount
    55  		before := NewHighestBefore(idx.Validator(validators.Len()))
    56  
    57  		before.SetForkDetected(0)
    58  		before.VTime.Set(0, 100)
    59  
    60  		before.SetForkDetected(1)
    61  		before.VTime.Set(1, 100)
    62  
    63  		before.VSeq.Set(2, vecfc.BranchSeq{Seq: 1})
    64  		before.VTime.Set(2, 10)
    65  
    66  		before.VSeq.Set(3, vecfc.BranchSeq{Seq: 1})
    67  		before.VTime.Set(3, 10)
    68  
    69  		before.VSeq.Set(4, vecfc.BranchSeq{Seq: 1})
    70  		before.VTime.Set(4, 10)
    71  
    72  		vi.SetHighestBefore(e, before)
    73  		assertar.Equal(native.Timestamp(10), vi.MedianTime(e, 1))
    74  	}
    75  
    76  	{ // normal
    77  		e := hash.ZeroEvent
    78  		// validator indexes are sorted by weight amount
    79  		before := NewHighestBefore(idx.Validator(validators.Len()))
    80  
    81  		before.VSeq.Set(0, vecfc.BranchSeq{Seq: 1})
    82  		before.VTime.Set(0, 11)
    83  
    84  		before.VSeq.Set(1, vecfc.BranchSeq{Seq: 2})
    85  		before.VTime.Set(1, 12)
    86  
    87  		before.VSeq.Set(2, vecfc.BranchSeq{Seq: 2})
    88  		before.VTime.Set(2, 13)
    89  
    90  		before.VSeq.Set(3, vecfc.BranchSeq{Seq: 3})
    91  		before.VTime.Set(3, 14)
    92  
    93  		before.VSeq.Set(4, vecfc.BranchSeq{Seq: 4})
    94  		before.VTime.Set(4, 15)
    95  
    96  		vi.SetHighestBefore(e, before)
    97  		assertar.Equal(native.Timestamp(12), vi.MedianTime(e, 1))
    98  	}
    99  
   100  }
   101  
   102  func TestMedianTimeOnDAG(t *testing.T) {
   103  	dagAscii := `
   104   ║
   105   nodeA001
   106   ║
   107   nodeA012
   108   ║            ║
   109   ║            nodeB001
   110   ║            ║            ║
   111   ║            ╠═══════════ nodeC001
   112   ║║           ║            ║            ║
   113   ║╚══════════─╫─══════════─╫─══════════ nodeD001
   114  ║║            ║            ║            ║
   115  ╚ nodeA002════╬════════════╬════════════╣
   116   ║║           ║            ║            ║
   117   ║╚══════════─╫─══════════─╫─══════════ nodeD002
   118   ║            ║            ║            ║
   119   nodeA003════─╫─══════════─╫─═══════════╣
   120   ║            ║            ║
   121   ╠════════════nodeB002     ║
   122   ║            ║            ║
   123   ╠════════════╫═══════════ nodeC002
   124  `
   125  
   126  	weights := []pos.Weight{3, 4, 2, 1}
   127  	genesisTime := native.Timestamp(1)
   128  	creationTimes := map[string]native.Timestamp{
   129  		"nodeA001": native.Timestamp(111),
   130  		"nodeB001": native.Timestamp(112),
   131  		"nodeC001": native.Timestamp(13),
   132  		"nodeD001": native.Timestamp(14),
   133  		"nodeA002": native.Timestamp(120),
   134  		"nodeD002": native.Timestamp(20),
   135  		"nodeA012": native.Timestamp(120),
   136  		"nodeA003": native.Timestamp(20),
   137  		"nodeB002": native.Timestamp(20),
   138  		"nodeC002": native.Timestamp(35),
   139  	}
   140  	medianTimes := map[string]native.Timestamp{
   141  		"nodeA001": genesisTime,
   142  		"nodeB001": genesisTime,
   143  		"nodeC001": native.Timestamp(13),
   144  		"nodeD001": genesisTime,
   145  		"nodeA002": native.Timestamp(112),
   146  		"nodeD002": genesisTime,
   147  		"nodeA012": genesisTime,
   148  		"nodeA003": native.Timestamp(20),
   149  		"nodeB002": native.Timestamp(20),
   150  		"nodeC002": native.Timestamp(35),
   151  	}
   152  	t.Run("testMedianTimeOnDAG", func(t *testing.T) {
   153  		testMedianTime(t, dagAscii, weights, creationTimes, medianTimes, genesisTime)
   154  	})
   155  }
   156  
   157  func testMedianTime(t *testing.T, dagAscii string, weights []pos.Weight, creationTimes map[string]native.Timestamp, medianTimes map[string]native.Timestamp, genesis native.Timestamp) {
   158  	assertar := assert.New(t)
   159  
   160  	var ordered dag.Events
   161  	nodes, _, named := tdag.ASCIIschemeForEach(dagAscii, tdag.ForEachEvent{
   162  		Process: func(e dag.Event, name string) {
   163  			ordered = append(ordered, &eventWithCreationTime{e, creationTimes[name]})
   164  		},
   165  	})
   166  
   167  	validators := pos.ArrayToValidators(nodes, weights)
   168  
   169  	events := make(map[hash.Event]dag.Event)
   170  	getEvent := func(id hash.Event) dag.Event {
   171  		return events[id]
   172  	}
   173  
   174  	vi := NewIndex(func(err error) { panic(err) }, LiteConfig())
   175  	vi.Reset(validators, memorydb.New(), getEvent)
   176  
   177  	// push
   178  	for _, e := range ordered {
   179  		events[e.ID()] = e
   180  		assertar.NoError(vi.Add(e))
   181  		vi.Flush()
   182  	}
   183  
   184  	// check
   185  	for name, e := range named {
   186  		expected, ok := medianTimes[name]
   187  		if !ok {
   188  			continue
   189  		}
   190  		assertar.Equal(expected, vi.MedianTime(e.ID(), genesis), name)
   191  	}
   192  }