cuelang.org/go@v0.10.1/cue/builtin_test.go (about) 1 // Copyright 2018 The 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 23 _ "cuelang.org/go/pkg" 24 ) 25 26 func TestBuiltins(t *testing.T) { 27 test := func(pkg, expr string) []*bimport { 28 return []*bimport{{"", 29 []string{fmt.Sprintf("import %q\n(%s)", pkg, expr)}, 30 }} 31 } 32 testExpr := func(expr string) []*bimport { 33 return []*bimport{{"", 34 []string{fmt.Sprintf("(%s)", expr)}, 35 }} 36 } 37 testCases := []struct { 38 instances []*bimport 39 emit string 40 }{{ 41 test("math", "math.Pi"), 42 `3.14159265358979323846264338327950288419716939937510582097494459`, 43 }, { 44 test("math", "math.Floor(math.Pi)"), 45 `3`, 46 }, { 47 test("math", "math.Pi(3)"), 48 `_|_ // cannot call non-function math.Pi (type float)`, 49 }, { 50 test("math", "math.Floor(3, 5)"), 51 `_|_ // too many arguments in call to math.Floor (have 2, want 1)`, 52 }, { 53 test("math", `math.Floor("foo")`), 54 `_|_ // cannot use "foo" (type string) as number in argument 1 to math.Floor`, 55 }, { 56 test("crypto/sha256", `sha256.Sum256("hash me")`), 57 `'\xeb \x1a\xf5\xaa\xf0\xd6\x06)\xd3Ҧ\x1eFl\xfc\x0f\xed\xb5\x17\xad\xd81\xec\xacR5\xe1کc\xd6'`, 58 }, { 59 test("crypto/md5", `len(md5.Sum("hash me"))`), 60 `16`, 61 }, { 62 test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<3})`), 63 `_|_ // error in call to encoding/yaml.Validate: a: invalid value 4 (out of bound <3)`, 64 }, { 65 test("encoding/yaml", `yaml.Validate("a: 2\n---\na: 4", {a:<5})`), 66 `true`, 67 }, { 68 test("encoding/yaml", `yaml.Validate("a: 2\n", {a:<5, b:int})`), 69 `_|_ // error in call to encoding/yaml.Validate: b: incomplete value int`, 70 }, { 71 test("strconv", `strconv.FormatUint(64, 16)`), 72 `"40"`, 73 }, { 74 test("regexp", `regexp.Find(#"f\w\w"#, "afoot")`), 75 `"foo"`, 76 }, { 77 test("regexp", `regexp.Find(#"f\w\w"#, "bar")`), 78 `_|_ // error in call to regexp.Find: no match`, 79 }, { 80 testExpr(`len([1, 2, 3])`), 81 `3`, 82 }, { 83 testExpr(`len("foo")`), 84 `3`, 85 }, { 86 test("encoding/json", `json.MarshalStream([{a: 1}, {b: 2}])`), 87 `"""` + "\n\t{\"a\":1}\n\t{\"b\":2}\n\n\t" + `"""`, 88 }, { 89 test("encoding/json", `{ 90 x: int 91 y: json.Marshal({a: x}) 92 }`), 93 `{ 94 x: int 95 y: _|_ // cannot convert incomplete value "int" to JSON 96 }`, 97 }, { 98 test("encoding/yaml", `yaml.MarshalStream([{a: 1}, {b: 2}])`), 99 `"""` + "\n\ta: 1\n\t---\n\tb: 2\n\n\t" + `"""`, 100 }, { 101 test("struct", `struct.MinFields(0) & ""`), 102 `_|_ // conflicting values struct.MinFields(0) and "" (mismatched types struct and string)`, 103 }, { 104 test("struct", `struct.MinFields(0) & {a: 1}`), 105 `{ 106 a: 1 107 }`, 108 }, { 109 test("struct", `struct.MinFields(2) & {a: 1}`), 110 // TODO: original value may be better. 111 // `_|_ // invalid value {a:1} (does not satisfy struct.MinFields(2))`, 112 `_|_ // invalid value {a:1} (does not satisfy struct.MinFields(2)): len(fields) < MinFields(2) (1 < 2)`, 113 }, { 114 test("time", `time.Time & "1937-01-01T12:00:27.87+00:20"`), 115 `"1937-01-01T12:00:27.87+00:20"`, 116 }, { 117 test("time", `time.Time & "no time"`), 118 `_|_ // invalid value "no time" (does not satisfy time.Time): error in call to time.Time: invalid time "no time"`, 119 }, { 120 test("time", `time.Unix(1500000000, 123456)`), 121 `"2017-07-14T02:40:00.000123456Z"`, 122 }} 123 for i, tc := range testCases { 124 t.Run(fmt.Sprint(i), func(t *testing.T) { 125 insts := cue.Build(makeInstances(tc.instances)) 126 if err := insts[0].Err; err != nil { 127 t.Fatal(err) 128 } 129 v := insts[0].Value() 130 got := fmt.Sprintf("%+v", v) 131 if got != tc.emit { 132 t.Errorf("\n got: %q\nwant: %q", got, tc.emit) 133 } 134 }) 135 } 136 } 137 138 // For debugging purposes. Do not remove. 139 func TestSingleBuiltin(t *testing.T) { 140 t.Skip("error message") 141 142 test := func(pkg, expr string) []*bimport { 143 return []*bimport{{"", 144 []string{fmt.Sprintf("import %q\n(%s)", pkg, expr)}, 145 }} 146 } 147 testCases := []struct { 148 instances []*bimport 149 emit string 150 }{{ 151 test("list", `list.Sort([{a:1}, {b:2}], list.Ascending)`), 152 `_|_ // error in call to list.Sort: less: invalid operands {b:2} and {a:1} to '<' (type struct and struct)`, 153 }} 154 for i, tc := range testCases { 155 t.Run(fmt.Sprint(i), func(t *testing.T) { 156 insts := cue.Build(makeInstances(tc.instances)) 157 if err := insts[0].Err; err != nil { 158 t.Fatal(err) 159 } 160 v := insts[0].Value() 161 got := fmt.Sprint(v) 162 if got != tc.emit { 163 t.Errorf("\n got: %s\nwant: %s", got, tc.emit) 164 } 165 }) 166 } 167 }