github.com/Goboolean/common@v0.0.0-20231130153141-cb54596b217d/pkg/kafka/consumer_test.go (about)

     1  package kafka_test
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	model_latest "github.com/Goboolean/common/api/kafka/model.latest"
    10  	"github.com/Goboolean/common/pkg/kafka"
    11  	"github.com/Goboolean/common/pkg/resolver"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  type SubscribeListenerImpl struct {
    16  	channel chan *model_latest.Event
    17  }
    18  
    19  func newSubscribeListenerImpl(ch chan *model_latest.Event) *SubscribeListenerImpl {
    20  	return &SubscribeListenerImpl{
    21  		channel: ch,
    22  	}
    23  }
    24  
    25  func (s *SubscribeListenerImpl) OnReceiveMessage(ctx context.Context, msg *model_latest.Event) error {
    26  	s.channel <- msg
    27  	return nil
    28  }
    29  
    30  func SetupConsumer(ch chan *model_latest.Event) *kafka.Consumer[*model_latest.Event] {
    31  
    32  	c, err := kafka.NewConsumer[*model_latest.Event](&resolver.ConfigMap{
    33  		"BOOTSTRAP_HOST":  os.Getenv("KAFKA_BOOTSTRAP_HOST"),
    34  		"GROUP_ID":        "TEST_GROUP",
    35  		"PROCESSOR_COUNT": 2,
    36  	}, newSubscribeListenerImpl(ch))
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  	return c
    41  }
    42  
    43  func SetupConsumerWithRegistry(ch chan *model_latest.Event) *kafka.Consumer[*model_latest.Event] {
    44  
    45  	c, err := kafka.NewConsumer[*model_latest.Event](&resolver.ConfigMap{
    46  		"BOOTSTRAP_HOST":  os.Getenv("KAFKA_BOOTSTRAP_HOST"),
    47  		"REGISTRY_HOST":   os.Getenv("KAFKA_REGISTRY_HOST"),
    48  		"GROUP_ID":        "TEST_GROUP",
    49  		"PROCESSOR_COUNT": 2,
    50  	}, newSubscribeListenerImpl(ch))
    51  	if err != nil {
    52  		panic(err)
    53  	}
    54  	return c
    55  }
    56  
    57  func SetupConsumerWithGroup(ch chan *model_latest.Event, group string) *kafka.Consumer[*model_latest.Event] {
    58  
    59  	c, err := kafka.NewConsumer[*model_latest.Event](&resolver.ConfigMap{
    60  		"BOOTSTRAP_HOST":  os.Getenv("KAFKA_BOOTSTRAP_HOST"),
    61  		"GROUP_ID":        group,
    62  		"PROCESSOR_COUNT": 2,
    63  	}, newSubscribeListenerImpl(ch))
    64  	if err != nil {
    65  		panic(err)
    66  	}
    67  	return c
    68  }
    69  
    70  func TeardownConsumer(c *kafka.Consumer[*model_latest.Event]) {
    71  	mutex.Lock()
    72  	defer mutex.Unlock()
    73  	c.Close()
    74  }
    75  
    76  func Test_Consumer(t *testing.T) {
    77  
    78  	const topic = "test-consumer"
    79  	var event = &model_latest.Event{
    80  		EventUuid: "test-uuid",
    81  	}
    82  
    83  	var channel = make(chan *model_latest.Event, 10)
    84  
    85  	c := SetupConsumer(channel)
    86  	defer TeardownConsumer(c)
    87  	p := SetupProducer()
    88  	defer TeardownProducer(p)
    89  
    90  	t.Run("Ping", func(t *testing.T) {
    91  		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    92  		defer cancel()
    93  
    94  		err := c.Ping(ctx)
    95  		assert.NoError(t, err)
    96  	})
    97  
    98  	t.Run("Subscribe", func(t *testing.T) {
    99  		err := c.Subscribe(topic, event.ProtoReflect().Type())
   100  		assert.NoError(t, err)
   101  	})
   102  
   103  	t.Run("ConsumeMessage", func(t *testing.T) {
   104  		err := p.Produce(topic, event)
   105  		assert.NoError(t, err)
   106  
   107  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*7)
   108  		defer cancel()
   109  
   110  		select {
   111  		case <-ctx.Done():
   112  			assert.Fail(t, "failed to receive all message before timeout")
   113  			return
   114  		case <-channel:
   115  			break
   116  		}
   117  	})
   118  }
   119  
   120  func Test_ConsumerWithRegistry(t *testing.T) {
   121  	t.Skip("Skip this test because of the registry is not ready.")
   122  
   123  	const topic = "test-consumer-with-registry"
   124  	var event = &model_latest.Event{}
   125  
   126  	var channel = make(chan *model_latest.Event, 10)
   127  
   128  	c := SetupConsumer(channel)
   129  	defer TeardownConsumer(c)
   130  	p := SetupProducer()
   131  	defer TeardownProducer(p)
   132  
   133  	t.Run("Ping", func(t *testing.T) {
   134  		ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   135  		defer cancel()
   136  
   137  		err := c.Ping(ctx)
   138  		assert.NoError(t, err)
   139  	})
   140  
   141  	t.Run("Subscribe", func(t *testing.T) {
   142  		err := c.Subscribe(topic, event.ProtoReflect().Type())
   143  		assert.NoError(t, err)
   144  	})
   145  
   146  	t.Run("ConsumeMessage", func(t *testing.T) {
   147  		_, err := p.Register(topic, event)
   148  		assert.NoError(t, err)
   149  
   150  		err = p.Produce(topic, event)
   151  		assert.NoError(t, err)
   152  
   153  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
   154  		defer cancel()
   155  
   156  		select {
   157  		case <-ctx.Done():
   158  			assert.Fail(t, "failed to receive all message before timeout")
   159  			return
   160  		case <-channel:
   161  			break
   162  		}
   163  	})
   164  }
   165  
   166  func Test_ConsumeSameGroup(t *testing.T) {
   167  
   168  	const topic = "test-consumer-same-group"
   169  	const count = 3
   170  	var event = &model_latest.Event{EventUuid: "test-uuid"}
   171  
   172  	var ch1 = make(chan *model_latest.Event, 10)
   173  	var ch2 = make(chan *model_latest.Event, 10)
   174  
   175  	c1 := SetupConsumerWithGroup(ch1, "TEST_GROUP")
   176  	defer TeardownConsumer(c1)
   177  	c2 := SetupConsumerWithGroup(ch2, "TEST_GROUP")
   178  	defer TeardownConsumer(c2)
   179  
   180  	p := SetupProducer()
   181  	defer TeardownProducer(p)
   182  
   183  	t.Run("Subscribe", func(t *testing.T) {
   184  		err := c1.Subscribe(topic, event.ProtoReflect().Type())
   185  		assert.NoError(t, err)
   186  
   187  		err = c2.Subscribe(topic, event.ProtoReflect().Type())
   188  		assert.NoError(t, err)
   189  	})
   190  
   191  	t.Run("ConsumeMessage", func(t *testing.T) {
   192  		for i := 0; i < count; i++ {
   193  			err := p.Produce(topic, event)
   194  			assert.NoError(t, err)
   195  		}
   196  
   197  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
   198  		defer cancel()
   199  
   200  		<-ctx.Done()
   201  		assert.Equal(t, count, len(ch1)+len(ch2))
   202  	})
   203  }
   204  
   205  func Test_ConsumeDifferentGroup(t *testing.T) {
   206  
   207  	const topic = "test-consumer-different-group"
   208  	const count = 3
   209  	var event = &model_latest.Event{EventUuid: "test-uuid"}
   210  
   211  	var ch_a = make(chan *model_latest.Event, 10)
   212  	var ch_b = make(chan *model_latest.Event, 10)
   213  
   214  	c_a := SetupConsumerWithGroup(ch_a, "TEST_GROUP_A")
   215  	defer TeardownConsumer(c_a)
   216  	c_b := SetupConsumerWithGroup(ch_b, "TEST_GROUP_B")
   217  	defer TeardownConsumer(c_b)
   218  
   219  	p := SetupProducer()
   220  	defer TeardownProducer(p)
   221  
   222  	t.Run("Subscribe", func(t *testing.T) {
   223  		err := c_a.Subscribe(topic, event.ProtoReflect().Type())
   224  		assert.NoError(t, err)
   225  
   226  		err = c_b.Subscribe(topic, event.ProtoReflect().Type())
   227  		assert.NoError(t, err)
   228  	})
   229  
   230  	t.Run("ConsumeMessage", func(t *testing.T) {
   231  		for i := 0; i < count; i++ {
   232  			err := p.Produce(topic, event)
   233  			assert.NoError(t, err)
   234  		}
   235  
   236  		ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
   237  		defer cancel()
   238  
   239  		<-ctx.Done()
   240  		assert.Equal(t, count, len(ch_a))
   241  		assert.Equal(t, count, len(ch_b))
   242  	})
   243  }