Skip to content

Commit fa18fc8

Browse files
committed
fix(json reference): fix resolving json reference after patching which caused a nil pointer panic
1 parent 20cc96d commit fa18fc8

70 files changed

Lines changed: 800 additions & 629 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/handler_http_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func TestHandler_Http(t *testing.T) {
223223
c := openapitest.NewConfig("3.0.0",
224224
openapitest.WithInfo("foo", "", ""),
225225
openapitest.WithPathRef("/foo/{bar}", &openapi.PathRef{
226-
Reference: dynamic.Reference{
226+
Reference: dynamic.Reference[*openapi.PathRef]{
227227
Ref: "#/components/pathItems/foo",
228228
Summary: "Summary",
229229
Description: "Description",
@@ -233,7 +233,7 @@ func TestHandler_Http(t *testing.T) {
233233
openapitest.WithOperation("get",
234234
openapitest.UseResponseRef(http.StatusOK,
235235
&openapi.ResponseRef{
236-
Reference: dynamic.Reference{
236+
Reference: dynamic.Reference[*openapi.ResponseRef]{
237237
Ref: "#/components/pathItems/foo",
238238
Description: "Description",
239239
},

api/handler_kafka_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"mokapi/api"
66
"mokapi/config/dynamic"
7-
"mokapi/config/dynamic/asyncApi"
87
"mokapi/config/dynamic/dynamictest"
98
"mokapi/config/static"
109
"mokapi/engine/enginetest"
@@ -1098,7 +1097,7 @@ func TestHandler_Kafka_Metrics(t *testing.T) {
10981097
}
10991098

11001099
func Test_IsAsyncApiConfig(t *testing.T) {
1101-
v2 := &asyncApi.Config{Info: asyncApi.Info{Name: "foo"}}
1100+
v2 := &asyncapi3.Config{Info: asyncapi3.Info{Name: "foo"}}
11021101
_, ok := runtime.IsAsyncApiConfig(&dynamic.Config{Data: v2})
11031102
require.True(t, ok)
11041103

api/handler_schema_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package api
33
import (
44
"encoding/base64"
55
"encoding/json"
6+
"mokapi/config/dynamic"
67
"mokapi/config/static"
78
"mokapi/providers/asyncapi3/asyncapi3test"
89
"mokapi/providers/openapi/openapitest"
@@ -540,7 +541,7 @@ func TestSchemaInfo_MarshalJSON(t *testing.T) {
540541
},
541542
{
542543
name: "json schema only ref",
543-
s: &schemaInfo{Schema: &jsonSchema.Schema{Ref: "foo/bar"}},
544+
s: &schemaInfo{Schema: &jsonSchema.Schema{Reference: dynamic.Reference[*jsonSchema.Schema]{Ref: "foo/bar"}}},
544545
test: func(t *testing.T, s string, err error) {
545546
require.NoError(t, err)
546547
require.Equal(t, `{"schema":{"$ref":"foo/bar"}}`, s)
@@ -549,8 +550,8 @@ func TestSchemaInfo_MarshalJSON(t *testing.T) {
549550
{
550551
name: "json schema ref and value",
551552
s: &schemaInfo{Schema: &jsonSchema.Schema{
552-
Ref: "foo/bar",
553-
Type: jsonSchema.Types{"string"},
553+
Reference: dynamic.Reference[*jsonSchema.Schema]{Ref: "foo/bar"},
554+
Type: jsonSchema.Types{"string"},
554555
}},
555556
test: func(t *testing.T, s string, err error) {
556557
require.NoError(t, err)

api/handler_search_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"context"
55
"encoding/json"
66
"mokapi/config/dynamic"
7-
"mokapi/config/dynamic/asyncApi/asyncapitest"
87
"mokapi/config/dynamic/dynamictest"
98
"mokapi/config/static"
109
"mokapi/engine/enginetest"
10+
"mokapi/providers/asyncapi3/asyncapi3test"
1111
"mokapi/providers/openapi/openapitest"
1212
"mokapi/runtime"
1313
"mokapi/runtime/search"
@@ -143,7 +143,7 @@ func TestHandler_SearchQuery(t *testing.T) {
143143

144144
h := openapitest.NewConfig("3.0", openapitest.WithInfo("foo", "", ""))
145145
app.AddHttp(toConfig(h))
146-
k := asyncapitest.NewConfig(asyncapitest.WithInfo("foo", "", ""))
146+
k := asyncapi3test.NewConfig(asyncapi3test.WithInfo("foo", "", ""))
147147
_, err := app.Kafka.Add(toConfig(k), enginetest.NewEngine())
148148
require.NoError(t, err)
149149

@@ -173,7 +173,7 @@ func TestHandler_SearchQuery(t *testing.T) {
173173

174174
h := openapitest.NewConfig("3.0", openapitest.WithInfo("foo", "", ""))
175175
app.AddHttp(toConfig(h))
176-
k := asyncapitest.NewConfig(asyncapitest.WithInfo("foo", "", ""))
176+
k := asyncapi3test.NewConfig(asyncapi3test.WithInfo("foo", "", ""))
177177
_, err := app.Kafka.Add(toConfig(k), enginetest.NewEngine())
178178
require.NoError(t, err)
179179

config/dynamic/asyncApi/config.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ type ServerTag struct {
7070
}
7171

7272
type ServerRef struct {
73-
Ref string
73+
dynamic.Reference[*ServerRef]
7474
Value *Server
7575
}
7676

@@ -79,7 +79,7 @@ type ServerBindings struct {
7979
}
8080

8181
type ChannelRef struct {
82-
Ref string
82+
dynamic.Reference[*ChannelRef]
8383
Value *Channel
8484
}
8585

@@ -109,7 +109,7 @@ type OperationBindings struct {
109109
}
110110

111111
type MessageRef struct {
112-
Ref string
112+
dynamic.Reference[*MessageRef]
113113
Value *Message
114114
}
115115

@@ -141,7 +141,7 @@ type Components struct {
141141
}
142142

143143
type ParameterRef struct {
144-
dynamic.Reference
144+
dynamic.Reference[*ParameterRef]
145145
Value *Parameter
146146
}
147147

@@ -152,7 +152,7 @@ type Parameter struct {
152152
}
153153

154154
type MessageTraitRef struct {
155-
dynamic.Reference
155+
dynamic.Reference[*MessageTraitRef]
156156
Value *MessageTrait
157157
}
158158

config/dynamic/asyncApi/convert.go

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -66,24 +66,21 @@ func convertChannels(cfg *asyncapi3.Config, channels map[string]*ChannelRef) err
6666
if orig == nil {
6767
continue
6868
}
69-
if len(orig.Ref) > 0 {
70-
cfg.Channels[name] = &asyncapi3.ChannelRef{Reference: dynamic.Reference{Ref: orig.Ref}}
69+
ch, err := convertChannel(name, orig, cfg)
70+
if err != nil {
71+
return err
7172
}
72-
if orig.Value != nil {
73-
ch, err := convertChannel(name, orig, cfg)
74-
if err != nil {
75-
return err
76-
}
73+
if ch.Value != nil {
7774
ch.Value.Config = cfg
78-
cfg.Channels[name] = ch
7975
}
76+
cfg.Channels[name] = ch
8077
}
8178

8279
return nil
8380
}
8481

8582
func convertChannel(name string, c *ChannelRef, config *asyncapi3.Config) (*asyncapi3.ChannelRef, error) {
86-
result := &asyncapi3.ChannelRef{Reference: dynamic.Reference{Ref: c.Ref}}
83+
result := &asyncapi3.ChannelRef{Reference: dynamic.Reference[*asyncapi3.ChannelRef]{Ref: c.Ref}}
8784

8885
if c.Value != nil {
8986
target := &asyncapi3.Channel{
@@ -98,7 +95,7 @@ func convertChannel(name string, c *ChannelRef, config *asyncapi3.Config) (*asyn
9895
for _, server := range c.Value.Servers {
9996
target.Servers = append(
10097
target.Servers,
101-
&asyncapi3.ServerRef{Reference: dynamic.Reference{
98+
&asyncapi3.ServerRef{Reference: dynamic.Reference[*asyncapi3.ServerRef]{
10299
Ref: fmt.Sprintf("#/servers/%s", server),
103100
}})
104101
}
@@ -192,53 +189,50 @@ func convertMessage(msg *MessageRef) *asyncapi3.MessageRef {
192189
return nil
193190
}
194191

195-
target := &asyncapi3.MessageRef{Reference: dynamic.Reference{Ref: msg.Ref}}
192+
target := &asyncapi3.MessageRef{Reference: dynamic.Reference[*asyncapi3.MessageRef]{Ref: msg.Ref}}
196193
if msg.Value != nil {
197194
target.Value = &asyncapi3.Message{
198195
Title: msg.Value.Title,
199196
Name: msg.Value.Name,
200197
Summary: msg.Value.Summary,
201198
Description: msg.Value.Description,
202199
ContentType: msg.Value.ContentType,
203-
Payload: nil,
200+
Payload: msg.Value.Payload,
204201
Bindings: convertMessageBinding(msg.Value.Bindings),
202+
Headers: msg.Value.Headers,
205203
ExternalDocs: nil,
206204
}
207205

208-
if msg.Value.Payload != nil && msg.Value.Payload.Value != nil {
209-
target.Value.Payload = msg.Value.Payload
210-
}
211-
if msg.Value.Headers != nil && msg.Value.Headers.Value != nil {
212-
target.Value.Headers = msg.Value.Headers
213-
}
214206
for _, orig := range msg.Value.Traits {
215-
trait := &asyncapi3.MessageTraitRef{}
216-
if len(orig.Ref) > 0 {
217-
trait.Reference = dynamic.Reference{Ref: trait.Ref}
218-
}
219-
if orig.Value != nil {
220-
trait.Value = convertMessageTrait(orig.Value).Value
207+
trait := convertMessageTrait(orig)
208+
if trait != nil {
209+
target.Value.Traits = append(target.Value.Traits, trait)
221210
}
222-
target.Value.Traits = append(target.Value.Traits, trait)
223211
}
224212
}
225213
return target
226214
}
227215

228-
func convertMessageTrait(trait *MessageTrait) *asyncapi3.MessageTraitRef {
229-
target := &asyncapi3.MessageTrait{
230-
Name: trait.Name,
231-
Title: trait.Title,
232-
Summary: trait.Summary,
233-
Description: trait.Description,
234-
ContentType: trait.ContentType,
235-
Bindings: convertMessageBinding(trait.Bindings),
216+
func convertMessageTrait(trait *MessageTraitRef) *asyncapi3.MessageTraitRef {
217+
target := &asyncapi3.MessageTraitRef{
218+
Reference: dynamic.Reference[*asyncapi3.MessageTraitRef]{Ref: trait.Ref},
236219
}
237220

238-
if trait.Headers != nil && trait.Headers.Value != nil {
239-
target.Headers = trait.Headers
221+
if trait.Value != nil {
222+
target.Value = &asyncapi3.MessageTrait{
223+
Name: trait.Value.Name,
224+
Title: trait.Value.Title,
225+
Summary: trait.Value.Summary,
226+
Description: trait.Value.Description,
227+
ContentType: trait.Value.ContentType,
228+
Bindings: convertMessageBinding(trait.Value.Bindings),
229+
}
230+
if trait.Value.Headers != nil && trait.Value.Headers.Value != nil {
231+
target.Value.Headers = trait.Value.Headers
232+
}
240233
}
241-
return &asyncapi3.MessageTraitRef{Value: target}
234+
235+
return target
242236
}
243237

244238
func convertParameters(channel *asyncapi3.Channel, params map[string]*ParameterRef) error {
@@ -251,7 +245,7 @@ func convertParameters(channel *asyncapi3.Channel, params map[string]*ParameterR
251245

252246
for name, orig := range params {
253247
if len(orig.Ref) > 0 {
254-
channel.Parameters[name] = &asyncapi3.ParameterRef{Reference: dynamic.Reference{Ref: orig.Ref}}
248+
channel.Parameters[name] = &asyncapi3.ParameterRef{Reference: dynamic.Reference[*asyncapi3.ParameterRef]{Ref: orig.Ref}}
255249
}
256250
if orig.Value != nil {
257251
p, err := convertParameter(name, orig.Value)
@@ -308,17 +302,15 @@ func convertServers(cfg *asyncapi3.Config, servers map[string]*ServerRef) {
308302
}
309303

310304
for name, orig := range servers {
311-
if len(orig.Ref) > 0 {
312-
cfg.Servers.Set(name, &asyncapi3.ServerRef{Reference: dynamic.Reference{Ref: orig.Ref}})
313-
}
314-
if orig.Value != nil {
315-
cfg.Servers.Set(name, convertServer(orig))
305+
if orig == nil {
306+
continue
316307
}
308+
cfg.Servers.Set(name, convertServer(orig))
317309
}
318310
}
319311

320312
func convertServer(ref *ServerRef) *asyncapi3.ServerRef {
321-
result := &asyncapi3.ServerRef{Reference: dynamic.Reference{Ref: ref.Ref}}
313+
result := &asyncapi3.ServerRef{Reference: dynamic.Reference[*asyncapi3.ServerRef]{Ref: ref.Ref}}
322314

323315
if ref.Value != nil {
324316
target := &asyncapi3.Server{
@@ -440,7 +432,7 @@ func convertComponents(c *Components, config *asyncapi3.Config) (*asyncapi3.Comp
440432
target.Parameters = map[string]*asyncapi3.ParameterRef{}
441433
}
442434
if len(orig.Ref) > 0 {
443-
target.Parameters[name] = &asyncapi3.ParameterRef{Reference: dynamic.Reference{Ref: orig.Ref}}
435+
target.Parameters[name] = &asyncapi3.ParameterRef{Reference: dynamic.Reference[*asyncapi3.ParameterRef]{Ref: orig.Ref}}
444436
}
445437
if orig.Value != nil {
446438
p, err := convertParameter(name, orig.Value)
@@ -455,12 +447,7 @@ func convertComponents(c *Components, config *asyncapi3.Config) (*asyncapi3.Comp
455447
if target.MessageTraits == nil {
456448
target.MessageTraits = map[string]*asyncapi3.MessageTraitRef{}
457449
}
458-
if len(orig.Ref) > 0 {
459-
target.MessageTraits[name] = &asyncapi3.MessageTraitRef{Reference: dynamic.Reference{Ref: orig.Ref}}
460-
}
461-
if orig.Value != nil {
462-
target.MessageTraits[name] = convertMessageTrait(orig.Value)
463-
}
450+
target.MessageTraits[name] = convertMessageTrait(orig)
464451
}
465452

466453
return target, nil

config/dynamic/asyncApi/convert_test.go

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ func TestConfig_Convert(t *testing.T) {
2323
err = yaml.Unmarshal(b, &cfg)
2424
require.NoError(t, err)
2525

26-
err = cfg.Parse(&dynamic.Config{Data: cfg}, &dynamictest.Reader{})
26+
c := &dynamic.Config{Data: cfg}
27+
err = cfg.Parse(c, &dynamictest.Reader{})
2728
require.NoError(t, err)
2829

29-
cfg3, err := cfg.Convert()
30-
require.NoError(t, err)
30+
cfg3 := c.Data.(*asyncapi3.Config)
3131

3232
require.Equal(t, "3.0.0", cfg3.Version)
3333
require.Equal(t, "urn:example:com:smartylighting:streetlights:server", cfg3.Id)
@@ -150,3 +150,70 @@ channels:
150150
require.Len(t, cfg.Operations["bar_send_publish"].Value.Messages, 1)
151151
require.Equal(t, cfg.Channels["bar"].Value.Messages["publish"], cfg.Operations["bar_send_publish"].Value.Messages[0])
152152
}
153+
154+
func TestConvert(t *testing.T) {
155+
testcases := []struct {
156+
name string
157+
cfg *asyncApi.Config
158+
test func(t *testing.T, config *asyncapi3.Config, err error)
159+
}{
160+
{
161+
name: "server ref",
162+
cfg: &asyncApi.Config{
163+
Servers: map[string]*asyncApi.ServerRef{
164+
"foo": {Reference: dynamic.Reference[*asyncApi.ServerRef]{Ref: "#/components/servers/foo"}},
165+
},
166+
Components: &asyncApi.Components{
167+
Servers: map[string]*asyncApi.ServerRef{
168+
"foo": {Value: &asyncApi.Server{Url: "foo.bar"}},
169+
},
170+
},
171+
},
172+
test: func(t *testing.T, config *asyncapi3.Config, err error) {
173+
require.Equal(t, 1, config.Servers.Len())
174+
s, _ := config.Servers.Get("foo")
175+
require.NotNil(t, s)
176+
require.NotNil(t, s.Value)
177+
require.Equal(t, "foo.bar", s.Value.Host)
178+
require.Equal(t, "#/components/servers/foo", s.Ref)
179+
},
180+
},
181+
{
182+
name: "channel ref",
183+
cfg: &asyncApi.Config{
184+
Channels: map[string]*asyncApi.ChannelRef{
185+
"foo": {Reference: dynamic.Reference[*asyncApi.ChannelRef]{Ref: "#/components/channels/foo"}},
186+
},
187+
Components: &asyncApi.Components{
188+
Channels: map[string]*asyncApi.ChannelRef{
189+
"foo": {Value: &asyncApi.Channel{
190+
Description: "foo",
191+
}},
192+
},
193+
},
194+
},
195+
test: func(t *testing.T, config *asyncapi3.Config, err error) {
196+
require.Len(t, config.Channels, 1)
197+
c := config.Channels["foo"]
198+
require.NotNil(t, c)
199+
require.NotNil(t, c.Value)
200+
require.Equal(t, "foo", c.Value.Description)
201+
require.Equal(t, "#/components/channels/foo", c.Ref)
202+
},
203+
},
204+
}
205+
206+
t.Parallel()
207+
for _, tc := range testcases {
208+
t.Run(tc.name, func(t *testing.T) {
209+
t.Parallel()
210+
211+
c := &dynamic.Config{Data: tc.cfg}
212+
err := tc.cfg.Parse(c, &dynamictest.Reader{})
213+
require.NoError(t, err)
214+
require.IsType(t, &asyncapi3.Config{}, c.Data)
215+
216+
tc.test(t, c.Data.(*asyncapi3.Config), err)
217+
})
218+
}
219+
}

0 commit comments

Comments
 (0)