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  }