cuelang.org/go@v0.10.1/cue/context_test.go (about) 1 // Copyright 2021 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 cue_test 16 17 import ( 18 "fmt" 19 "testing" 20 21 "cuelang.org/go/cue" 22 "cuelang.org/go/cue/build" 23 "cuelang.org/go/cue/cuecontext" 24 "cuelang.org/go/internal/astinternal" 25 "cuelang.org/go/internal/cuetest" 26 "cuelang.org/go/internal/cuetxtar" 27 "cuelang.org/go/internal/tdtest" 28 "github.com/go-quicktest/qt" 29 "golang.org/x/tools/txtar" 30 ) 31 32 func TestNewList(t *testing.T) { 33 ctx := cuecontext.New() 34 35 intList := ctx.CompileString("[...int]") 36 37 l123 := ctx.NewList( 38 ctx.Encode(1), 39 ctx.Encode(2), 40 ctx.Encode(3), 41 ) 42 43 testCases := []struct { 44 desc string 45 v cue.Value 46 out string 47 }{{ 48 v: ctx.NewList(), 49 out: `[]`, 50 }, { 51 v: l123, 52 out: `[1, 2, 3]`, 53 }, { 54 v: l123.Unify(intList), 55 out: `[1, 2, 3]`, 56 }, { 57 v: l123.Unify(intList).Unify(l123), 58 out: `[1, 2, 3]`, 59 }, { 60 v: intList.Unify(ctx.NewList(ctx.Encode("string"))), 61 out: `_|_ // 0: conflicting values "string" and int (mismatched types string and int)`, 62 }, { 63 v: ctx.NewList().Unify(l123), 64 out: `_|_ // incompatible list lengths (0 and 3)`, 65 }, { 66 v: ctx.NewList( 67 intList, 68 intList, 69 ).Unify(ctx.NewList( 70 ctx.NewList( 71 ctx.Encode(1), 72 ctx.Encode(3), 73 ), 74 ctx.NewList( 75 ctx.Encode(5), 76 ctx.Encode(7), 77 ), 78 )), 79 out: `[[1, 3], [5, 7]]`, 80 }} 81 for _, tc := range testCases { 82 t.Run(tc.desc, func(t *testing.T) { 83 got := fmt.Sprint(tc.v) 84 if got != tc.out { 85 t.Errorf(" got: %v\nwant: %v", got, tc.out) 86 } 87 }) 88 } 89 } 90 91 func TestBuildInstancesSuccess(t *testing.T) { 92 in := ` 93 -- foo.cue -- 94 package foo 95 96 foo: [{a: "b", c: "d"}, {a: "e", g: "f"}] 97 bar: [ 98 for f in foo 99 if (f & {c: "b"}) != _|_ 100 {f} 101 ] 102 ` 103 104 a := txtar.Parse([]byte(in)) 105 instance := cuetxtar.Load(a, t.TempDir())[0] 106 if instance.Err != nil { 107 t.Fatal(instance.Err) 108 } 109 110 _, err := cuecontext.New().BuildInstances([]*build.Instance{instance}) 111 if err != nil { 112 t.Fatalf("BuildInstances() = %v", err) 113 } 114 } 115 116 func TestBuildInstancesError(t *testing.T) { 117 in := ` 118 -- foo.cue -- 119 package foo 120 121 foo: [{a: "b", c: "d"}, {a: "e", g: "f"}] 122 bar: [ 123 for f in foo 124 if f & {c: "b") != _|_ // NOTE: ')' instead of '}' 125 {f} 126 ] 127 ` 128 129 a := txtar.Parse([]byte(in)) 130 instance := cuetxtar.Load(a, t.TempDir())[0] 131 132 // Normally, this should be checked, however, this is explicitly 133 // testing the path where this was NOT checked. 134 // if instance.Err != nil { 135 // t.Fatal(instance.Err) 136 // } 137 138 vs, err := cuecontext.New().BuildInstances([]*build.Instance{instance}) 139 if err == nil { 140 t.Fatalf("BuildInstances() = %#v, wanted error", vs) 141 } 142 } 143 144 func TestEncodeType(t *testing.T) { 145 type testCase struct { 146 name string 147 x interface{} 148 wantErr string 149 out string 150 } 151 testCases := []testCase{{ 152 name: "Struct", 153 x: struct { 154 A int `json:"a"` 155 B string `json:"b,omitempty"` 156 C []bool 157 }{}, 158 out: `{a: int64, b?: string, C?: *null|[...bool]}`, 159 }, { 160 name: "CUEValue#1", 161 x: struct { 162 A cue.Value `json:"a"` 163 }{}, 164 out: `{a: _}`, 165 }, { 166 name: "CUEValue#2", 167 x: cue.Value{}, 168 out: `_`, 169 }, { 170 // TODO this looks like a shortcoming of EncodeType. 171 name: "map", 172 x: map[string]int{}, 173 out: `*null|{}`, 174 }, { 175 name: "slice", 176 x: []int{}, 177 out: `*null|[...int64]`, 178 }, { 179 name: "chan", 180 x: chan int(nil), 181 wantErr: `unsupported Go type \(chan int\)`, 182 }} 183 tdtest.Run(t, testCases, func(t *cuetest.T, tc *testCase) { 184 v := cuecontext.New().EncodeType(tc.x) 185 if tc.wantErr != "" { 186 qt.Assert(t, qt.ErrorMatches(v.Err(), tc.wantErr)) 187 return 188 } 189 qt.Assert(t, qt.IsNil(v.Err())) 190 got := fmt.Sprint(astinternal.DebugStr(v.Eval().Syntax())) 191 t.Equal(got, tc.out) 192 }) 193 } 194 195 func TestContextCheck(t *testing.T) { 196 qt.Assert(t, qt.PanicMatches(func() { 197 var c cue.Context 198 c.CompileString("1") 199 }, `.*use cuecontext\.New.*`)) 200 }