mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-07 15:10:01 +08:00
131 lines
4.7 KiB
Go
131 lines
4.7 KiB
Go
package generator
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/emicklei/proto"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
conf "github.com/zeromicro/go-zero/tools/goctl/config"
|
|
"github.com/zeromicro/go-zero/tools/goctl/rpc/parser"
|
|
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
|
|
)
|
|
|
|
// mockDirContext is a minimal DirContext for unit-testing genCallGroup.
|
|
type mockDirContext struct {
|
|
callDir Dir
|
|
pbDir Dir
|
|
protoGo Dir
|
|
}
|
|
|
|
func (m *mockDirContext) GetCall() Dir { return m.callDir }
|
|
func (m *mockDirContext) GetEtc() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetInternal() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetConfig() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetLogic() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetServer() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetSvc() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetPb() Dir { return m.pbDir }
|
|
func (m *mockDirContext) GetProtoGo() Dir { return m.protoGo }
|
|
func (m *mockDirContext) GetMain() Dir { return Dir{} }
|
|
func (m *mockDirContext) GetServiceName() stringx.String { return stringx.From("test") }
|
|
func (m *mockDirContext) SetPbDir(pbDir, grpcDir string) {}
|
|
|
|
// TestGenCallGroup_OnlyUsedTypesAliased verifies that in multi-service mode each
|
|
// generated client file contains type aliases only for the message types actually
|
|
// used by that service's RPCs (fix for issue #5481).
|
|
func TestGenCallGroup_OnlyUsedTypesAliased(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
callBase := filepath.Join(tmpDir, "call")
|
|
pbBase := filepath.Join(tmpDir, "pb")
|
|
|
|
// Pre-create subdirs that genCallGroup will write into.
|
|
require.NoError(t, os.MkdirAll(filepath.Join(callBase, "servicea"), 0755))
|
|
require.NoError(t, os.MkdirAll(filepath.Join(callBase, "serviceb"), 0755))
|
|
require.NoError(t, os.MkdirAll(pbBase, 0755))
|
|
|
|
mctx := &mockDirContext{
|
|
callDir: Dir{
|
|
Filename: callBase,
|
|
Package: "example.com/multitest/call",
|
|
Base: "call",
|
|
GetChildPackage: func(childPath string) (string, error) {
|
|
// Return a package path whose Base() is the lowercase service name.
|
|
return filepath.Join(callBase, strings.ToLower(childPath)), nil
|
|
},
|
|
},
|
|
pbDir: Dir{
|
|
Filename: pbBase,
|
|
Package: "example.com/multitest/pb",
|
|
Base: "pb",
|
|
},
|
|
protoGo: Dir{
|
|
// Must differ from "servicea"/"serviceb" so isCallPkgSameToPbPkg stays false
|
|
// and alias generation is triggered.
|
|
Filename: pbBase,
|
|
Package: "example.com/multitest/pb",
|
|
Base: "pb",
|
|
},
|
|
}
|
|
|
|
// Proto with two services that use completely disjoint message types.
|
|
protoData := parser.Proto{
|
|
Name: "multi.proto",
|
|
PbPackage: "pb",
|
|
Message: []parser.Message{
|
|
{Message: &proto.Message{Name: "AReq"}},
|
|
{Message: &proto.Message{Name: "AResp"}},
|
|
{Message: &proto.Message{Name: "BReq"}},
|
|
{Message: &proto.Message{Name: "BResp"}},
|
|
},
|
|
Service: parser.Services{
|
|
{
|
|
Service: &proto.Service{Name: "ServiceA"},
|
|
RPC: []*parser.RPC{
|
|
{RPC: &proto.RPC{Name: "DoA", RequestType: "AReq", ReturnsType: "AResp"}},
|
|
},
|
|
},
|
|
{
|
|
Service: &proto.Service{Name: "ServiceB"},
|
|
RPC: []*parser.RPC{
|
|
{RPC: &proto.RPC{Name: "DoB", RequestType: "BReq", ReturnsType: "BResp"}},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
cfg, err := conf.NewConfig("")
|
|
require.NoError(t, err)
|
|
|
|
g := NewGenerator("gozero", false)
|
|
require.NoError(t, g.genCallGroup(mctx, protoData, cfg))
|
|
|
|
// servicea/servicea.go — aliases for AReq/AResp only
|
|
aContent, err := os.ReadFile(filepath.Join(callBase, "servicea", "servicea.go"))
|
|
require.NoError(t, err)
|
|
aFile := normalizeWS(string(aContent))
|
|
|
|
assert.Contains(t, aFile, "AReq = pb.AReq", "ServiceA file should alias AReq")
|
|
assert.Contains(t, aFile, "AResp = pb.AResp", "ServiceA file should alias AResp")
|
|
assert.NotContains(t, aFile, "BReq = pb.BReq", "ServiceA file must not alias BReq")
|
|
assert.NotContains(t, aFile, "BResp = pb.BResp", "ServiceA file must not alias BResp")
|
|
|
|
// serviceb/serviceb.go — aliases for BReq/BResp only
|
|
bContent, err := os.ReadFile(filepath.Join(callBase, "serviceb", "serviceb.go"))
|
|
require.NoError(t, err)
|
|
bFile := normalizeWS(string(bContent))
|
|
|
|
assert.Contains(t, bFile, "BReq = pb.BReq", "ServiceB file should alias BReq")
|
|
assert.Contains(t, bFile, "BResp = pb.BResp", "ServiceB file should alias BResp")
|
|
assert.NotContains(t, bFile, "AReq = pb.AReq", "ServiceB file must not alias AReq")
|
|
assert.NotContains(t, bFile, "AResp = pb.AResp", "ServiceB file must not alias AResp")
|
|
}
|
|
|
|
// normalizeWS replaces runs of whitespace with a single space.
|
|
func normalizeWS(s string) string {
|
|
return strings.Join(strings.Fields(strings.ReplaceAll(s, "\n", " \n ")), " ")
|
|
}
|