github.com/cmd-stream/base-go@v0.0.0-20230813145615-dd6ac24c16f5/server/worker_test.go (about)

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net"
     7  	"sync"
     8  	"testing"
     9  
    10  	"github.com/cmd-stream/base-go/testdata/mock"
    11  	"github.com/ymz-ncnk/mok"
    12  )
    13  
    14  func TestWorker(t *testing.T) {
    15  
    16  	addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9000}
    17  
    18  	t.Run("Worker should be able to handle several conns with LostConnCallback",
    19  		func(t *testing.T) {
    20  			var (
    21  				wantErr  = errors.New("handle conn failed")
    22  				wg       = &sync.WaitGroup{}
    23  				conn1    = MakeConn(addr)
    24  				conn2    = MakeConn(addr)
    25  				delegate = mock.NewServerDelegate().RegisterHandle(
    26  					func(ctx context.Context, conn net.Conn) (err error) {
    27  						if conn != conn1 {
    28  							t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
    29  						}
    30  						return wantErr
    31  					},
    32  				).RegisterHandle(
    33  					func(ctx context.Context, conn net.Conn) (err error) {
    34  						if conn != conn2 {
    35  							t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
    36  						}
    37  						return wantErr
    38  					},
    39  				)
    40  				lostConnCallback = func(addr net.Addr, err error) {
    41  					defer wg.Done()
    42  					if err != wantErr {
    43  						t.Errorf("unexpected error, want '%v' actual '%v'", wantErr, err)
    44  					}
    45  				}
    46  			)
    47  			testWorker(delegate, conn1, conn2, lostConnCallback, wg, t)
    48  		})
    49  
    50  	t.Run("Worker should be able to handle several conns without LostConnCallback",
    51  		func(t *testing.T) {
    52  			var (
    53  				wantErr  = errors.New("handle conn failed")
    54  				wg       = &sync.WaitGroup{}
    55  				conn1    = mock.NewConn()
    56  				conn2    = mock.NewConn()
    57  				delegate = mock.NewServerDelegate().RegisterHandle(
    58  					func(ctx context.Context, conn net.Conn) (err error) {
    59  						defer wg.Done()
    60  						if conn != conn1 {
    61  							t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
    62  						}
    63  						return wantErr
    64  					},
    65  				).RegisterHandle(
    66  					func(ctx context.Context, conn net.Conn) (err error) {
    67  						defer wg.Done()
    68  						if conn != conn2 {
    69  							t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
    70  						}
    71  						return wantErr
    72  					},
    73  				)
    74  			)
    75  			testWorker(delegate, conn1, conn2, nil, wg, t)
    76  		},
    77  	)
    78  
    79  	// t.Run("Handle two connections", func(t *testing.T) {
    80  	// 	// addr := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9000}
    81  
    82  	// 	// t.Run("With LostConnCallback", func(t *testing.T) {
    83  	// 	// 	var (
    84  	// 	// 		wantErr  = errors.New("handle conn failed")
    85  	// 	// 		wg       = &sync.WaitGroup{}
    86  	// 	// 		conn1    = MakeConn(addr)
    87  	// 	// 		conn2    = MakeConn(addr)
    88  	// 	// 		delegate = mock.NewServerDelegate().RegisterHandle(
    89  	// 	// 			func(ctx context.Context, conn net.Conn) (err error) {
    90  	// 	// 				if conn != conn1 {
    91  	// 	// 					t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
    92  	// 	// 				}
    93  	// 	// 				return wantErr
    94  	// 	// 			},
    95  	// 	// 		).RegisterHandle(
    96  	// 	// 			func(ctx context.Context, conn net.Conn) (err error) {
    97  	// 	// 				if conn != conn2 {
    98  	// 	// 					t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
    99  	// 	// 				}
   100  	// 	// 				return wantErr
   101  	// 	// 			},
   102  	// 	// 		)
   103  	// 	// 		lostConnCallback = func(addr net.Addr, err error) {
   104  	// 	// 			defer wg.Done()
   105  	// 	// 			if err != wantErr {
   106  	// 	// 				t.Errorf("unexpected error, want '%v' actual '%v'", wantErr, err)
   107  	// 	// 			}
   108  	// 	// 		}
   109  	// 	// 	)
   110  	// 	// 	testWorker(delegate, conn1, conn2, lostConnCallback, wg, t)
   111  	// 	// })
   112  
   113  	// 	// t.Run("Without LostConnCallback", func(t *testing.T) {
   114  	// 	// 	var (
   115  	// 	// 		wantErr  = errors.New("handle conn failed")
   116  	// 	// 		wg       = &sync.WaitGroup{}
   117  	// 	// 		conn1    = mock.NewConn()
   118  	// 	// 		conn2    = mock.NewConn()
   119  	// 	// 		delegate = mock.NewServerDelegate().RegisterHandle(
   120  	// 	// 			func(ctx context.Context, conn net.Conn) (err error) {
   121  	// 	// 				defer wg.Done()
   122  	// 	// 				if conn != conn1 {
   123  	// 	// 					t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
   124  	// 	// 				}
   125  	// 	// 				return wantErr
   126  	// 	// 			},
   127  	// 	// 		).RegisterHandle(
   128  	// 	// 			func(ctx context.Context, conn net.Conn) (err error) {
   129  	// 	// 				defer wg.Done()
   130  	// 	// 				if conn != conn2 {
   131  	// 	// 					t.Errorf("unexpected conn, want '%v' actual '%v'", conn1, conn)
   132  	// 	// 				}
   133  	// 	// 				return wantErr
   134  	// 	// 			},
   135  	// 	// 		)
   136  	// 	// 	)
   137  	// 	// 	testWorker(delegate, conn1, conn2, nil, wg, t)
   138  	// 	// })
   139  	// })
   140  
   141  	t.Run("We should be able to close the worker", func(t *testing.T) {
   142  		var (
   143  			wantErr  = ErrClosed
   144  			conns    = make(chan net.Conn)
   145  			delegate = mock.NewServerDelegate()
   146  			mocks    = []*mok.Mock{delegate.Mock}
   147  			worker   = NewWorker(conns, delegate, nil)
   148  		)
   149  		errs := RunWorker(worker)
   150  		if err := worker.Stop(); err != nil {
   151  			t.Fatal(err)
   152  		}
   153  		testAsyncErr(wantErr, errs, mocks, t)
   154  	})
   155  
   156  	t.Run("We should be able to shutdown the worker", func(t *testing.T) {
   157  		var (
   158  			wantErr  error = nil
   159  			conns          = make(chan net.Conn)
   160  			delegate       = mock.NewServerDelegate()
   161  			mocks          = []*mok.Mock{delegate.Mock}
   162  			worker         = NewWorker(conns, delegate, nil)
   163  		)
   164  		errs := RunWorker(worker)
   165  		close(conns)
   166  		testAsyncErr(wantErr, errs, mocks, t)
   167  	})
   168  
   169  }
   170  
   171  func RunWorker(worker Worker) (errs chan error) {
   172  	errs = make(chan error, 1)
   173  	go func() {
   174  		err := worker.Run()
   175  		errs <- err
   176  		close(errs)
   177  	}()
   178  	return errs
   179  }
   180  
   181  func testWorker(delegate mock.ServerDelegate, conn1, conn2 mock.Conn,
   182  	lostConnCallback LostConnCallback,
   183  	wg *sync.WaitGroup,
   184  	t *testing.T,
   185  ) {
   186  	var (
   187  		conns  = make(chan net.Conn)
   188  		worker = NewWorker(conns, delegate, lostConnCallback)
   189  		mocks  = []*mok.Mock{conn1.Mock, conn2.Mock, delegate.Mock}
   190  		errs   = RunWorker(worker)
   191  	)
   192  
   193  	wg.Add(2)
   194  	conns <- conn1
   195  	conns <- conn2
   196  	wg.Wait()
   197  
   198  	err := worker.Stop()
   199  	if err != nil {
   200  		t.Fatal(err)
   201  	}
   202  	testAsyncErr(ErrClosed, errs, mocks, t)
   203  }