1package pgs
2
3import (
4	"errors"
5	"testing"
6
7	"github.com/golang/protobuf/proto"
8	"github.com/golang/protobuf/protoc-gen-go/descriptor"
9	"github.com/stretchr/testify/assert"
10)
11
12func TestField_Name(t *testing.T) {
13	t.Parallel()
14
15	f := &field{desc: &descriptor.FieldDescriptorProto{Name: proto.String("foo")}}
16
17	assert.Equal(t, "foo", f.Name().String())
18}
19
20func TestField_FullyQualifiedName(t *testing.T) {
21	t.Parallel()
22
23	f := &field{fqn: "field"}
24	assert.Equal(t, f.fqn, f.FullyQualifiedName())
25}
26
27func TestField_Syntax(t *testing.T) {
28	t.Parallel()
29
30	f := &field{}
31	m := dummyMsg()
32	m.addField(f)
33
34	assert.Equal(t, m.Syntax(), f.Syntax())
35}
36
37func TestField_Package(t *testing.T) {
38	t.Parallel()
39
40	f := &field{}
41	m := dummyMsg()
42	m.addField(f)
43
44	assert.NotNil(t, f.Package())
45	assert.Equal(t, m.Package(), f.Package())
46}
47
48func TestField_File(t *testing.T) {
49	t.Parallel()
50
51	f := &field{}
52	m := dummyMsg()
53	m.addField(f)
54
55	assert.NotNil(t, f.File())
56	assert.Equal(t, m.File(), f.File())
57}
58
59func TestField_BuildTarget(t *testing.T) {
60	t.Parallel()
61
62	f := &field{}
63	m := dummyMsg()
64	m.addField(f)
65
66	assert.False(t, f.BuildTarget())
67	m.setParent(&file{buildTarget: true})
68	assert.True(t, f.BuildTarget())
69}
70
71func TestField_Descriptor(t *testing.T) {
72	t.Parallel()
73
74	f := &field{desc: &descriptor.FieldDescriptorProto{}}
75	assert.Equal(t, f.desc, f.Descriptor())
76}
77
78func TestField_Message(t *testing.T) {
79	t.Parallel()
80
81	f := &field{}
82	m := dummyMsg()
83	m.addField(f)
84
85	assert.Equal(t, m, f.Message())
86}
87
88func TestField_OneOf(t *testing.T) {
89	t.Parallel()
90
91	f := &field{}
92	assert.Nil(t, f.OneOf())
93	assert.False(t, f.InOneOf())
94
95	o := dummyOneof()
96	o.addField(f)
97
98	assert.Equal(t, o, f.OneOf())
99	assert.True(t, f.InOneOf())
100}
101
102func TestField_Type(t *testing.T) {
103	t.Parallel()
104
105	f := &field{}
106	f.addType(&scalarT{})
107
108	assert.Equal(t, f.typ, f.Type())
109}
110
111func TestField_Extension(t *testing.T) {
112	// cannot be parallel
113
114	f := &field{desc: &descriptor.FieldDescriptorProto{}}
115	assert.NotPanics(t, func() { f.Extension(nil, nil) })
116}
117
118func TestField_Accept(t *testing.T) {
119	t.Parallel()
120
121	f := &field{}
122
123	assert.NoError(t, f.accept(nil))
124
125	v := &mockVisitor{err: errors.New("")}
126	assert.Error(t, f.accept(v))
127	assert.Equal(t, 1, v.field)
128}
129
130func TestField_Imports(t *testing.T) {
131	t.Parallel()
132
133	f := &field{}
134	f.addType(&scalarT{})
135	assert.Empty(t, f.Imports())
136
137	f.addType(&mockT{i: []File{&file{}, &file{}}})
138	assert.Len(t, f.Imports(), 2)
139}
140
141func TestField_Required(t *testing.T) {
142	t.Parallel()
143
144	msg := dummyMsg()
145
146	lbl := descriptor.FieldDescriptorProto_LABEL_REQUIRED
147
148	f := &field{desc: &descriptor.FieldDescriptorProto{Label: &lbl}}
149	f.setMessage(msg)
150
151	assert.False(t, f.Required(), "proto3 messages can never be marked required")
152
153	f.File().(*file).desc.Syntax = proto.String(string(Proto2))
154	assert.True(t, f.Required(), "proto2 + required")
155
156	lbl = descriptor.FieldDescriptorProto_LABEL_OPTIONAL
157	f.desc.Label = &lbl
158	assert.False(t, f.Required(), "proto2 + optional")
159}
160
161func TestField_ChildAtPath(t *testing.T) {
162	t.Parallel()
163
164	f := &field{}
165	assert.Equal(t, f, f.childAtPath(nil))
166	assert.Nil(t, f.childAtPath([]int32{1}))
167}
168
169type mockField struct {
170	Field
171	i   []File
172	m   Message
173	err error
174}
175
176func (f *mockField) Imports() []File { return f.i }
177
178func (f *mockField) setMessage(m Message) { f.m = m }
179
180func (f *mockField) accept(v Visitor) error {
181	_, err := v.VisitField(f)
182	if f.err != nil {
183		return f.err
184	}
185	return err
186}
187
188func dummyField() *field {
189	m := dummyMsg()
190	str := descriptor.FieldDescriptorProto_TYPE_STRING
191	f := &field{desc: &descriptor.FieldDescriptorProto{Name: proto.String("field"), Type: &str}}
192	m.addField(f)
193	t := &scalarT{}
194	f.addType(t)
195	return f
196}
197