1 package spec
2
3 import (
4 "encoding/json"
5 "fmt"
6 "regexp"
7 "strings"
8 "testing"
9
10 "github.com/go-openapi/swag"
11 "github.com/stretchr/testify/assert"
12 "github.com/stretchr/testify/require"
13 )
14
15 var rex = regexp.MustCompile(`"\$ref":\s*"(.*?)"`)
16
17 func jsonDoc(path string) (json.RawMessage, error) {
18 data, err := swag.LoadFromFileOrHTTP(path)
19 if err != nil {
20 return nil, err
21 }
22 return json.RawMessage(data), nil
23 }
24
25 func docAndOpts(t testing.TB, fixturePath string) ([]byte, *ExpandOptions) {
26 doc, err := jsonDoc(fixturePath)
27 require.NoError(t, err)
28
29 return doc, &ExpandOptions{
30 RelativeBase: fixturePath,
31 }
32 }
33
34 func expandThisSchemaOrDieTrying(t testing.TB, fixturePath string) (string, *Schema) {
35 doc, opts := docAndOpts(t, fixturePath)
36
37 sch := new(Schema)
38 require.NoError(t, json.Unmarshal(doc, sch))
39
40 require.NotPanics(t, func() {
41 require.NoError(t, ExpandSchemaWithBasePath(sch, nil, opts))
42 }, "calling expand schema circular refs, should not panic!")
43
44 bbb, err := json.MarshalIndent(sch, "", " ")
45 require.NoError(t, err)
46
47 return string(bbb), sch
48 }
49
50 func expandThisOrDieTrying(t testing.TB, fixturePath string) (string, *Swagger) {
51 doc, opts := docAndOpts(t, fixturePath)
52
53 spec := new(Swagger)
54 require.NoError(t, json.Unmarshal(doc, spec))
55
56 require.NotPanics(t, func() {
57 require.NoError(t, ExpandSpec(spec, opts))
58 }, "calling expand spec with circular refs, should not panic!")
59
60 bbb, err := json.MarshalIndent(spec, "", " ")
61 require.NoError(t, err)
62
63 return string(bbb), spec
64 }
65
66
67
68
69 func assertRefInJSON(t testing.TB, jazon, prefix string) {
70
71 m := rex.FindAllStringSubmatch(jazon, -1)
72 require.NotNil(t, m)
73
74 for _, matched := range m {
75 subMatch := matched[1]
76 assert.True(t, strings.HasPrefix(subMatch, prefix),
77 "expected $ref to match %q, got: %s", prefix, matched[0])
78 }
79 }
80
81
82
83
84 func assertRefInJSONRegexp(t testing.TB, jazon, match string) {
85
86 m := rex.FindAllStringSubmatch(jazon, -1)
87 require.NotNil(t, m)
88
89 refMatch, err := regexp.Compile(match)
90 require.NoError(t, err)
91
92 for _, matched := range m {
93 subMatch := matched[1]
94 assert.True(t, refMatch.MatchString(subMatch),
95 "expected $ref to match %q, got: %s", match, matched[0])
96 }
97 }
98
99
100 func assertNoRef(t testing.TB, jazon string) {
101 m := rex.FindAllStringSubmatch(jazon, -1)
102 require.Nil(t, m)
103 }
104
105
106
107
108 func assertRefExpand(t *testing.T, jazon, _ string, root interface{}, opts ...*ExpandOptions) {
109 assertRefWithFunc(t, jazon, "", func(t *testing.T, match string) {
110 ref := RefSchema(match)
111 if len(opts) > 0 {
112 options := *opts[0]
113 require.NoError(t, ExpandSchemaWithBasePath(ref, nil, &options))
114 } else {
115 require.NoError(t, ExpandSchema(ref, root, nil))
116 }
117 })
118 }
119
120
121
122
123 func assertRefResolve(t *testing.T, jazon, exclude string, root interface{}, opts ...*ExpandOptions) {
124 assertRefWithFunc(t, jazon, exclude, func(t *testing.T, match string) {
125 ref := MustCreateRef(match)
126 var (
127 sch *Schema
128 err error
129 )
130 if len(opts) > 0 {
131 options := *opts[0]
132 sch, err = ResolveRefWithBase(root, &ref, &options)
133 } else {
134 sch, err = ResolveRef(root, &ref)
135 }
136
137 require.NoErrorf(t, err, `%v: for "$ref": %q`, err, match)
138 require.NotNil(t, sch)
139 })
140 }
141
142
143
144
145 func assertRefWithFunc(t *testing.T, jazon, exclude string, asserter func(t *testing.T, match string)) {
146 filterRex := regexp.MustCompile(exclude)
147 m := rex.FindAllStringSubmatch(jazon, -1)
148 require.NotNil(t, m)
149 allRefs := make(map[string]struct{}, len(m))
150 for _, matched := range m {
151 subMatch := matched[1]
152 if exclude != "" && filterRex.MatchString(subMatch) {
153 continue
154 }
155 _, ok := allRefs[subMatch]
156 if ok {
157 continue
158 }
159 allRefs[subMatch] = struct{}{}
160
161 t.Run(fmt.Sprintf("%s-%s", t.Name(), subMatch), func(t *testing.T) {
162 t.Parallel()
163 asserter(t, subMatch)
164 })
165 }
166 }
167
168 func asJSON(t testing.TB, sp interface{}) string {
169 bbb, err := json.MarshalIndent(sp, "", " ")
170 require.NoError(t, err)
171
172 return string(bbb)
173 }
174
View as plain text