github.com/ethereum/go-ethereum@v1.16.1/beacon/light/request/server_test.go (about) 1 package request 2 3 import ( 4 "testing" 5 6 "github.com/ethereum/go-ethereum/common/mclock" 7 ) 8 9 const ( 10 testRequest = "Life, the Universe, and Everything" 11 testResponse = 42 12 ) 13 14 var testEventType = &EventType{Name: "testEvent"} 15 16 func TestServerEvents(t *testing.T) { 17 rs := &testRequestServer{} 18 clock := &mclock.Simulated{} 19 srv := NewServer(rs, clock) 20 var lastEventType *EventType 21 srv.subscribe(func(event Event) { lastEventType = event.Type }) 22 evTypeName := func(evType *EventType) string { 23 if evType == nil { 24 return "none" 25 } 26 return evType.Name 27 } 28 expEvent := func(expType *EventType) { 29 if lastEventType != expType { 30 t.Errorf("Wrong event type (expected %s, got %s)", evTypeName(expType), evTypeName(lastEventType)) 31 } 32 lastEventType = nil 33 } 34 // user events should simply be passed through 35 rs.eventCb(Event{Type: testEventType}) 36 expEvent(testEventType) 37 // send request, soft timeout, then valid response 38 srv.sendRequest(testRequest) 39 clock.WaitForTimers(1) 40 clock.Run(softRequestTimeout) 41 expEvent(EvTimeout) 42 rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}}) 43 expEvent(EvResponse) 44 // send request, hard timeout (response after hard timeout should be ignored) 45 srv.sendRequest(testRequest) 46 clock.WaitForTimers(1) 47 clock.Run(softRequestTimeout) 48 expEvent(EvTimeout) 49 clock.WaitForTimers(1) 50 clock.Run(hardRequestTimeout) 51 expEvent(EvFail) 52 rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}}) 53 expEvent(nil) 54 srv.unsubscribe() 55 } 56 57 func TestServerParallel(t *testing.T) { 58 rs := &testRequestServer{} 59 srv := NewServer(rs, &mclock.Simulated{}) 60 srv.subscribe(func(event Event) {}) 61 62 expSend := func(expSent int) { 63 var sent int 64 for sent <= expSent { 65 if !srv.canRequestNow() { 66 break 67 } 68 sent++ 69 srv.sendRequest(testRequest) 70 } 71 if sent != expSent { 72 t.Errorf("Wrong number of parallel requests accepted (expected %d, got %d)", expSent, sent) 73 } 74 } 75 // max out parallel allowance 76 expSend(defaultParallelLimit) 77 // 1 answered, should accept 1 more 78 rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}}) 79 expSend(1) 80 // 2 answered, should accept 2 more 81 rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 2, Request: testRequest, Response: testResponse}}) 82 rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 3, Request: testRequest, Response: testResponse}}) 83 expSend(2) 84 // failed request, should decrease allowance and not accept more 85 rs.eventCb(Event{Type: EvFail, Data: RequestResponse{ID: 4, Request: testRequest}}) 86 expSend(0) 87 srv.unsubscribe() 88 } 89 90 func TestServerFail(t *testing.T) { 91 rs := &testRequestServer{} 92 clock := &mclock.Simulated{} 93 srv := NewServer(rs, clock) 94 srv.subscribe(func(event Event) {}) 95 expCanRequest := func(expCanRequest bool) { 96 if canRequest := srv.canRequestNow(); canRequest != expCanRequest { 97 t.Errorf("Wrong result for canRequestNow (expected %v, got %v)", expCanRequest, canRequest) 98 } 99 } 100 // timed out request 101 expCanRequest(true) 102 srv.sendRequest(testRequest) 103 clock.WaitForTimers(1) 104 expCanRequest(true) 105 clock.Run(softRequestTimeout) 106 expCanRequest(false) // cannot request when there is a timed out request 107 rs.eventCb(Event{Type: EvResponse, Data: RequestResponse{ID: 1, Request: testRequest, Response: testResponse}}) 108 expCanRequest(true) 109 // explicit server.Fail 110 srv.fail("") 111 clock.WaitForTimers(1) 112 expCanRequest(false) // cannot request for a while after a failure 113 clock.Run(minFailureDelay) 114 expCanRequest(true) 115 // request returned with EvFail 116 srv.sendRequest(testRequest) 117 rs.eventCb(Event{Type: EvFail, Data: RequestResponse{ID: 2, Request: testRequest}}) 118 clock.WaitForTimers(1) 119 expCanRequest(false) // EvFail should also start failure delay 120 clock.Run(minFailureDelay) 121 expCanRequest(false) // second failure delay is longer, should still be disabled 122 clock.Run(minFailureDelay) 123 expCanRequest(true) 124 srv.unsubscribe() 125 } 126 127 func TestServerEventRateLimit(t *testing.T) { 128 rs := &testRequestServer{} 129 clock := &mclock.Simulated{} 130 srv := NewServer(rs, clock) 131 var eventCount int 132 srv.subscribe(func(event Event) { 133 eventCount++ 134 }) 135 expEvents := func(send, expAllowed int) { 136 eventCount = 0 137 for sent := 0; sent < send; sent++ { 138 rs.eventCb(Event{Type: testEventType}) 139 } 140 if eventCount != expAllowed { 141 t.Errorf("Wrong number of server events passing rate limitation (sent %d, expected %d, got %d)", send, expAllowed, eventCount) 142 } 143 } 144 expEvents(maxServerEventBuffer+5, maxServerEventBuffer) 145 clock.Run(maxServerEventRate) 146 expEvents(5, 1) 147 clock.Run(maxServerEventRate * maxServerEventBuffer * 2) 148 expEvents(maxServerEventBuffer+5, maxServerEventBuffer) 149 srv.unsubscribe() 150 } 151 152 func TestServerUnsubscribe(t *testing.T) { 153 rs := &testRequestServer{} 154 clock := &mclock.Simulated{} 155 srv := NewServer(rs, clock) 156 var eventCount int 157 srv.subscribe(func(event Event) { 158 eventCount++ 159 }) 160 eventCb := rs.eventCb 161 eventCb(Event{Type: testEventType}) 162 if eventCount != 1 { 163 t.Errorf("Server event callback not called before unsubscribe") 164 } 165 srv.unsubscribe() 166 if rs.eventCb != nil { 167 t.Errorf("Server event callback not removed after unsubscribe") 168 } 169 eventCb(Event{Type: testEventType}) 170 if eventCount != 1 { 171 t.Errorf("Server event callback called after unsubscribe") 172 } 173 } 174 175 type testRequestServer struct { 176 eventCb func(Event) 177 } 178 179 func (rs *testRequestServer) Name() string { return "" } 180 func (rs *testRequestServer) Subscribe(eventCb func(Event)) { rs.eventCb = eventCb } 181 func (rs *testRequestServer) SendRequest(ID, Request) {} 182 func (rs *testRequestServer) Unsubscribe() { rs.eventCb = nil }