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  }