github.com/wfusion/gofusion@v1.1.14/test/mq/cases/raw_test.go (about)

     1  package cases
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/suite"
    11  	"go.uber.org/atomic"
    12  
    13  	"github.com/wfusion/gofusion/common/utils"
    14  	"github.com/wfusion/gofusion/common/utils/serialize"
    15  	"github.com/wfusion/gofusion/log"
    16  	"github.com/wfusion/gofusion/mq"
    17  	"github.com/wfusion/gofusion/test/internal/mock"
    18  
    19  	fusCtx "github.com/wfusion/gofusion/context"
    20  	testMq "github.com/wfusion/gofusion/test/mq"
    21  )
    22  
    23  func TestRaw(t *testing.T) {
    24  	testingSuite := &Raw{Test: new(testMq.Test)}
    25  	testingSuite.Init(testingSuite)
    26  	suite.Run(t, testingSuite)
    27  }
    28  
    29  type Raw struct {
    30  	*testMq.Test
    31  }
    32  
    33  func (t *Raw) BeforeTest(suiteName, testName string) {
    34  	t.Catch(func() {
    35  		log.Info(context.Background(), "right before %s %s", suiteName, testName)
    36  	})
    37  }
    38  
    39  func (t *Raw) AfterTest(suiteName, testName string) {
    40  	t.Catch(func() {
    41  		ctx := context.Background()
    42  		log.Info(ctx, "right after %s %s", suiteName, testName)
    43  	})
    44  }
    45  
    46  func (t *Raw) TestRabbitmq() {
    47  	t.defaultTest(nameRawRabbitmq)
    48  }
    49  
    50  func (t *Raw) TestKafka() {
    51  	t.defaultTest(nameRawKafka)
    52  }
    53  
    54  func (t *Raw) TestPulsar() {
    55  	t.defaultTest(nameRawPulsar)
    56  }
    57  
    58  func (t *Raw) TestRedis() {
    59  	t.defaultTest(nameRawRedis)
    60  }
    61  
    62  func (t *Raw) TestMysql() {
    63  	t.defaultTest(nameRawMysql)
    64  }
    65  
    66  func (t *Raw) TestPostgres() {
    67  	t.defaultTest(nameRawPostgres)
    68  }
    69  
    70  func (t *Raw) TestGoChannel() {
    71  	t.defaultTest(nameRawGoChannel)
    72  }
    73  
    74  func (t *Raw) defaultTest(name string) {
    75  	naming := func(n string) string { return name + "_" + n }
    76  	t.Run(naming("PubSubRaw"), func() { t.testPubSubRaw(name) })
    77  	t.Run(naming("PubHandleRaw"), func() { t.testPubHandleRaw(name) })
    78  }
    79  
    80  func (t *Raw) testPubSubRaw(name string) {
    81  	t.Catch(func() {
    82  		// Given
    83  		expected := 5
    84  		cnt := atomic.NewInt64(0)
    85  		ctx := context.Background()
    86  		traceID := utils.NginxID()
    87  		ctx = fusCtx.SetTraceID(ctx, traceID)
    88  		ctx, cancel := context.WithTimeout(ctx, time.Duration(expected)*timeout)
    89  		defer func() {
    90  			time.Sleep(ackTimeout) // wait for ack
    91  			cancel()
    92  		}()
    93  
    94  		objList := mock.GenObjListBySerializeAlgo(serialize.AlgorithmJson, expected).([]*mock.CommonObj)
    95  		objMap := utils.SliceToMap(objList, func(v *mock.CommonObj) string { return v.Str })
    96  
    97  		// When
    98  		sub := mq.Sub(name, mq.AppName(t.AppName()))
    99  		msgCh, err := sub.SubscribeRaw(ctx, mq.ChannelLen(expected))
   100  		t.NoError(err)
   101  
   102  		wg := new(sync.WaitGroup)
   103  		wg.Add(1)
   104  		go func() {
   105  			defer wg.Done()
   106  			for {
   107  				select {
   108  				case msg := <-msgCh:
   109  					cnt.Add(1)
   110  					if msg == nil {
   111  						t.NotNil(msg)
   112  						break
   113  					}
   114  
   115  					ctx := msg.Context()
   116  					log.Info(ctx, "we get raw message consumed [raw_message[%s]]", msg.ID())
   117  					t.NotEmpty(msg.ID())
   118  					actual := utils.MustJsonUnmarshal[mock.CommonObj](msg.Payload())
   119  					t.EqualValues(objMap[msg.ID()], actual)
   120  					t.True(msg.Ack())
   121  
   122  					if cnt.Load() == int64(len(objList)) {
   123  						return
   124  					}
   125  
   126  				case <-ctx.Done():
   127  					return
   128  				}
   129  			}
   130  		}()
   131  
   132  		t.publishAsMessage(ctx, name, objList, wg)
   133  
   134  		// Then
   135  		wg.Wait()
   136  		t.EqualValues(len(objList), cnt.Load())
   137  	})
   138  }
   139  
   140  func (t *Raw) testPubHandleRaw(name string) {
   141  	t.Catch(func() {
   142  		// Given
   143  		expected := 5
   144  		cnt := atomic.NewInt64(0)
   145  		ctx := context.Background()
   146  		traceID := utils.NginxID()
   147  		ctx = fusCtx.SetTraceID(ctx, traceID)
   148  		ctx, cancel := context.WithTimeout(ctx, time.Duration(expected)*timeout)
   149  		defer func() {
   150  			time.Sleep(ackTimeout) // wait for ack
   151  			cancel()
   152  		}()
   153  
   154  		objList := mock.GenObjListBySerializeAlgo(serialize.AlgorithmJson, expected).([]*mock.CommonObj)
   155  		objMap := utils.SliceToMap(objList, func(v *mock.CommonObj) string { return v.Str })
   156  
   157  		// When
   158  		wg := new(sync.WaitGroup)
   159  		r := mq.Use(name, mq.AppName(t.AppName()))
   160  		r.Handle(fmt.Sprintf("%s_raw_message_handler", name), func(msg mq.Message) (err error) {
   161  			cnt.Add(1)
   162  
   163  			log.Info(msg.Context(), "we get raw message consumed [raw_message[%s]]", msg.ID())
   164  			actual := utils.MustJsonUnmarshal[mock.CommonObj](msg.Payload())
   165  			t.EqualValues(objMap[msg.ID()], actual)
   166  			return
   167  		})
   168  		r.Start()
   169  
   170  		<-r.Running()
   171  		t.publishAsMessage(ctx, name, objList, wg)
   172  
   173  		// Then
   174  		wg.Wait()
   175  	BREAKING:
   176  		for {
   177  			select {
   178  			case <-ctx.Done():
   179  				break BREAKING
   180  			default:
   181  				if cnt.Load() == int64(len(objList)) {
   182  					break BREAKING
   183  				}
   184  			}
   185  		}
   186  		t.EqualValues(len(objList), cnt.Load())
   187  	})
   188  }
   189  
   190  func (t *Raw) publishAsMessage(ctx context.Context, name string, objList []*mock.CommonObj, wg *sync.WaitGroup) {
   191  	// publisher
   192  	p := mq.Pub(name, mq.AppName(t.AppName()))
   193  
   194  	for i := 0; i < len(objList); i++ {
   195  		msg := mq.NewMessage(objList[i].Str, utils.MustJsonMarshal(objList[i]))
   196  		wg.Add(1)
   197  		go func() {
   198  			defer wg.Done()
   199  			t.NoError(p.PublishRaw(ctx, mq.Messages(msg)))
   200  		}()
   201  	}
   202  }