Skip to content

Commit 567087a

Browse files
kevwanCopilot
andauthored
test(goctl): add regression test for per-service type alias filtering (#5481) (#5483)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 4d2e64a commit 567087a

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package generator
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"strings"
7+
"testing"
8+
9+
"github.com/emicklei/proto"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
conf "github.com/zeromicro/go-zero/tools/goctl/config"
13+
"github.com/zeromicro/go-zero/tools/goctl/rpc/parser"
14+
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
15+
)
16+
17+
// mockDirContext is a minimal DirContext for unit-testing genCallGroup.
18+
type mockDirContext struct {
19+
callDir Dir
20+
pbDir Dir
21+
protoGo Dir
22+
}
23+
24+
func (m *mockDirContext) GetCall() Dir { return m.callDir }
25+
func (m *mockDirContext) GetEtc() Dir { return Dir{} }
26+
func (m *mockDirContext) GetInternal() Dir { return Dir{} }
27+
func (m *mockDirContext) GetConfig() Dir { return Dir{} }
28+
func (m *mockDirContext) GetLogic() Dir { return Dir{} }
29+
func (m *mockDirContext) GetServer() Dir { return Dir{} }
30+
func (m *mockDirContext) GetSvc() Dir { return Dir{} }
31+
func (m *mockDirContext) GetPb() Dir { return m.pbDir }
32+
func (m *mockDirContext) GetProtoGo() Dir { return m.protoGo }
33+
func (m *mockDirContext) GetMain() Dir { return Dir{} }
34+
func (m *mockDirContext) GetServiceName() stringx.String { return stringx.From("test") }
35+
func (m *mockDirContext) SetPbDir(pbDir, grpcDir string) {}
36+
37+
// TestGenCallGroup_OnlyUsedTypesAliased verifies that in multi-service mode each
38+
// generated client file contains type aliases only for the message types actually
39+
// used by that service's RPCs (fix for issue #5481).
40+
func TestGenCallGroup_OnlyUsedTypesAliased(t *testing.T) {
41+
tmpDir := t.TempDir()
42+
callBase := filepath.Join(tmpDir, "call")
43+
pbBase := filepath.Join(tmpDir, "pb")
44+
45+
// Pre-create subdirs that genCallGroup will write into.
46+
require.NoError(t, os.MkdirAll(filepath.Join(callBase, "servicea"), 0755))
47+
require.NoError(t, os.MkdirAll(filepath.Join(callBase, "serviceb"), 0755))
48+
require.NoError(t, os.MkdirAll(pbBase, 0755))
49+
50+
mctx := &mockDirContext{
51+
callDir: Dir{
52+
Filename: callBase,
53+
Package: "example.com/multitest/call",
54+
Base: "call",
55+
GetChildPackage: func(childPath string) (string, error) {
56+
// Return a package path whose Base() is the lowercase service name.
57+
return filepath.Join(callBase, strings.ToLower(childPath)), nil
58+
},
59+
},
60+
pbDir: Dir{
61+
Filename: pbBase,
62+
Package: "example.com/multitest/pb",
63+
Base: "pb",
64+
},
65+
protoGo: Dir{
66+
// Must differ from "servicea"/"serviceb" so isCallPkgSameToPbPkg stays false
67+
// and alias generation is triggered.
68+
Filename: pbBase,
69+
Package: "example.com/multitest/pb",
70+
Base: "pb",
71+
},
72+
}
73+
74+
// Proto with two services that use completely disjoint message types.
75+
protoData := parser.Proto{
76+
Name: "multi.proto",
77+
PbPackage: "pb",
78+
Message: []parser.Message{
79+
{Message: &proto.Message{Name: "AReq"}},
80+
{Message: &proto.Message{Name: "AResp"}},
81+
{Message: &proto.Message{Name: "BReq"}},
82+
{Message: &proto.Message{Name: "BResp"}},
83+
},
84+
Service: parser.Services{
85+
{
86+
Service: &proto.Service{Name: "ServiceA"},
87+
RPC: []*parser.RPC{
88+
{RPC: &proto.RPC{Name: "DoA", RequestType: "AReq", ReturnsType: "AResp"}},
89+
},
90+
},
91+
{
92+
Service: &proto.Service{Name: "ServiceB"},
93+
RPC: []*parser.RPC{
94+
{RPC: &proto.RPC{Name: "DoB", RequestType: "BReq", ReturnsType: "BResp"}},
95+
},
96+
},
97+
},
98+
}
99+
100+
cfg, err := conf.NewConfig("")
101+
require.NoError(t, err)
102+
103+
g := NewGenerator("gozero", false)
104+
require.NoError(t, g.genCallGroup(mctx, protoData, cfg))
105+
106+
// servicea/servicea.go — aliases for AReq/AResp only
107+
aContent, err := os.ReadFile(filepath.Join(callBase, "servicea", "servicea.go"))
108+
require.NoError(t, err)
109+
aFile := string(aContent)
110+
111+
assert.Contains(t, aFile, "AReq = pb.AReq", "ServiceA file should alias AReq")
112+
assert.Contains(t, aFile, "AResp = pb.AResp", "ServiceA file should alias AResp")
113+
assert.NotContains(t, aFile, "BReq = pb.BReq", "ServiceA file must not alias BReq")
114+
assert.NotContains(t, aFile, "BResp = pb.BResp", "ServiceA file must not alias BResp")
115+
116+
// serviceb/serviceb.go — aliases for BReq/BResp only
117+
bContent, err := os.ReadFile(filepath.Join(callBase, "serviceb", "serviceb.go"))
118+
require.NoError(t, err)
119+
bFile := string(bContent)
120+
121+
assert.Contains(t, bFile, "BReq = pb.BReq", "ServiceB file should alias BReq")
122+
assert.Contains(t, bFile, "BResp = pb.BResp", "ServiceB file should alias BResp")
123+
assert.NotContains(t, bFile, "AReq = pb.AReq", "ServiceB file must not alias AReq")
124+
assert.NotContains(t, bFile, "AResp = pb.AResp", "ServiceB file must not alias AResp")
125+
}

0 commit comments

Comments
 (0)