github.com/volts-dev/volts@v0.0.0-20240120094013-5e9c65924106/broker/http/http_test.go (about) 1 package http 2 3 import ( 4 "sync" 5 "testing" 6 "time" 7 8 "github.com/google/uuid" 9 "github.com/volts-dev/volts/broker" 10 "github.com/volts-dev/volts/registry" 11 "github.com/volts-dev/volts/registry/memory" 12 ) 13 14 var ( 15 // mock data 16 testData = map[string][]*registry.Service{ 17 "foo": { 18 { 19 Name: "foo", 20 Version: "1.0.0", 21 Nodes: []*registry.Node{ 22 { 23 Id: "foo-1.0.0-123", 24 Address: "localhost:9999", 25 }, 26 { 27 Id: "foo-1.0.0-321", 28 Address: "localhost:9999", 29 }, 30 }, 31 }, 32 { 33 Name: "foo", 34 Version: "1.0.1", 35 Nodes: []*registry.Node{ 36 { 37 Id: "foo-1.0.1-321", 38 Address: "localhost:6666", 39 }, 40 }, 41 }, 42 { 43 Name: "foo", 44 Version: "1.0.3", 45 Nodes: []*registry.Node{ 46 { 47 Id: "foo-1.0.3-345", 48 Address: "localhost:8888", 49 }, 50 }, 51 }, 52 }, 53 } 54 ) 55 56 func newTestRegistry() registry.IRegistry { 57 return memory.New(memory.Services(testData)) 58 } 59 60 func sub(be *testing.B, c int) { 61 be.StopTimer() 62 m := newTestRegistry() 63 64 b := New(broker.WithRegistry(m)) 65 topic := uuid.New().String() 66 67 if err := b.Init(); err != nil { 68 be.Errorf("Unexpected init error: %v", err) 69 } 70 71 if err := b.Start(); err != nil { 72 be.Errorf("Unexpected connect error: %v", err) 73 } 74 75 msg := &broker.Message{ 76 Header: map[string]string{ 77 "Content-Type": "application/json", 78 }, 79 Body: []byte(`{"message": "Hello World"}`), 80 } 81 82 var subs []broker.ISubscriber 83 done := make(chan bool, c) 84 85 for i := 0; i < c; i++ { 86 sub, err := b.Subscribe(topic, func(p broker.IEvent) error { 87 done <- true 88 m := p.Message() 89 90 if string(m.Body) != string(msg.Body) { 91 be.Errorf("Unexpected msg %s, expected %s", string(m.Body), string(msg.Body)) 92 } 93 94 return nil 95 }, broker.Queue("shared")) 96 if err != nil { 97 be.Errorf("Unexpected subscribe error: %v", err) 98 } 99 subs = append(subs, sub) 100 } 101 102 for i := 0; i < be.N; i++ { 103 be.StartTimer() 104 if err := b.Publish(topic, msg); err != nil { 105 be.Errorf("Unexpected publish error: %v", err) 106 } 107 <-done 108 be.StopTimer() 109 } 110 111 for _, sub := range subs { 112 sub.Unsubscribe() 113 } 114 115 if err := b.Close(); err != nil { 116 be.Errorf("Unexpected disconnect error: %v", err) 117 } 118 } 119 120 func pub(be *testing.B, c int) { 121 be.StopTimer() 122 m := newTestRegistry() 123 b := New(broker.WithRegistry(m)) 124 topic := uuid.New().String() 125 126 if err := b.Init(); err != nil { 127 be.Errorf("Unexpected init error: %v", err) 128 } 129 130 if err := b.Start(); err != nil { 131 be.Errorf("Unexpected connect error: %v", err) 132 } 133 134 msg := &broker.Message{ 135 Header: map[string]string{ 136 "Content-Type": "application/json", 137 }, 138 Body: []byte(`{"message": "Hello World"}`), 139 } 140 141 done := make(chan bool, c*4) 142 143 sub, err := b.Subscribe(topic, func(p broker.IEvent) error { 144 done <- true 145 m := p.Message() 146 if string(m.Body) != string(msg.Body) { 147 be.Errorf("Unexpected msg %s, expected %s", string(m.Body), string(msg.Body)) 148 } 149 return nil 150 }, broker.Queue("shared")) 151 if err != nil { 152 be.Errorf("Unexpected subscribe error: %v", err) 153 } 154 155 var wg sync.WaitGroup 156 ch := make(chan int, c*4) 157 be.StartTimer() 158 159 for i := 0; i < c; i++ { 160 go func() { 161 for range ch { 162 if err := b.Publish(topic, msg); err != nil { 163 be.Errorf("Unexpected publish error: %v", err) 164 } 165 select { 166 case <-done: 167 case <-time.After(time.Second): 168 } 169 wg.Done() 170 } 171 }() 172 } 173 174 for i := 0; i < be.N; i++ { 175 wg.Add(1) 176 ch <- i 177 } 178 179 wg.Wait() 180 be.StopTimer() 181 sub.Unsubscribe() 182 close(ch) 183 close(done) 184 185 if err := b.Close(); err != nil { 186 be.Errorf("Unexpected disconnect error: %v", err) 187 } 188 } 189 190 func TestBroker(t *testing.T) { 191 m := newTestRegistry() 192 b := New(broker.WithRegistry(m)) 193 194 if err := b.Init(); err != nil { 195 t.Errorf("Unexpected init error: %v", err) 196 } 197 198 if err := b.Start(); err != nil { 199 t.Errorf("Unexpected connect error: %v", err) 200 } 201 202 msg := &broker.Message{ 203 Header: map[string]string{ 204 "Content-Type": "application/json", 205 }, 206 Body: []byte(`{"message": "Hello World"}`), 207 } 208 209 done := make(chan bool) 210 211 sub, err := b.Subscribe("test", func(p broker.IEvent) error { 212 m := p.Message() 213 214 if string(m.Body) != string(msg.Body) { 215 t.Errorf("Unexpected msg %s, expected %s", string(m.Body), string(msg.Body)) 216 } 217 218 close(done) 219 return nil 220 }) 221 if err != nil { 222 t.Errorf("Unexpected subscribe error: %v", err) 223 } 224 225 if err := b.Publish("test", msg); err != nil { 226 t.Errorf("Unexpected publish error: %v", err) 227 } 228 229 <-done 230 sub.Unsubscribe() 231 232 if err := b.Close(); err != nil { 233 t.Errorf("Unexpected disconnect error: %v", err) 234 } 235 } 236 237 func TestConcurrentSubBroker(t *testing.T) { 238 m := newTestRegistry() 239 b := New(broker.WithRegistry(m)) 240 241 if err := b.Init(); err != nil { 242 t.Errorf("Unexpected init error: %v", err) 243 } 244 245 if err := b.Start(); err != nil { 246 t.Errorf("Unexpected connect error: %v", err) 247 } 248 249 msg := &broker.Message{ 250 Header: map[string]string{ 251 "Content-Type": "application/json", 252 }, 253 Body: []byte(`{"message": "Hello World"}`), 254 } 255 256 var subs []broker.ISubscriber 257 var wg sync.WaitGroup 258 259 for i := 0; i < 10; i++ { 260 sub, err := b.Subscribe("test", func(p broker.IEvent) error { 261 defer wg.Done() 262 263 m := p.Message() 264 265 if string(m.Body) != string(msg.Body) { 266 t.Errorf("Unexpected msg %s, expected %s", string(m.Body), string(msg.Body)) 267 } 268 269 return nil 270 }) 271 if err != nil { 272 t.Errorf("Unexpected subscribe error: %v", err) 273 } 274 275 wg.Add(1) 276 subs = append(subs, sub) 277 } 278 279 if err := b.Publish("test", msg); err != nil { 280 t.Errorf("Unexpected publish error: %v", err) 281 } 282 283 wg.Wait() 284 285 for _, sub := range subs { 286 sub.Unsubscribe() 287 } 288 289 if err := b.Close(); err != nil { 290 t.Errorf("Unexpected disconnect error: %v", err) 291 } 292 } 293 294 func TestConcurrentPubBroker(t *testing.T) { 295 m := newTestRegistry() 296 b := New(broker.WithRegistry(m)) 297 298 if err := b.Init(); err != nil { 299 t.Errorf("Unexpected init error: %v", err) 300 } 301 302 if err := b.Start(); err != nil { 303 t.Errorf("Unexpected connect error: %v", err) 304 } 305 306 msg := &broker.Message{ 307 Header: map[string]string{ 308 "Content-Type": "application/json", 309 }, 310 Body: []byte(`{"message": "Hello World"}`), 311 } 312 313 var wg sync.WaitGroup 314 315 sub, err := b.Subscribe("test", func(p broker.IEvent) error { 316 defer wg.Done() 317 318 m := p.Message() 319 320 if string(m.Body) != string(msg.Body) { 321 t.Errorf("Unexpected msg %s, expected %s", string(m.Body), string(msg.Body)) 322 } 323 324 return nil 325 }) 326 if err != nil { 327 t.Errorf("Unexpected subscribe error: %v", err) 328 } 329 330 for i := 0; i < 10; i++ { 331 wg.Add(1) 332 333 if err := b.Publish("test", msg); err != nil { 334 t.Errorf("Unexpected publish error: %v", err) 335 } 336 } 337 338 wg.Wait() 339 340 sub.Unsubscribe() 341 342 if err := b.Close(); err != nil { 343 t.Errorf("Unexpected disconnect error: %v", err) 344 } 345 } 346 347 func BenchmarkSub1(b *testing.B) { 348 sub(b, 1) 349 } 350 func BenchmarkSub8(b *testing.B) { 351 sub(b, 8) 352 } 353 354 func BenchmarkSub32(b *testing.B) { 355 sub(b, 32) 356 } 357 358 func BenchmarkSub64(b *testing.B) { 359 sub(b, 64) 360 } 361 362 func BenchmarkSub128(b *testing.B) { 363 sub(b, 128) 364 } 365 366 func BenchmarkPub1(b *testing.B) { 367 pub(b, 1) 368 } 369 370 func BenchmarkPub8(b *testing.B) { 371 pub(b, 8) 372 } 373 374 func BenchmarkPub32(b *testing.B) { 375 pub(b, 32) 376 } 377 378 func BenchmarkPub64(b *testing.B) { 379 pub(b, 64) 380 } 381 382 func BenchmarkPub128(b *testing.B) { 383 pub(b, 128) 384 }