cuelang.org/go@v0.10.1/encoding/jsonschema/decode_test.go (about) 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 15 package jsonschema_test 16 17 import ( 18 "bytes" 19 "fmt" 20 "net/url" 21 "path" 22 "testing" 23 24 "github.com/go-quicktest/qt" 25 "golang.org/x/tools/txtar" 26 27 "cuelang.org/go/cue" 28 "cuelang.org/go/cue/ast" 29 "cuelang.org/go/cue/cuecontext" 30 "cuelang.org/go/cue/errors" 31 "cuelang.org/go/cue/format" 32 "cuelang.org/go/cue/token" 33 "cuelang.org/go/encoding/json" 34 "cuelang.org/go/encoding/jsonschema" 35 "cuelang.org/go/encoding/yaml" 36 "cuelang.org/go/internal/astinternal" 37 "cuelang.org/go/internal/cuetdtest" 38 "cuelang.org/go/internal/cuetxtar" 39 _ "cuelang.org/go/pkg" 40 ) 41 42 // TestDecode reads the testdata/*.txtar files, converts the contained 43 // JSON schema to CUE and compares it against the output. 44 // 45 // Set CUE_UPDATE=1 to update test files with the corresponding output. 46 func TestDecode(t *testing.T) { 47 test := cuetxtar.TxTarTest{ 48 Root: "./testdata", 49 Name: "decode", 50 Matrix: cuetdtest.FullMatrix, 51 } 52 test.Run(t, func(t *cuetxtar.Test) { 53 cfg := &jsonschema.Config{} 54 55 if t.HasTag("openapi") { 56 cfg.Root = "#/components/schemas/" 57 cfg.Map = func(p token.Pos, a []string) ([]ast.Label, error) { 58 // Just for testing: does not validate the path. 59 return []ast.Label{ast.NewIdent("#" + a[len(a)-1])}, nil 60 } 61 } 62 cfg.Strict = t.HasTag("strict") 63 64 ctx := t.Context() 65 var v cue.Value 66 67 for _, f := range t.Archive.Files { 68 switch path.Ext(f.Name) { 69 case ".json": 70 expr, err := json.Extract(f.Name, f.Data) 71 if err != nil { 72 t.Fatal(err) 73 } 74 v = ctx.BuildExpr(expr) 75 case ".yaml": 76 file, err := yaml.Extract(f.Name, f.Data) 77 if err != nil { 78 t.Fatal(err) 79 } 80 v = ctx.BuildFile(file) 81 } 82 } 83 84 expr, err := jsonschema.Extract(v, cfg) 85 if err != nil { 86 got := []byte(errors.Details(err, nil)) 87 got = append(bytes.TrimSpace(got), '\n') 88 t.Writer("err").Write(got) 89 } 90 91 if expr != nil { 92 b, err := format.Node(expr, format.Simplify()) 93 if err != nil { 94 t.Fatal(errors.Details(err, nil)) 95 } 96 97 // verify the generated CUE. 98 if !t.HasTag("noverify") { 99 v := ctx.CompileBytes(b, cue.Filename("generated.cue")) 100 if err := v.Err(); err != nil { 101 t.Fatal(errors.Details(err, nil)) 102 } 103 } 104 105 b = append(bytes.TrimSpace(b), '\n') 106 t.Writer("cue").Write(b) 107 } 108 }) 109 } 110 111 func TestMapURL(t *testing.T) { 112 v := cuecontext.New().CompileString(` 113 type: "object" 114 properties: x: $ref: "https://something.test/foo#/definitions/blah" 115 `) 116 var calls []string 117 expr, err := jsonschema.Extract(v, &jsonschema.Config{ 118 MapURL: func(u *url.URL) (string, error) { 119 calls = append(calls, u.String()) 120 return "other.test/something:blah", nil 121 }, 122 }) 123 qt.Assert(t, qt.IsNil(err)) 124 b, err := format.Node(expr, format.Simplify()) 125 if err != nil { 126 t.Fatal(errors.Details(err, nil)) 127 } 128 qt.Assert(t, qt.DeepEquals(calls, []string{"https://something.test/foo"})) 129 qt.Assert(t, qt.Equals(string(b), ` 130 import "other.test/something:blah" 131 132 x?: blah.#blah 133 ... 134 `[1:])) 135 } 136 137 func TestMapURLErrors(t *testing.T) { 138 v := cuecontext.New().CompileString(` 139 type: "object" 140 properties: { 141 x: $ref: "https://something.test/foo#/definitions/x" 142 y: $ref: "https://something.test/foo#/definitions/y" 143 } 144 `, cue.Filename("foo.cue")) 145 _, err := jsonschema.Extract(v, &jsonschema.Config{ 146 MapURL: func(u *url.URL) (string, error) { 147 return "", fmt.Errorf("some error") 148 }, 149 }) 150 qt.Assert(t, qt.Equals(errors.Details(err, nil), ` 151 cannot determine import path from URL "https://something.test/foo": some error: 152 foo.cue:4:5 153 `[1:])) 154 } 155 156 func TestX(t *testing.T) { 157 t.Skip() 158 data := ` 159 -- schema.json -- 160 ` 161 162 a := txtar.Parse([]byte(data)) 163 164 ctx := cuecontext.New() 165 var v cue.Value 166 var err error 167 for _, f := range a.Files { 168 switch path.Ext(f.Name) { 169 case ".json": 170 expr, err := json.Extract(f.Name, f.Data) 171 if err != nil { 172 t.Fatal(err) 173 } 174 v = ctx.BuildExpr(expr) 175 case ".yaml": 176 file, err := yaml.Extract(f.Name, f.Data) 177 if err != nil { 178 t.Fatal(err) 179 } 180 v = ctx.BuildFile(file) 181 } 182 } 183 184 cfg := &jsonschema.Config{ID: "test"} 185 expr, err := jsonschema.Extract(v, cfg) 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 t.Fatal(astinternal.DebugStr(expr)) 191 }