fix: dead loop introduced by thrift IDL file cycle-referring (#24)
This commit is contained in:
parent
52b70ac401
commit
1f846f24bd
|
@ -1,5 +1,6 @@
|
|||
include "base.thrift"
|
||||
include "deep/deep.ref.thrift"
|
||||
include "example.thrift"
|
||||
include "ref.thrift"
|
||||
namespace go example
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
include "example.thrift"
|
||||
|
||||
namespace go ref
|
||||
|
||||
|
|
|
@ -173,23 +173,33 @@ func parseIDLContent(path, content string, includes map[string]string, isAbsIncl
|
|||
}
|
||||
_includes[k] = t
|
||||
}
|
||||
if err := parseIncludes(tree, _includes, isAbsIncludePath); err != nil {
|
||||
|
||||
done := map[string]*parser.Thrift{path: tree}
|
||||
if err := refIncludes(tree, path, done, _includes, isAbsIncludePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tree, nil
|
||||
}
|
||||
|
||||
func parseIncludes(tree *parser.Thrift, includes map[string]*parser.Thrift, isAbsIncludePath bool) error {
|
||||
func refIncludes(tree *parser.Thrift, path string, done map[string]*parser.Thrift, includes map[string]*parser.Thrift, isAbsIncludePath bool) error {
|
||||
done[path] = tree
|
||||
for _, i := range tree.Includes {
|
||||
p := i.Path
|
||||
if isAbsIncludePath {
|
||||
p = absPath(tree.Filename, i.Path)
|
||||
}
|
||||
|
||||
// check cycle reference
|
||||
if t := done[p]; t != nil {
|
||||
i.Reference = t
|
||||
continue
|
||||
}
|
||||
|
||||
ref, ok := includes[p]
|
||||
if !ok {
|
||||
return fmt.Errorf("miss include path: %s for file: %s", p, tree.Filename)
|
||||
}
|
||||
if err := parseIncludes(ref, includes, isAbsIncludePath); err != nil {
|
||||
if err := refIncludes(ref, p, done, includes, isAbsIncludePath); err != nil {
|
||||
return err
|
||||
}
|
||||
i.Reference = ref
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudwego/dynamicgo/meta"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -271,41 +270,15 @@ func TestOptionSetOptionalBitmap(t *testing.T) {
|
|||
require.Equal(t, true, req.Struct().Requires().IsSet(3))
|
||||
}
|
||||
|
||||
func TestOptionHalfParsing(t *testing.T) {
|
||||
func TestNewFunctionDescriptorFromContent_absPath(t *testing.T) {
|
||||
content := `
|
||||
include "/a/b/main.thrift"
|
||||
include "/ref.thrift"
|
||||
|
||||
namespace go kitex.test.server
|
||||
|
||||
struct Base {
|
||||
1: string DefaultField,
|
||||
2: optional string OptionalField,
|
||||
3: required string RequiredField,
|
||||
}
|
||||
|
||||
service InboxService {
|
||||
Base ExampleMethod(1: Base req)
|
||||
}
|
||||
`
|
||||
p, err := GetDescFromContent(content, "ExampleMethod", &Options{
|
||||
ParseFunctionMode: meta.ParseResponseOnly,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Nil(t, p.Request())
|
||||
require.NotNil(t, p.Response())
|
||||
|
||||
p, err = GetDescFromContent(content, "ExampleMethod", &Options{
|
||||
ParseFunctionMode: meta.ParseRequestOnly,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p.Request())
|
||||
require.Nil(t, p.Response())
|
||||
}
|
||||
|
||||
func TestNewFunctionDescriptorFromContent(t *testing.T) {
|
||||
content := `
|
||||
namespace go kitex.test.server
|
||||
|
||||
struct Base {
|
||||
1: string DefaultField,
|
||||
1: string DefaultField = ref.ConstString,
|
||||
2: optional string OptionalField,
|
||||
3: required string RequiredField,
|
||||
}
|
||||
|
@ -315,16 +288,61 @@ func TestNewFunctionDescriptorFromContent(t *testing.T) {
|
|||
Base Method2(1: Base req)
|
||||
}
|
||||
`
|
||||
path := "a/b/main.thrift"
|
||||
ref := `
|
||||
include "/a/b/main.thrift"
|
||||
|
||||
namespace go ref
|
||||
|
||||
const string ConstString = "const string"
|
||||
`
|
||||
path := "/a/b/main.thrift"
|
||||
includes := map[string]string{
|
||||
path: content,
|
||||
"/ref.thrift": ref,
|
||||
}
|
||||
|
||||
p, err := Options{}.NewDescriptorFromContentWithMethod(context.Background(), path, content, includes, false, "Method1")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p.Functions()["Method1"])
|
||||
require.Nil(t, p.Functions()["Method2"])
|
||||
}
|
||||
|
||||
func TestNewFunctionDescriptorFromContent_relativePath(t *testing.T) {
|
||||
content := `
|
||||
include "main.thrift"
|
||||
include "ref.thrift"
|
||||
|
||||
namespace go kitex.test.server
|
||||
|
||||
struct Base {
|
||||
1: string DefaultField = ref.ConstString,
|
||||
2: optional string OptionalField,
|
||||
3: required string RequiredField,
|
||||
}
|
||||
|
||||
service InboxService {
|
||||
Base Method1(1: Base req)
|
||||
Base Method2(1: Base req)
|
||||
}
|
||||
`
|
||||
ref := `
|
||||
include "/a/b/main.thrift"
|
||||
|
||||
namespace go ref
|
||||
|
||||
const string ConstString = "const string"
|
||||
`
|
||||
path := "/a/b/main.thrift"
|
||||
includes := map[string]string{
|
||||
path: content,
|
||||
"/a/b/ref.thrift": ref,
|
||||
}
|
||||
p, err := Options{}.NewDescriptorFromContentWithMethod(context.Background(), path, content, includes, true, "Method1")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p.Functions()["Method1"])
|
||||
require.Nil(t, p.Functions()["Method2"])
|
||||
}
|
||||
|
||||
func TestNewFunctionDescriptorFromPath(t *testing.T) {
|
||||
p, err := Options{}.NewDescriptorFromPathWithMethod(context.Background(), "../testdata/idl/example.thrift", nil, "ExampleMethod")
|
||||
require.NoError(t, err)
|
||||
|
|
Loading…
Reference in New Issue