github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/simulations/simulation.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:42</date> 10 //</624450107256868865> 11 12 13 package simulations 14 15 import ( 16 "context" 17 "time" 18 19 "github.com/ethereum/go-ethereum/p2p/enode" 20 ) 21 22 //模拟为在模拟网络中运行操作提供了一个框架 23 //然后等待期望得到满足 24 type Simulation struct { 25 network *Network 26 } 27 28 //新模拟返回在给定网络中运行的新模拟 29 func NewSimulation(network *Network) *Simulation { 30 return &Simulation{ 31 network: network, 32 } 33 } 34 35 //运行通过执行步骤的操作执行模拟步骤,并 36 //然后等待步骤的期望得到满足 37 func (s *Simulation) Run(ctx context.Context, step *Step) (result *StepResult) { 38 result = newStepResult() 39 40 result.StartedAt = time.Now() 41 defer func() { result.FinishedAt = time.Now() }() 42 43 //在步骤期间监视网络事件 44 stop := s.watchNetwork(result) 45 defer stop() 46 47 //执行操作 48 if err := step.Action(ctx); err != nil { 49 result.Error = err 50 return 51 } 52 53 //等待所有节点期望通过、错误或超时 54 nodes := make(map[enode.ID]struct{}, len(step.Expect.Nodes)) 55 for _, id := range step.Expect.Nodes { 56 nodes[id] = struct{}{} 57 } 58 for len(result.Passes) < len(nodes) { 59 select { 60 case id := <-step.Trigger: 61 //如果不检查节点,则跳过 62 if _, ok := nodes[id]; !ok { 63 continue 64 } 65 66 //如果节点已通过,则跳过 67 if _, ok := result.Passes[id]; ok { 68 continue 69 } 70 71 //运行节点期望检查 72 pass, err := step.Expect.Check(ctx, id) 73 if err != nil { 74 result.Error = err 75 return 76 } 77 if pass { 78 result.Passes[id] = time.Now() 79 } 80 case <-ctx.Done(): 81 result.Error = ctx.Err() 82 return 83 } 84 } 85 86 return 87 } 88 89 func (s *Simulation) watchNetwork(result *StepResult) func() { 90 stop := make(chan struct{}) 91 done := make(chan struct{}) 92 events := make(chan *Event) 93 sub := s.network.Events().Subscribe(events) 94 go func() { 95 defer close(done) 96 defer sub.Unsubscribe() 97 for { 98 select { 99 case event := <-events: 100 result.NetworkEvents = append(result.NetworkEvents, event) 101 case <-stop: 102 return 103 } 104 } 105 }() 106 return func() { 107 close(stop) 108 <-done 109 } 110 } 111 112 type Step struct { 113 //操作是为此步骤执行的操作 114 Action func(context.Context) error 115 116 //触发器是一个接收节点ID并触发 117 //该节点的预期检查 118 Trigger chan enode.ID 119 120 //Expect是执行此步骤时等待的期望 121 Expect *Expectation 122 } 123 124 type Expectation struct { 125 //节点是要检查的节点列表 126 Nodes []enode.ID 127 128 //检查给定节点是否满足预期 129 Check func(context.Context, enode.ID) (bool, error) 130 } 131 132 func newStepResult() *StepResult { 133 return &StepResult{ 134 Passes: make(map[enode.ID]time.Time), 135 } 136 } 137 138 type StepResult struct { 139 //错误是运行步骤时遇到的错误 140 Error error 141 142 //Startedat是步骤开始的时间 143 StartedAt time.Time 144 145 //FinishedAt是步骤完成的时间。 146 FinishedAt time.Time 147 148 //传递是成功节点期望的时间戳 149 Passes map[enode.ID]time.Time 150 151 //NetworkEvents是在步骤中发生的网络事件。 152 NetworkEvents []*Event 153 } 154