1// Copyright 2019 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package openapi_test
16
17import (
18 "bytes"
19 "encoding/json"
20 "strings"
21 "testing"
22
23 "github.com/go-quicktest/qt"
24
25 "cuelang.org/go/cue"
26 "cuelang.org/go/cue/cuecontext"
27 "cuelang.org/go/cue/errors"
28 "cuelang.org/go/encoding/openapi"
29 "cuelang.org/go/internal/cuetdtest"
30 "cuelang.org/go/internal/cuetxtar"
31)
32
33var (
34 matrix = cuetdtest.FullMatrix
35)
36
37func TestGenerateOpenAPI(t *testing.T) {
38 t.Parallel()
39 test := cuetxtar.TxTarTest{
40 Root: "./testdata",
41 Name: t.Name(),
42 Matrix: matrix,
43 }
44
45 nameFuncs := map[string]func(v cue.Value, path cue.Path) string{
46 "toUpper": func(v cue.Value, path cue.Path) string {
47 var buf strings.Builder
48 for i, sel := range path.Selectors() {
49 if i > 0 {
50 buf.WriteByte('_')
51 }
52 s := sel.String()
53 s = strings.TrimPrefix(s, "#")
54 buf.WriteString(strings.ToUpper(s))
55 }
56 return buf.String()
57 },
58 "excludeExcluded": func(v cue.Value, path cue.Path) string {
59 switch {
60 case strings.HasPrefix(path.Selectors()[0].String(), "#Excluded"):
61 return ""
62 }
63 return strings.TrimPrefix(path.String(), "#")
64 },
65 }
66
67 descFuncs := map[string]func(v cue.Value) string{
68 "randomish": func(v cue.Value) string {
69 return "Randomly picked description from a set of size one."
70 },
71 }
72
73 test.Run(t, func(t *cuetxtar.Test) {
74 t.Parallel()
75 a := t.Instance()
76 ctx := t.CueContext()
77 v := ctx.BuildInstance(a)
78
79 if err := v.Err(); err != nil {
80 t.Fatal(errors.Details(err, nil))
81 }
82
83 config := openapi.Config{}
84 if t.HasTag("ExpandReferences") {
85 config.ExpandReferences = true
86 }
87 if filter, ok := t.Value("FieldFilter"); ok {
88 config.FieldFilter = filter
89 }
90 if version, ok := t.Value("Version"); ok {
91 config.Version = version
92 }
93 if name, ok := t.Value("NameFunc"); ok {
94 if fun, found := nameFuncs[name]; found {
95 config.NameFunc = fun
96 } else {
97 t.Fatal("Unknown NameFunc", name)
98 }
99 }
100 if desc, ok := t.Value("DescriptionFunc"); ok {
101 if fun, found := descFuncs[desc]; found {
102 config.DescriptionFunc = fun
103 } else {
104 t.Fatal("Unknown DescriptionFunc", desc)
105 }
106 }
107
108 expectedErr, shouldErr := t.Value("ExpectError")
109 f, err := openapi.Generate(v, &config)
110 if err != nil {
111 details := errors.Details(err, nil)
112 if !shouldErr || !strings.Contains(details, expectedErr) {
113 t.Fatal("unexpected error:", details)
114 }
115 return
116 }
117 if shouldErr {
118 t.Fatal("unexpected success")
119 } else {
120 _, err := openapi.Gen(v, &config)
121 if err != nil {
122 t.Fatal(err)
123 }
124 }
125 gen := ctx.BuildFile(f)
126 qt.Assert(t, qt.IsNil(gen.Err()))
127 var out bytes.Buffer
128 enc := json.NewEncoder(&out)
129 enc.SetEscapeHTML(false)
130 enc.SetIndent("", " ")
131 err = enc.Encode(gen)
132 qt.Assert(t, qt.IsNil(err))
133 _, err = t.Writer("out.json").Write(out.Bytes())
134 qt.Assert(t, qt.IsNil(err))
135
136 // Check that we can extract the resulting schema without error.
137 _, err = openapi.Extract(gen, &config)
138 if expectedErr, shouldErr := t.Value("ExpectExtractError"); shouldErr {
139 qt.Assert(t, qt.ErrorMatches(err, expectedErr))
140 return
141 }
142 // TODO check that the resulting schema actually validates some
143 // data values as expected.
144 qt.Assert(t, qt.IsNil(err))
145 })
146}
147
148// TODO: move OpenAPI testing to txtar and allow errors.
149func TestIssue1234(t *testing.T) {
150 val := cuecontext.New().CompileString(`
151#Test: or([])
152
153 `)
154 if err := val.Err(); err != nil {
155 t.Fatal(err)
156 }
157
158 _, err := openapi.Gen(val, &openapi.Config{})
159 if err == nil {
160 t.Fatal("expected error")
161 }
162}
163
164// This is for debugging purposes. Do not remove.
165func TestX(t *testing.T) {
166 t.Skip()
167
168 val := cuecontext.New().CompileString(`
169 `)
170 if err := val.Err(); err != nil {
171 t.Fatal(err)
172 }
173
174 b, err := openapi.Gen(val, &openapi.Config{
175 // ExpandReferences: true,
176 })
177 if err != nil {
178 t.Fatal(errors.Details(err, nil))
179 }
180
181 var out = &bytes.Buffer{}
182 _ = json.Indent(out, b, "", " ")
183 t.Error(out.String())
184}