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  }