cuelang.org/go@v0.13.0/encoding/openapi/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 openapi_test 16 17 import ( 18 "bytes" 19 "io/fs" 20 "os" 21 "path" 22 "path/filepath" 23 "strings" 24 "testing" 25 26 "github.com/go-quicktest/qt" 27 "github.com/google/go-cmp/cmp" 28 "golang.org/x/tools/txtar" 29 30 "cuelang.org/go/cue" 31 "cuelang.org/go/cue/ast" 32 "cuelang.org/go/cue/cuecontext" 33 "cuelang.org/go/cue/errors" 34 "cuelang.org/go/cue/format" 35 "cuelang.org/go/encoding/json" 36 "cuelang.org/go/encoding/openapi" 37 "cuelang.org/go/encoding/yaml" 38 "cuelang.org/go/internal" 39 "cuelang.org/go/internal/cuetest" 40 ) 41 42 // TestDecode reads the testdata/script/*.txtar files, converts the 43 // contained JSON (or YAML) schema to CUE and compares it against the 44 // output. 45 // 46 // The first .json or .yaml file in the txtar archive (with no / in 47 // the name) is used as the input. The first .cue file in the archive 48 // (with no / in the name) is used as the expected output. 49 // 50 // Set CUE_UPDATE=1 to update test files with the corresponding output. 51 func TestDecode(t *testing.T) { 52 err := filepath.WalkDir("testdata/script", func(fullpath string, entry fs.DirEntry, err error) error { 53 if err != nil { 54 return err 55 } 56 if !strings.HasSuffix(fullpath, ".txtar") { 57 return nil 58 } 59 60 t.Run(fullpath, func(t *testing.T) { 61 a, err := txtar.ParseFile(fullpath) 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 cfg := &openapi.Config{PkgName: "foo"} 67 68 var inFile *ast.File 69 var out, errout []byte 70 outIndex := -1 71 72 for i, f := range a.Files { 73 if strings.Contains(f.Name, "/") { 74 continue 75 } 76 switch path.Ext(f.Name) { 77 case ".json": 78 if inFile == nil { 79 var inExpr ast.Expr 80 inExpr, err = json.Extract(f.Name, f.Data) 81 inFile = internal.ToFile(inExpr) 82 } 83 case ".yaml": 84 if inFile == nil { 85 inFile, err = yaml.Extract(f.Name, f.Data) 86 } 87 case ".cue": 88 if out == nil { 89 out = f.Data 90 outIndex = i 91 } 92 case ".err": 93 if errout == nil { 94 errout = f.Data 95 } 96 } 97 } 98 if err != nil { 99 t.Fatal(err) 100 } 101 ctx := cuecontext.New() 102 in := ctx.BuildFile(inFile) 103 if err := in.Err(); err != nil { 104 t.Fatal(err) 105 } 106 107 gotFile, err := openapi.Extract(in, cfg) 108 if err != nil && errout == nil { 109 t.Fatal(errors.Details(err, nil)) 110 } 111 got := []byte(nil) 112 if err != nil { 113 got = []byte(err.Error()) 114 } 115 if diff := cmp.Diff(errout, got); diff != "" { 116 t.Error(diff) 117 } 118 119 if gotFile != nil { 120 // verify the generated CUE. 121 v := ctx.BuildFile(gotFile, cue.Filename(fullpath)) 122 if err := v.Err(); err != nil { 123 t.Fatal(errors.Details(err, nil)) 124 } 125 126 b, err := format.Node(gotFile, format.Simplify()) 127 if err != nil { 128 t.Fatal(err) 129 } 130 131 b = bytes.TrimSpace(b) 132 out = bytes.TrimSpace(out) 133 134 if diff := cmp.Diff(b, out); diff != "" { 135 if cuetest.UpdateGoldenFiles { 136 a.Files[outIndex].Data = b 137 b = txtar.Format(a) 138 err = os.WriteFile(fullpath, b, 0666) 139 if err != nil { 140 t.Fatal(err) 141 } 142 return 143 } 144 t.Error(cmp.Diff(string(out), string(b))) 145 } 146 } 147 }) 148 return nil 149 }) 150 qt.Assert(t, qt.IsNil(err)) 151 }