---- 测试:并发 Call ----
(t *testing.T)
| 281 | // ---- 测试:并发 Call ---- |
| 282 | |
| 283 | func TestCall_Concurrent(t *testing.T) { |
| 284 | hub := New(Options{PeerExtractor: mdPeerExtractor}) |
| 285 | env := newTestEnv(t, hub) |
| 286 | cc := env.dial(t) |
| 287 | mock := startNodeMock(t, cc, "n") |
| 288 | waitOnline(t, hub, "n") |
| 289 | |
| 290 | mock.handle("echo", func(reqID string, body []byte) (bool, []byte, string) { |
| 291 | return true, body, "" |
| 292 | }) |
| 293 | |
| 294 | const N = 100 |
| 295 | var wg sync.WaitGroup |
| 296 | wg.Add(N) |
| 297 | errs := make(chan error, N) |
| 298 | for i := 0; i < N; i++ { |
| 299 | i := i |
| 300 | go func() { |
| 301 | defer wg.Done() |
| 302 | payload, _ := json.Marshal(map[string]int{"i": i}) |
| 303 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
| 304 | defer cancel() |
| 305 | raw, err := hub.Call(ctx, "n", "echo", json.RawMessage(payload)) |
| 306 | if err != nil { |
| 307 | errs <- fmt.Errorf("call %d: %w", i, err) |
| 308 | return |
| 309 | } |
| 310 | // raw 是 node 把 body 原样回的字节;但我们把 RawMessage 序列化时 |
| 311 | // 会被双重编码,所以这里只校验非空与可解析。 |
| 312 | if len(raw) == 0 { |
| 313 | errs <- fmt.Errorf("call %d: empty body", i) |
| 314 | } |
| 315 | }() |
| 316 | } |
| 317 | wg.Wait() |
| 318 | close(errs) |
| 319 | for err := range errs { |
| 320 | t.Error(err) |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | // ---- 测试:重连踢旧连接 ---- |
| 325 |
nothing calls this directly
no test coverage detected