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 }