github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/internal/gateway/tcp/gateway_test.go (about) 1 package tcpGateway_test 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 "os" 8 "testing" 9 "time" 10 11 "github.com/gobwas/ws" 12 "github.com/ronaksoft/rony" 13 tcpGateway "github.com/ronaksoft/rony/internal/gateway/tcp" 14 wsutil "github.com/ronaksoft/rony/internal/gateway/tcp/util" 15 "github.com/ronaksoft/rony/pools" 16 "github.com/ronaksoft/rony/tools" 17 . "github.com/smartystreets/goconvey/convey" 18 "github.com/valyala/fasthttp" 19 ) 20 21 /* 22 Creation Time: 2020 - Aug - 10 23 Created by: (ehsan) 24 Maintainers: 25 1. Ehsan N. Moosa (E2) 26 Auditor: Ehsan N. Moosa (E2) 27 Copyright Ronak Software Group 2020 28 */ 29 30 var ( 31 hostPort = "127.0.0.1:8080" 32 gw *tcpGateway.Gateway 33 ) 34 35 func TestMain(m *testing.M) { 36 _ = os.RemoveAll("./_hdd") 37 _ = os.MkdirAll("./_hdd", os.ModePerm) 38 39 gw = setupGateway() 40 gw.Start() 41 42 // Wait for server to come up 43 time.Sleep(time.Second * 3) 44 45 code := m.Run() 46 gw.Shutdown() 47 _ = os.RemoveAll("./_hdd") 48 os.Exit(code) 49 } 50 51 func setupGateway() *tcpGateway.Gateway { 52 //rony.SetLogLevel(log.DebugLevel) 53 gw, err := tcpGateway.New(tcpGateway.Config{ 54 Concurrency: 1000, 55 ListenAddress: hostPort, 56 MaxBodySize: 0, 57 MaxIdleTime: 0, 58 ExternalAddrs: []string{hostPort}, 59 }) 60 if err != nil { 61 panic(err) 62 } 63 64 gw.Subscribe( 65 &testGatewayDelegate{ 66 onConnectFunc: func(c rony.Conn, kvs ...*rony.KeyValue) { 67 //fmt.Println("Open", c.ClientIP()) 68 }, 69 onMessageFunc: func(c rony.Conn, streamID int64, data []byte) { 70 if len(data) > 0 && data[0] == 'S' { 71 time.Sleep(time.Duration(len(data)) * time.Second) 72 } 73 err := c.WriteBinary(streamID, data) 74 if err != nil { 75 fmt.Println("MessageHandler:", err.Error()) 76 } 77 }, 78 onClose: func(c rony.Conn) { 79 //fmt.Println("Closed", c.ClientIP()) 80 }, 81 }, 82 ) 83 84 return gw 85 } 86 87 func TestGateway(t *testing.T) { 88 Convey("Gateway Test", t, func(c C) { 89 Convey("Ping", func(c C) { 90 wsc, _, _, err := ws.Dial(context.Background(), fmt.Sprintf("ws://%s", hostPort)) 91 if err != nil { 92 c.Println(err) 93 } 94 c.So(err, ShouldBeNil) 95 for j := 0; j < 20; j++ { 96 err := wsutil.WriteMessage(wsc, ws.StateClientSide, ws.OpPing, []byte{1, 2, 3, 4}) 97 if err != nil { 98 c.Println(err) 99 } 100 c.So(err, ShouldBeNil) 101 m, err := wsutil.ReadMessage(wsc, ws.StateClientSide, nil) 102 c.So(err, ShouldBeNil) 103 c.So(m, ShouldHaveLength, 1) 104 c.So(m[0].OpCode, ShouldEqual, ws.OpPong) 105 } 106 }) 107 Convey("Websocket Parallel", func(c C) { 108 wsc, _, _, err := ws.Dial(context.Background(), fmt.Sprintf("ws://%s", hostPort)) 109 if err != nil { 110 c.Println(err) 111 } 112 c.So(err, ShouldBeNil) 113 114 err = wsutil.WriteMessage(wsc, ws.StateClientSide, ws.OpBinary, []byte{'S', 1, 2, 3, 4}) 115 c.So(err, ShouldBeNil) 116 117 wg := pools.AcquireWaitGroup() 118 119 wg.Add(1) 120 go func() { 121 for i := 0; i < 5; i++ { 122 err := wsutil.WriteMessage(wsc, ws.StateClientSide, ws.OpBinary, []byte{1, 2, 3, 4}) 123 if err != nil { 124 c.Println(err) 125 } 126 c.So(err, ShouldBeNil) 127 _, err = wsutil.ReadMessage(wsc, ws.StateClientSide, nil) 128 if err != nil { 129 c.Println(err) 130 } 131 c.So(err, ShouldBeNil) 132 } 133 wg.Done() 134 }() 135 136 wg.Wait() 137 err = wsc.Close() 138 c.So(err, ShouldBeNil) 139 }) 140 Convey("Websocket / With Normal Handler", func(c C) { 141 wg := pools.AcquireWaitGroup() 142 for i := 0; i < 50; i++ { 143 wg.Add(1) 144 go func() { 145 wsc, _, _, err := ws.Dial(context.Background(), fmt.Sprintf("ws://%s", hostPort)) 146 if err != nil { 147 c.Println(err) 148 } 149 c.So(err, ShouldBeNil) 150 for j := 0; j < 20; j++ { 151 err := wsutil.WriteMessage(wsc, ws.StateClientSide, ws.OpBinary, []byte{1, 2, 3, 4}) 152 if err != nil { 153 c.Println(err) 154 } 155 c.So(err, ShouldBeNil) 156 } 157 err = wsc.Close() 158 c.So(err, ShouldBeNil) 159 wg.Done() 160 }() 161 } 162 wg.Wait() 163 time.Sleep(time.Second) 164 }) 165 Convey("Http With Normal Handler", func(c C) { 166 wg := pools.AcquireWaitGroup() 167 wg.Add(1) 168 go func() { 169 httpc := &fasthttp.Client{} 170 for i := 0; i < 400; i++ { 171 wg.Add(1) 172 go func() { 173 req := fasthttp.AcquireRequest() 174 defer fasthttp.ReleaseRequest(req) 175 res := fasthttp.AcquireResponse() 176 defer fasthttp.ReleaseResponse(res) 177 req.SetHost(hostPort) 178 req.Header.SetMethod(http.MethodPost) 179 req.SetBody([]byte{1, 2, 3, 4}) 180 err := httpc.Do(req, res) 181 if err != nil { 182 c.Println(err) 183 } 184 c.So(err, ShouldBeNil) 185 c.So(res.Body(), ShouldResemble, []byte{1, 2, 3, 4}) 186 wg.Done() 187 }() 188 } 189 wg.Done() 190 }() 191 192 wg.Wait() 193 time.Sleep(time.Second) 194 }) 195 Convey("Http With Path", func(c C) { 196 wg := pools.AcquireWaitGroup() 197 wg.Add(1) 198 go func() { 199 httpc := &fasthttp.Client{} 200 for i := 0; i < 400; i++ { 201 wg.Add(1) 202 go func() { 203 x := tools.RandomID(10) 204 req := fasthttp.AcquireRequest() 205 defer fasthttp.ReleaseRequest(req) 206 res := fasthttp.AcquireResponse() 207 defer fasthttp.ReleaseResponse(res) 208 req.SetRequestURI(fmt.Sprintf("http://%s/x/%s", hostPort, x)) 209 req.Header.SetMethod(rony.MethodGet) 210 err := httpc.Do(req, res) 211 if err != nil { 212 c.Println(err) 213 } 214 c.So(err, ShouldBeNil) 215 wg.Done() 216 }() 217 } 218 wg.Done() 219 }() 220 221 wg.Wait() 222 time.Sleep(time.Second) 223 }) 224 }) 225 } 226 227 type testGatewayDelegate struct { 228 onConnectFunc func(c rony.Conn, kvs ...*rony.KeyValue) 229 onMessageFunc func(c rony.Conn, streamID int64, data []byte) 230 onClose func(c rony.Conn) 231 } 232 233 func (t *testGatewayDelegate) OnConnect(c rony.Conn, kvs ...*rony.KeyValue) { 234 t.onConnectFunc(c, kvs...) 235 } 236 237 func (t *testGatewayDelegate) OnMessage(c rony.Conn, streamID int64, data []byte) { 238 t.onMessageFunc(c, streamID, data) 239 } 240 241 func (t *testGatewayDelegate) OnClose(c rony.Conn) { 242 t.onClose(c) 243 } 244 245 func TestGateway2(t *testing.T) { 246 msg := []byte(tools.RandomID(1024)) 247 Convey("Gateway Test", t, func(c C) { 248 for j := 0; j < 100; j++ { 249 wsc, _, _, err := ws.Dial(context.Background(), fmt.Sprintf("ws://%s", hostPort)) 250 c.So(err, ShouldBeNil) 251 252 var m []wsutil.Message 253 for i := 0; i < 10; i++ { 254 err = wsutil.WriteMessage(wsc, ws.StateClientSide, ws.OpBinary, msg) 255 c.So(err, ShouldBeNil) 256 m, err = wsutil.ReadMessage(wsc, ws.StateClientSide, m[:0]) 257 c.So(err, ShouldBeNil) 258 c.So(m, ShouldHaveLength, 1) 259 c.So(m[0].Payload, ShouldResemble, msg) 260 } 261 262 err = wsc.Close() 263 c.So(err, ShouldBeNil) 264 } 265 }) 266 } 267 268 func BenchmarkGateway(b *testing.B) { 269 msg := []byte(tools.RandomID(1024)) 270 271 b.ReportAllocs() 272 b.ResetTimer() 273 b.SetParallelism(5) 274 b.RunParallel(func(pb *testing.PB) { 275 wsc, _, _, err := ws.Dial(context.Background(), fmt.Sprintf("ws://%s", hostPort)) 276 if err != nil { 277 panic(err) 278 } 279 280 var m []wsutil.Message 281 for pb.Next() { 282 err = wsutil.WriteMessage(wsc, ws.StateClientSide, ws.OpBinary, msg) 283 if err != nil { 284 b.Log(err) 285 } 286 m, err = wsutil.ReadMessage(wsc, ws.StateClientSide, m[:0]) 287 if err != nil { 288 b.Log(err) 289 } 290 } 291 292 _ = wsc.Close() 293 }) 294 }