...

Source file src/cuelang.org/go/cue/builtin_test.go

Documentation: cuelang.org/go/cue

     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  }
   168  

View as plain text