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 }