blob: 83cd80d248b43ec8a73a0b230679cbeb4a9f98a3 [file] [log] [blame]
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001// 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
15package cue
16
17import (
Marcel van Lohuizen7b5d2fd2018-12-11 16:34:56 +010018 "fmt"
Marcel van Lohuizen7b5d2fd2018-12-11 16:34:56 +010019 "strings"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010020 "testing"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010021)
22
Marcel van Lohuizen7b5d2fd2018-12-11 16:34:56 +010023func TestBuiltins(t *testing.T) {
24 test := func(pkg, expr string) []*bimport {
25 return []*bimport{&bimport{"",
26 []string{fmt.Sprintf("import %q\n(%s)", pkg, expr)},
27 }}
28 }
29 testExpr := func(expr string) []*bimport {
30 return []*bimport{&bimport{"",
31 []string{fmt.Sprintf("(%s)", expr)},
32 }}
33 }
34 testCases := []struct {
35 instances []*bimport
36 emit string
37 }{{
38 test("math", "math.Pi"),
39 `3.14159265358979323846264338327950288419716939937510582097494459`,
40 }, {
41 test("math", "math.Floor(math.Pi)"),
42 `3`,
43 }, {
44 test("math", "math.Pi(3)"),
45 `_|_(<0>.Pi:cannot call non-function 3.14159265358979323846264338327950288419716939937510582097494459 (type float))`,
46 }, {
47 test("math", "math.Floor(3, 5)"),
48 `_|_(<0>.Floor (3,5):number of arguments does not match (1 vs 2))`,
49 }, {
50 test("math", `math.Floor("foo")`),
51 `_|_(<0>.Floor ("foo"):argument 1 requires type number, found string)`,
52 }, {
53 test("encoding/hex", `hex.Encode("foo")`),
54 `"666f6f"`,
55 }, {
56 test("encoding/hex", `hex.Decode(hex.Encode("foo"))`),
57 `'foo'`,
58 }, {
59 test("encoding/hex", `hex.Decode("foo")`),
60 `_|_(<0>.Decode ("foo"):call error: encoding/hex: invalid byte: U+006F 'o')`,
61 }, {
62 test("strconv", `strconv.FormatUint(64, 16)`),
63 `"40"`,
64 }, {
65 // Find a better alternative, as this call should go.
66 test("strconv", `strconv.FormatFloat(3.02, 300, 4, 64)`),
67 `_|_(<0>.FormatFloat (3.02,300,4,64):argument 1 out of range: has 9 > 8 bits)`,
68 }, {
69 // Find a better alternative, as this call should go.
70 test("strconv", `strconv.FormatFloat(3.02, -1, 4, 64)`),
71 `_|_(<0>.FormatFloat (3.02,-1,4,64):argument 1 must be a positive integer)`,
72 }, {
73 // Find a better alternative, as this call should go.
74 test("strconv", `strconv.FormatFloat(3.02, 1.0, 4, 64)`),
75 `_|_(<0>.FormatFloat (3.02,1.0,4,64):argument 2 requires type int, found float)`,
76 }, {
77 // Panics
78 test("math", `math.Jacobi(1000, 2000)`),
79 `_|_(<0>.Jacobi (1000,2000):call error: big: invalid 2nd argument to Int.Jacobi: need odd integer but got 2000)`,
80 }, {
81 test("math", `math.Jacobi(1000, 201)`),
82 `1`,
83 }, {
84 test("math", `math.Asin(2.0e400)`),
85 `_|_(<0>.Asin (2.0e+400):invalid argument 0: cue: value was rounded up)`,
86 }, {
87 test("encoding/csv", `csv.Decode("1,2,3\n4,5,6")`),
88 `[["1","2","3"],["4","5","6"]]`,
89 }, {
90 test("strconv", `strconv.FormatBool(true)`),
91 `"true"`,
92 }, {
93 test("strings", `strings.Join(["Hello", "World!"], " ")`),
94 `"Hello World!"`,
95 }, {
96 test("strings", `strings.Join([1, 2], " ")`),
Marcel van Lohuizen4a360992019-05-11 18:18:31 +020097 `_|_(<0>.Join ([1,2]," "):list element 1: not of right kind (int vs string))`,
Marcel van Lohuizen7b5d2fd2018-12-11 16:34:56 +010098 }, {
99 test("math/bits", `bits.Or(0x8, 0x1)`),
100 `9`,
101 }, {
102 testExpr(`len({})`),
103 `0`,
104 }, {
105 testExpr(`len({a: 1, b: 2, <foo>: int, _c: 3})`),
106 `2`,
107 }, {
108 testExpr(`len([1, 2, 3])`),
109 `3`,
110 }, {
111 testExpr(`len("foo")`),
112 `3`,
113 }, {
114 testExpr(`len('f\x20\x20')`),
115 `3`,
Marcel van Lohuizena460fe82019-04-26 10:20:51 +0200116 }, {
117 testExpr(`and([string, "foo"])`),
118 `"foo"`,
119 }, {
120 testExpr(`and([string, =~"fo"]) & "foo"`),
121 `"foo"`,
122 }, {
123 testExpr(`and([])`),
124 `_`,
125 }, {
126 testExpr(`or([1, 2, 3]) & 2`),
127 `2`,
128 }, {
129 testExpr(`or([])`),
130 `_|_(builtin:or:empty or)`,
Marcel van Lohuizen7b5d2fd2018-12-11 16:34:56 +0100131 }}
132 for _, tc := range testCases {
133 t.Run("", func(t *testing.T) {
134 insts := Build(makeInstances(tc.instances))
135 if err := insts[0].Err; err != nil {
136 t.Fatal(err)
137 }
138 got := strings.TrimSpace(fmt.Sprintf("%s\n", insts[0].Value()))
139 if got != tc.emit {
140 t.Errorf("\n got: %s\nwant: %s", got, tc.emit)
141 }
142 })
143 }
144}