func TestEmptyPlugin(t *testing.T) { transport, done := fakeEnvelopeClient() defer done() go Main(&Plugin{Name: "hello"}) client := api.NewPluginClient(multiplex.NewClient("Plugin", transport)) response, err := client.Handshake(&api.HandshakeRequest{}) require.NoError(t, err) assert.Equal(t, api.APIVersion, response.APIVersion) assert.Equal(t, "hello", response.Name) assert.Equal(t, version.Version, *response.LibraryVersion) assert.Empty(t, response.Features) assert.NoError(t, client.Goodbye()) }
func (h *transportHandle) ServiceGenerator() ServiceGenerator { if !h.Running.Load() { panic(fmt.Sprintf("handle for plugin %q has already been closed", h.name)) } if _, hasFeature := h.Features[api.FeatureServiceGenerator]; !hasFeature { return nil } return &serviceGenerator{ handle: h, Running: h.Running, ServiceGenerator: api.NewServiceGeneratorClient(multiplex.NewClient( "ServiceGenerator", envelope.NewClient(_proto, h.Transport), )), } }
func TestServiceGenerator(t *testing.T) { transport, done := fakeEnvelopeClient() defer done() mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() serviceGenerator := plugintest.NewMockServiceGenerator(mockCtrl) go Main(&Plugin{ Name: "hello", ServiceGenerator: serviceGenerator, }) pluginClient := api.NewPluginClient(multiplex.NewClient("Plugin", transport)) defer pluginClient.Goodbye() handshake, err := pluginClient.Handshake(&api.HandshakeRequest{}) require.NoError(t, err) assert.Equal(t, api.APIVersion, handshake.APIVersion) assert.Equal(t, version.Version, *handshake.LibraryVersion) assert.Equal(t, "hello", handshake.Name) assert.Contains(t, handshake.Features, api.FeatureServiceGenerator) sgClient := api.NewServiceGeneratorClient(multiplex.NewClient("ServiceGenerator", transport)) req := &api.GenerateServiceRequest{ RootServices: []api.ServiceID{1}, Services: map[api.ServiceID]*api.Service{ 1: { Name: "MyService", ThriftName: "MyService", Functions: []*api.Function{}, ParentID: (*api.ServiceID)(ptr.Int32(2)), ModuleID: 1, }, 2: { Name: "BaseService", ThriftName: "BaseService", Functions: []*api.Function{ { Name: "Healthy", ThriftName: "healthy", Arguments: []*api.Argument{}, }, }, ModuleID: 1, }, }, Modules: map[api.ModuleID]*api.Module{ 1: { ImportPath: "go.uber.org/thriftrw/plugin/fake", Directory: "fake", }, }, } res := &api.GenerateServiceResponse{ Files: map[string][]byte{ "fake/myservice/foo.go": {1, 2, 3}, "fake/baseservice/bar.go": {4, 5, 6}, "fake/baz.go": {7, 8, 9}, }, } serviceGenerator.EXPECT().Generate(req).Return(res, nil) gotRes, err := sgClient.Generate(req) if assert.NoError(t, err) { assert.Equal(t, res, gotRes) } }
// NewTransportHandle builds a new Handle which speaks to the given transport. // // If the transport is an io.Closer, it will be closed when the handle is closed. func NewTransportHandle(name string, t envelope.Transport) (Handle, error) { client := api.NewPluginClient(multiplex.NewClient( "Plugin", envelope.NewClient(_proto, t), )) handshake, err := client.Handshake(&api.HandshakeRequest{}) if err != nil { return nil, errHandshakeFailed{Name: name, Reason: err} } if handshake.Name != name { return nil, errHandshakeFailed{ Name: name, Reason: errNameMismatch{Want: name, Got: handshake.Name}, } } if handshake.APIVersion != api.APIVersion { return nil, errHandshakeFailed{ Name: name, Reason: errAPIVersionMismatch{Want: api.APIVersion, Got: handshake.APIVersion}, } } // If we got here, the API version matches so the plugin must have // provided the Version if handshake.LibraryVersion == nil { return nil, errHandshakeFailed{ Name: name, Reason: errVersionIsRequired, } } version, err := semver.Parse(*handshake.LibraryVersion) if err != nil { return nil, errHandshakeFailed{Name: name, Reason: err} } if !compatRange.Contains(version) { return nil, errHandshakeFailed{ Name: name, Reason: errVersionMismatch{ Want: compatRange, Got: *handshake.LibraryVersion, }, } } features := make(map[api.Feature]struct{}, len(handshake.Features)) for _, feature := range handshake.Features { features[feature] = struct{}{} } return &transportHandle{ name: name, Transport: t, Client: client, Running: atomic.NewBool(true), Features: features, }, nil }