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 }