github.com/emcfarlane/larking@v0.0.0-20220605172417-1704b45ee6c3/proxy_test.go (about)

     1  // Copyright 2021 Edward McFarlane. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package larking
     6  
     7  import (
     8  	"context"
     9  	"net"
    10  	"testing"
    11  
    12  	"github.com/google/go-cmp/cmp"
    13  	"google.golang.org/genproto/googleapis/api/httpbody"
    14  	"google.golang.org/grpc"
    15  	"google.golang.org/grpc/credentials/insecure"
    16  	"google.golang.org/grpc/metadata"
    17  	"google.golang.org/grpc/reflection"
    18  	"google.golang.org/protobuf/proto"
    19  	"google.golang.org/protobuf/testing/protocmp"
    20  
    21  	"github.com/emcfarlane/larking/testpb"
    22  	"golang.org/x/sync/errgroup"
    23  )
    24  
    25  func TestGRPCProxy(t *testing.T) {
    26  	// Create test server.
    27  	ms := &testpb.UnimplementedMessagingServer{}
    28  	fs := &testpb.UnimplementedFilesServer{}
    29  
    30  	o := &overrides{}
    31  	gs := grpc.NewServer(o.streamOption(), o.unaryOption())
    32  	testpb.RegisterMessagingServer(gs, ms)
    33  	testpb.RegisterFilesServer(gs, fs)
    34  	reflection.Register(gs)
    35  
    36  	lis, err := net.Listen("tcp", "localhost:0")
    37  	if err != nil {
    38  		t.Fatalf("failed to listen: %v", err)
    39  	}
    40  	defer lis.Close()
    41  
    42  	var g errgroup.Group
    43  	defer func() {
    44  		if err := g.Wait(); err != nil {
    45  			t.Fatal(err)
    46  		}
    47  	}()
    48  
    49  	g.Go(func() error {
    50  		return gs.Serve(lis)
    51  	})
    52  	defer gs.Stop()
    53  
    54  	// Create the client.
    55  	conn, err := grpc.Dial(
    56  		lis.Addr().String(),
    57  		grpc.WithTransportCredentials(insecure.NewCredentials()),
    58  	)
    59  	if err != nil {
    60  		t.Fatalf("cannot connect to server: %v", err)
    61  	}
    62  	defer conn.Close()
    63  
    64  	h, err := NewMux()
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  	if err := h.RegisterConn(context.Background(), conn); err != nil {
    69  		t.Fatal(err)
    70  	}
    71  
    72  	lisProxy, err := net.Listen("tcp", "localhost:0")
    73  	if err != nil {
    74  		t.Fatalf("failed to listen: %v", err)
    75  	}
    76  	defer lisProxy.Close()
    77  
    78  	ts := grpc.NewServer(
    79  		grpc.UnknownServiceHandler(h.StreamHandler()),
    80  	)
    81  
    82  	g.Go(func() error {
    83  		return ts.Serve(lisProxy)
    84  	})
    85  	defer ts.Stop()
    86  
    87  	cc, err := grpc.Dial(
    88  		lisProxy.Addr().String(),
    89  		//grpc.WithTransportCredentials(
    90  		//	credentials.NewTLS(transport.TLSClientConfig),
    91  		//),
    92  		grpc.WithTransportCredentials(insecure.NewCredentials()),
    93  	)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	cmpOpts := cmp.Options{protocmp.Transform()}
    99  
   100  	var unaryStreamDesc = &grpc.StreamDesc{
   101  		ClientStreams: false,
   102  		ServerStreams: false,
   103  	}
   104  
   105  	tests := []struct {
   106  		name   string
   107  		desc   *grpc.StreamDesc
   108  		method string
   109  		inouts []interface{}
   110  	}{{
   111  		name:   "unary_message",
   112  		desc:   unaryStreamDesc,
   113  		method: "/larking.testpb.Messaging/GetMessageOne",
   114  		inouts: []interface{}{in{
   115  			msg: &testpb.GetMessageRequestOne{Name: "proxy"},
   116  		}, out{
   117  			msg: &testpb.Message{Text: "success"},
   118  		}},
   119  	}, {
   120  		name: "stream_file",
   121  		desc: &grpc.StreamDesc{
   122  			ClientStreams: true,
   123  			ServerStreams: true,
   124  		},
   125  		method: "/larking.testpb.Files/LargeUploadDownload",
   126  		inouts: []interface{}{in{
   127  			method: "/larking.testpb.Files/LargeUploadDownload",
   128  			msg: &testpb.UploadFileRequest{
   129  				Filename: "cat.jpg",
   130  				File: &httpbody.HttpBody{
   131  					ContentType: "jpg",
   132  					Data:        []byte("cat"),
   133  				},
   134  			},
   135  		}, in{
   136  			msg: &testpb.UploadFileRequest{
   137  				File: &httpbody.HttpBody{
   138  					Data: []byte("dog"),
   139  				},
   140  			},
   141  		}, out{
   142  			msg: &httpbody.HttpBody{
   143  				Data: []byte("cat"),
   144  			},
   145  		}, out{
   146  			msg: &httpbody.HttpBody{
   147  				Data: []byte("dog"),
   148  			},
   149  		}},
   150  	}}
   151  
   152  	for _, tt := range tests {
   153  		t.Run(tt.name, func(t *testing.T) {
   154  			o.reset(t, "test", tt.inouts)
   155  
   156  			ctx := context.Background()
   157  			ctx = metadata.AppendToOutgoingContext(ctx, "test", tt.method)
   158  
   159  			s, err := cc.NewStream(ctx, tt.desc, tt.method)
   160  			if err != nil {
   161  				t.Fatal(err)
   162  			}
   163  
   164  			for i := 0; i < len(tt.inouts); i++ {
   165  				switch typ := tt.inouts[i].(type) {
   166  				case in:
   167  					if err := s.SendMsg(typ.msg); err != nil {
   168  						t.Fatal(err)
   169  					}
   170  				case out:
   171  					out := proto.Clone(typ.msg)
   172  					if err := s.RecvMsg(out); err != nil {
   173  						t.Fatal(err)
   174  					}
   175  					diff := cmp.Diff(out, typ.msg, cmpOpts...)
   176  					if diff != "" {
   177  						t.Fatal(diff)
   178  					}
   179  				}
   180  			}
   181  		})
   182  	}
   183  }