You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
697 lines
17 KiB
697 lines
17 KiB
package generators |
|
|
|
import ( |
|
"reflect" |
|
"testing" |
|
|
|
"go-common/app/tool/gengo/types" |
|
) |
|
|
|
func Test_isRootedUnder(t *testing.T) { |
|
testCases := []struct { |
|
path string |
|
roots []string |
|
expect bool |
|
}{ |
|
{ |
|
path: "/foo/bar", |
|
roots: nil, |
|
expect: false, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{}, |
|
expect: false, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{ |
|
"/bad", |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{ |
|
"/foo", |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{ |
|
"/bad", |
|
"/foo", |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
path: "/foo/bar/qux/zorb", |
|
roots: []string{ |
|
"/foo/bar/qux", |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{ |
|
"/foo/bar", |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
path: "/foo/barn", |
|
roots: []string{ |
|
"/foo/bar", |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{ |
|
"/foo/barn", |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
path: "/foo/bar", |
|
roots: []string{ |
|
"", |
|
}, |
|
expect: true, |
|
}, |
|
} |
|
|
|
for i, tc := range testCases { |
|
r := isRootedUnder(tc.path, tc.roots) |
|
if r != tc.expect { |
|
t.Errorf("case[%d]: expected %t, got %t for %q in %q", i, tc.expect, r, tc.path, tc.roots) |
|
} |
|
} |
|
} |
|
|
|
func Test_deepCopyMethod(t *testing.T) { |
|
testCases := []struct { |
|
typ types.Type |
|
expect bool |
|
error bool |
|
}{ |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
// No DeepCopy method. |
|
Methods: map[string]*types.Type{}, |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// No DeepCopy method. |
|
"method": { |
|
Name: types.Name{Package: "pkgname", Name: "func()"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (no result). |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func()"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (wrong result). |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func() int"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{ |
|
{ |
|
Name: types.Name{Name: "int"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature with pointer receiver, but non-pointer result. |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func() pkgname.typename"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{ |
|
{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature with non-pointer receiver, but pointer result. |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func() pkgname.typename"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{ |
|
{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Correct signature with non-pointer receiver. |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func() pkgname.typename"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{ |
|
{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Correct signature with pointer receiver. |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func() pkgname.typename"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{ |
|
{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (has params). |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func(int) pkgname.typename"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{ |
|
{ |
|
Name: types.Name{Name: "int"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
Results: []*types.Type{ |
|
{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (extra results). |
|
"DeepCopy": { |
|
Name: types.Name{Package: "pkgname", Name: "func() (pkgname.typename, int)"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{ |
|
{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
}, |
|
{ |
|
Name: types.Name{Name: "int"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
} |
|
|
|
for i, tc := range testCases { |
|
r, err := deepCopyMethod(&tc.typ) |
|
if tc.error && err == nil { |
|
t.Errorf("case[%d]: expected an error, got none", i) |
|
} else if !tc.error && err != nil { |
|
t.Errorf("case[%d]: expected no error, got: %v", i, err) |
|
} else if !tc.error && (r != nil) != tc.expect { |
|
t.Errorf("case[%d]: expected result %v, got: %v", i, tc.expect, r) |
|
} |
|
} |
|
} |
|
|
|
func Test_deepCopyIntoMethod(t *testing.T) { |
|
testCases := []struct { |
|
typ types.Type |
|
expect bool |
|
error bool |
|
}{ |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
// No DeepCopyInto method. |
|
Methods: map[string]*types.Type{}, |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// No DeepCopyInto method. |
|
"method": { |
|
Name: types.Name{Package: "pkgname", Name: "func()"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (no parameter). |
|
"DeepCopyInto": { |
|
Name: types.Name{Package: "pkgname", Name: "func()"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (unexpected result). |
|
"DeepCopyInto": { |
|
Name: types.Name{Package: "pkgname", Name: "func(*pkgname.typename) int"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{ |
|
{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
}, |
|
Results: []*types.Type{ |
|
{ |
|
Name: types.Name{Name: "int"}, |
|
Kind: types.Builtin, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (non-pointer parameter, pointer receiver). |
|
"DeepCopyInto": { |
|
Name: types.Name{Package: "pkgname", Name: "func(pkgname.typename)"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{ |
|
{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Wrong signature (non-pointer parameter, non-pointer receiver). |
|
"DeepCopyInto": { |
|
Name: types.Name{Package: "pkgname", Name: "func(pkgname.typename)"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
Parameters: []*types.Type{ |
|
{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: false, |
|
error: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Correct signature with non-pointer receiver. |
|
"DeepCopyInto": { |
|
Name: types.Name{Package: "pkgname", Name: "func(*pkgname.typename)"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
Parameters: []*types.Type{ |
|
{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: true, |
|
}, |
|
{ |
|
typ: types.Type{ |
|
Name: types.Name{Package: "pkgname", Name: "typename"}, |
|
Kind: types.Builtin, |
|
Methods: map[string]*types.Type{ |
|
// Correct signature with pointer receiver. |
|
"DeepCopyInto": { |
|
Name: types.Name{Package: "pkgname", Name: "func(*pkgname.typename)"}, |
|
Kind: types.Func, |
|
Signature: &types.Signature{ |
|
Receiver: &types.Type{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
Parameters: []*types.Type{ |
|
{ |
|
Kind: types.Pointer, |
|
Elem: &types.Type{Kind: types.Struct, Name: types.Name{Package: "pkgname", Name: "typename"}}, |
|
}, |
|
}, |
|
Results: []*types.Type{}, |
|
}, |
|
}, |
|
}, |
|
}, |
|
expect: true, |
|
}, |
|
} |
|
|
|
for i, tc := range testCases { |
|
r, err := deepCopyIntoMethod(&tc.typ) |
|
if tc.error && err == nil { |
|
t.Errorf("case[%d]: expected an error, got none", i) |
|
} else if !tc.error && err != nil { |
|
t.Errorf("case[%d]: expected no error, got: %v", i, err) |
|
} else if !tc.error && (r != nil) != tc.expect { |
|
t.Errorf("case[%d]: expected result %v, got: %v", i, tc.expect, r) |
|
} |
|
} |
|
} |
|
|
|
func Test_extractTagParams(t *testing.T) { |
|
testCases := []struct { |
|
comments []string |
|
expect *tagValue |
|
}{ |
|
{ |
|
comments: []string{ |
|
"Human comment", |
|
}, |
|
expect: nil, |
|
}, |
|
{ |
|
comments: []string{ |
|
"Human comment", |
|
"+bili:deepcopy-gen", |
|
}, |
|
expect: &tagValue{ |
|
value: "", |
|
register: false, |
|
}, |
|
}, |
|
{ |
|
comments: []string{ |
|
"Human comment", |
|
"+bili:deepcopy-gen=package", |
|
}, |
|
expect: &tagValue{ |
|
value: "package", |
|
register: false, |
|
}, |
|
}, |
|
{ |
|
comments: []string{ |
|
"Human comment", |
|
"+bili:deepcopy-gen=package,register", |
|
}, |
|
expect: &tagValue{ |
|
value: "package", |
|
register: true, |
|
}, |
|
}, |
|
{ |
|
comments: []string{ |
|
"Human comment", |
|
"+bili:deepcopy-gen=package,register=true", |
|
}, |
|
expect: &tagValue{ |
|
value: "package", |
|
register: true, |
|
}, |
|
}, |
|
{ |
|
comments: []string{ |
|
"Human comment", |
|
"+bili:deepcopy-gen=package,register=false", |
|
}, |
|
expect: &tagValue{ |
|
value: "package", |
|
register: false, |
|
}, |
|
}, |
|
} |
|
|
|
for i, tc := range testCases { |
|
r := extractTag(tc.comments) |
|
if r == nil && tc.expect != nil { |
|
t.Errorf("case[%d]: expected non-nil", i) |
|
} |
|
if r != nil && tc.expect == nil { |
|
t.Errorf("case[%d]: expected nil, got %v", i, *r) |
|
} |
|
if r != nil && *r != *tc.expect { |
|
t.Errorf("case[%d]: expected %v, got %v", i, *tc.expect, *r) |
|
} |
|
} |
|
} |
|
|
|
func Test_extractInterfacesTag(t *testing.T) { |
|
testCases := []struct { |
|
comments []string |
|
expect []string |
|
}{ |
|
{ |
|
comments: []string{}, |
|
expect: nil, |
|
}, |
|
{ |
|
comments: []string{ |
|
"+bili:deepcopy-gen:interfaces=k8s.io/kubernetes/runtime.Object", |
|
}, |
|
expect: []string{ |
|
"k8s.io/kubernetes/runtime.Object", |
|
}, |
|
}, |
|
{ |
|
comments: []string{ |
|
"+bili:deepcopy-gen:interfaces=k8s.io/kubernetes/runtime.Object", |
|
"+bili:deepcopy-gen:interfaces=k8s.io/kubernetes/runtime.List", |
|
}, |
|
expect: []string{ |
|
"k8s.io/kubernetes/runtime.Object", |
|
"k8s.io/kubernetes/runtime.List", |
|
}, |
|
}, |
|
{ |
|
comments: []string{ |
|
"+bili:deepcopy-gen:interfaces=k8s.io/kubernetes/runtime.Object", |
|
"+bili:deepcopy-gen:interfaces=k8s.io/kubernetes/runtime.Object", |
|
}, |
|
expect: []string{ |
|
"k8s.io/kubernetes/runtime.Object", |
|
"k8s.io/kubernetes/runtime.Object", |
|
}, |
|
}, |
|
} |
|
|
|
for i, tc := range testCases { |
|
r := extractInterfacesTag(tc.comments) |
|
if r == nil && tc.expect != nil { |
|
t.Errorf("case[%d]: expected non-nil", i) |
|
} |
|
if r != nil && tc.expect == nil { |
|
t.Errorf("case[%d]: expected nil, got %v", i, r) |
|
} |
|
if r != nil && !reflect.DeepEqual(r, tc.expect) { |
|
t.Errorf("case[%d]: expected %v, got %v", i, tc.expect, r) |
|
} |
|
} |
|
}
|
|
|