github.com/renbou/grpcbridge@v0.0.2-0.20240416012907-bcbd8b12648a/routing/routing_test.go (about)

     1  package routing
     2  
     3  import (
     4  	"fmt"
     5  	"math/rand"
     6  	"testing"
     7  
     8  	"github.com/renbou/grpcbridge/bridgedesc"
     9  	"github.com/renbou/grpcbridge/grpcadapter"
    10  	"go.uber.org/goleak"
    11  	"google.golang.org/protobuf/reflect/protoreflect"
    12  )
    13  
    14  // nilConnPool implements ConnPool without returning any connection for tests.
    15  type nilConnPool struct{}
    16  
    17  func (nilConnPool) Get(target string) (grpcadapter.ClientConn, bool) {
    18  	return nil, true
    19  }
    20  
    21  var testTarget = bridgedesc.Target{
    22  	Name: "routing-testsvc",
    23  	Services: []bridgedesc.Service{
    24  		{
    25  			Name: "grpcbridge.routing.v1.PureGRPCSvc",
    26  			Methods: []bridgedesc.Method{
    27  				{RPCName: "/grpcbridge.routing.v1.PureGRPCSvc/Get"},
    28  				{RPCName: "/grpcbridge.routing.v1.PureGRPCSvc/List"},
    29  			},
    30  		},
    31  		{
    32  			Name: "grpcbridge.routing.v1.RestSvc",
    33  			Methods: []bridgedesc.Method{
    34  				{
    35  					RPCName: "/grpcbridge.routing.v1.RestSvc/CreateEntity",
    36  					Bindings: []bridgedesc.Binding{
    37  						{HTTPMethod: "POST", Pattern: "/api/v1/entities"},
    38  						{HTTPMethod: "POST", Pattern: "/api/v1/entity"},
    39  					},
    40  				},
    41  				{
    42  					RPCName: "/grpcbridge.routing.v1.RestSvc/GetEntity",
    43  					Bindings: []bridgedesc.Binding{
    44  						{HTTPMethod: "GET", Pattern: "/api/v1/entity/{entity_id=*}"}, // equivalent to {entity_id}
    45  					},
    46  				},
    47  				{
    48  					RPCName: "/grpcbridge.routing.v1.RestSvc/ListEntities",
    49  					Bindings: []bridgedesc.Binding{
    50  						{HTTPMethod: "GET", Pattern: "/api/v1/entities"},
    51  					},
    52  				},
    53  				{
    54  					RPCName: "/grpcbridge.routing.v1.RestSvc/UpdateEntity",
    55  					Bindings: []bridgedesc.Binding{
    56  						{HTTPMethod: "PUT", Pattern: "/api/v1/entity/{entity_id}"},
    57  						{HTTPMethod: "PATCH", Pattern: "/api/v1/entity/{entity_id}"},
    58  					},
    59  				},
    60  				{
    61  					RPCName: "/grpcbridge.routing.v1.RestSvc/DeleteEntity",
    62  					Bindings: []bridgedesc.Binding{
    63  						{HTTPMethod: "DELETE", Pattern: "/api/v1/entity/{entity_id}"},
    64  					},
    65  				},
    66  			},
    67  		},
    68  		{
    69  			Name: "grpcbridge.routing.v2.RestSvc",
    70  			Methods: []bridgedesc.Method{
    71  				{
    72  					RPCName: "/grpcbridge.routing.v2.RestSvc/CreateEntity",
    73  					Bindings: []bridgedesc.Binding{
    74  						{HTTPMethod: "POST", Pattern: "/api/v2/entity:create"},
    75  					},
    76  				},
    77  				{
    78  					RPCName: "/grpcbridge.routing.v2.RestSvc/GetEntity",
    79  					Bindings: []bridgedesc.Binding{
    80  						{HTTPMethod: "GET", Pattern: "/api/v2/entity/{entity_id}"},
    81  					},
    82  				},
    83  				{
    84  					RPCName: "/grpcbridge.routing.v2.RestSvc/WatchEntity",
    85  					Bindings: []bridgedesc.Binding{
    86  						{HTTPMethod: "POST", Pattern: "/api/v2/entity/{entity_id}/{path=**}:watch"},
    87  						{HTTPMethod: "POST", Pattern: "/api/v2/entities/{path=all/**}:watch"},
    88  					},
    89  				},
    90  			},
    91  		},
    92  	},
    93  }
    94  
    95  type templateTargetInfo struct {
    96  	template int
    97  	name     string
    98  }
    99  
   100  func buildTemplateTargets(n int, seed int64, templates [][]bridgedesc.Target) []templateTargetInfo {
   101  	rnd := rand.New(rand.NewSource(seed))
   102  	targets := make([]templateTargetInfo, n)
   103  
   104  	for i := range targets {
   105  		targets[i] = templateTargetInfo{template: rnd.Intn(len(templates)), name: fmt.Sprintf("target_%d", i)}
   106  	}
   107  
   108  	return targets
   109  }
   110  
   111  // buildDescTemplate builds a target description from a template,
   112  // used in router tests for generating multiple different targets with unique names based on a few templates.
   113  func buildDescTemplate(template *bridgedesc.Target, dest *bridgedesc.Target, targetName string, targetIdx int) {
   114  	dest.Name = targetName
   115  	dest.Services = make([]bridgedesc.Service, len(template.Services))
   116  
   117  	for svcIdx := range template.Services {
   118  		templateSvc := &template.Services[svcIdx]
   119  		destSvc := &dest.Services[svcIdx]
   120  
   121  		destSvc.Name = protoreflect.FullName(fmt.Sprintf(string(templateSvc.Name), targetIdx))
   122  		destSvc.Methods = make([]bridgedesc.Method, len(templateSvc.Methods))
   123  
   124  		for methodIdx := range templateSvc.Methods {
   125  			templateMethod := &templateSvc.Methods[methodIdx]
   126  			destMethod := &destSvc.Methods[methodIdx]
   127  
   128  			destMethod.RPCName = fmt.Sprintf(templateMethod.RPCName, targetIdx)
   129  			destMethod.Bindings = make([]bridgedesc.Binding, len(templateMethod.Bindings))
   130  
   131  			for bindingIdx := range templateMethod.Bindings {
   132  				templateBinding := &templateMethod.Bindings[bindingIdx]
   133  				destBinding := &destMethod.Bindings[bindingIdx]
   134  
   135  				destBinding.HTTPMethod = templateBinding.HTTPMethod
   136  				destBinding.Pattern = fmt.Sprintf(templateBinding.Pattern, targetIdx)
   137  			}
   138  		}
   139  	}
   140  }
   141  
   142  func TestMain(m *testing.M) {
   143  	goleak.VerifyTestMain(m)
   144  }