func TestGenerate(t *testing.T) { var ( ts compile.TypeSpec = &compile.TypedefSpec{ Name: "Timestamp", File: testdata(t, "thrift/common/bar.thrift"), Target: &compile.I64Spec{}, } ts2 compile.TypeSpec = &compile.TypedefSpec{ Name: "Timestamp", File: testdata(t, "thrift/foo.thrift"), Target: ts, } ) ts2, err := ts2.Link(compile.EmptyScope("bar")) require.NoError(t, err) ts, err = ts.Link(compile.EmptyScope("bar")) require.NoError(t, err) module := &compile.Module{ Name: "foo", ThriftPath: testdata(t, "thrift/foo.thrift"), Includes: map[string]*compile.IncludedModule{ "bar": { Name: "bar", Module: &compile.Module{ Name: "bar", ThriftPath: testdata(t, "thrift/common/bar.thrift"), Types: map[string]compile.TypeSpec{"Timestamp": ts}, }, }, }, Types: map[string]compile.TypeSpec{"Timestamp": ts2}, } tests := []struct { desc string noRecurse bool getPlugin func(*gomock.Controller) plugin.Handle wantFiles []string wantError string }{ { desc: "nil plugin; no recurse", noRecurse: true, wantFiles: []string{"foo/types.go"}, }, { desc: "nil plugin; recurse", wantFiles: []string{ "foo/types.go", "common/bar/types.go", }, }, { desc: "no service generator", getPlugin: func(mockCtrl *gomock.Controller) plugin.Handle { handle := handletest.NewMockHandle(mockCtrl) handle.EXPECT().ServiceGenerator().Return(nil) return handle }, wantFiles: []string{ "foo/types.go", "common/bar/types.go", }, }, { desc: "empty plugin", getPlugin: func(mockCtrl *gomock.Controller) plugin.Handle { return plugin.EmptyHandle }, wantFiles: []string{ "foo/types.go", "common/bar/types.go", }, }, { desc: "ServiceGenerator plugin", getPlugin: func(mockCtrl *gomock.Controller) plugin.Handle { sgen := handletest.NewMockServiceGenerator(mockCtrl) sgen.EXPECT().Generate(gomock.Any()). Return(&api.GenerateServiceResponse{ Files: map[string][]byte{ "foo.txt": []byte("hello world\n"), "bar/baz.go": []byte("package bar\n"), }, }, nil) handle := handletest.NewMockHandle(mockCtrl) handle.EXPECT().ServiceGenerator().Return(sgen) return handle }, wantFiles: []string{ "foo/types.go", "common/bar/types.go", "foo.txt", "bar/baz.go", }, }, { desc: "ServiceGenerator plugin conflict", getPlugin: func(mockCtrl *gomock.Controller) plugin.Handle { sgen := handletest.NewMockServiceGenerator(mockCtrl) sgen.EXPECT().Generate(gomock.Any()). Return(&api.GenerateServiceResponse{ Files: map[string][]byte{ "common/bar/types.go": []byte("hulk smash"), }, }, nil) handle := handletest.NewMockHandle(mockCtrl) handle.EXPECT().ServiceGenerator().Return(sgen) return handle }, wantError: `file generation conflict: multiple sources are trying to write to "common/bar/types.go"`, }, { desc: "ServiceGenerator plugin error", getPlugin: func(mockCtrl *gomock.Controller) plugin.Handle { sgen := handletest.NewMockServiceGenerator(mockCtrl) sgen.EXPECT().Generate(gomock.Any()).Return(nil, errors.New("great sadness")) handle := handletest.NewMockHandle(mockCtrl) handle.EXPECT().ServiceGenerator().Return(sgen) return handle }, wantError: `great sadness`, }, } for _, tt := range tests { func() { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() outputDir, err := ioutil.TempDir(os.TempDir(), "test-generate-recurse") require.NoError(t, err) defer os.RemoveAll(outputDir) var p plugin.Handle if tt.getPlugin != nil { p = tt.getPlugin(mockCtrl) } err = Generate(module, &Options{ OutputDir: outputDir, PackagePrefix: "go.uber.org/thriftrw/gen/testdata", ThriftRoot: testdata(t, "thrift"), Plugin: p, NoRecurse: tt.noRecurse, }) if tt.wantError != "" { assert.Contains(t, err.Error(), tt.wantError) return } if assert.NoError(t, err, tt.desc) { for _, f := range tt.wantFiles { _, err = os.Stat(filepath.Join(outputDir, f)) assert.NoError(t, err, tt.desc) } } }() } }