...

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

Documentation: cuelang.org/go/cue

     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  	"strings"
    19  	"testing"
    20  
    21  	"cuelang.org/go/cue"
    22  	"cuelang.org/go/cue/cuecontext"
    23  	"cuelang.org/go/cue/format"
    24  )
    25  
    26  func TestSyntax(t *testing.T) {
    27  	o := func(opts ...cue.Option) []cue.Option {
    28  		return opts
    29  	}
    30  	_ = o
    31  	testCases := []struct {
    32  		name    string
    33  		in      string
    34  		path    string
    35  		options []cue.Option
    36  		out     string
    37  	}{{
    38  		name: "preseve docs",
    39  		in: `
    40  		// Aloha
    41  		hello: "world"
    42  		// Aloha2
    43  		if true {
    44  			// Aloha3
    45  			if true {
    46  				// Aloha4
    47  				hello2: "world"
    48  			}
    49  		}
    50  		`,
    51  		options: o(cue.Docs(true)),
    52  		out: `
    53  {
    54  	// Aloha
    55  	hello: "world"
    56  	// Aloha2
    57  	if true {
    58  		// Aloha3
    59  		if true {
    60  			// Aloha4
    61  			hello2: "world"
    62  		}
    63  	}
    64  }`,
    65  	}, {
    66  		name: "partially resolvable",
    67  		in: `
    68  		x: {}
    69  		t: {name: string}
    70  		output: [ ... {t & x.value}]
    71  		`,
    72  		options: o(cue.ResolveReferences(true)),
    73  		out: `
    74  {
    75  	x: {}
    76  	t: {
    77  		name: string
    78  	}
    79  	output: [...t & x.value]
    80  }`,
    81  	}, {
    82  		name: "issue867",
    83  		path: "output",
    84  		in: `
    85  	x: {}
    86  	t: {name: string}
    87  	output: [ ... {t & x.value}]
    88  	`,
    89  		out: `
    90  {
    91  	[...T & {}.value]
    92  
    93  	//cue:path: t
    94  	let T = {
    95  		name: string
    96  	}
    97  }`}, {
    98  		// Structural errors (and worse) are reported as is.
    99  		name: "structural error",
   100  		in: `
   101  			#List: {
   102  				value: _
   103  				next: #List
   104  			}
   105  			a: b: #List
   106  			`,
   107  		path:    "a",
   108  		options: o(cue.ResolveReferences(true)),
   109  		out: `
   110  {
   111  	b: _|_ // #List.next: structural cycle (and 1 more errors)
   112  }`,
   113  	}, {
   114  		name: "resolveReferences",
   115  		path: "resource",
   116  		in: `
   117  		// User 1
   118  		v1: #Deployment: {
   119  			spec: {
   120  				replicas: int
   121  				containers: [...]
   122  				other: option: int
   123  			}
   124  
   125  			incomplete: {
   126  				// NOTE: the definition of "a" will be out of scope so this
   127  				// reference will not be resolvable.
   128  				// TODO: hoist the definition of "a" into a let expression.
   129  				x: a.x
   130  				y: 1 | 2
   131  				z: [1, 2][a.x]
   132  			}
   133  
   134  			// NOTE: structural cycles are eliminated from disjunctions. This
   135  			// means the semantics of the type is not preserved.
   136  			// TODO: should we change this?
   137  			recursive: #List
   138  		}
   139  
   140  		a: {}
   141  		#D: {}
   142  
   143  		#List: {
   144  			Value: _
   145  			Next: #List | *null
   146  		}
   147  
   148  		parameter: {
   149  			image: string
   150  			replicas: int
   151  		}
   152  
   153  		_mystring: string
   154  
   155  		resource: v1.#Deployment & {
   156  			spec: {
   157  			   replicas: parameter.replicas
   158  			   containers: [{
   159  						image: parameter.image
   160  						name: "main"
   161  						envs: [..._mystring]
   162  				}]
   163  			}
   164  		}
   165  
   166  		parameter: image: *"myimage" | string
   167  		parameter: replicas: *2 | >=1 & <5
   168  
   169  		// User 2
   170  		parameter: replicas: int
   171  
   172  		resource: spec: replicas: parameter.replicas
   173  
   174  		parameter: replicas: 3
   175  		`,
   176  		options: o(cue.ResolveReferences(true)),
   177  		out: `
   178  {
   179  	spec: {
   180  		replicas: 3
   181  		containers: [{
   182  			image: *"myimage" | string
   183  			name:  "main"
   184  			envs: [...string]
   185  		}]
   186  		other: {
   187  			option: int
   188  		}
   189  	}
   190  	incomplete: {
   191  		x: {}.x
   192  		y: 1 | 2
   193  		z: [1, 2][{}.x]
   194  	}
   195  	recursive: {
   196  		Value: _
   197  		Next:  null
   198  	}
   199  }
   200  		`,
   201  	}, {
   202  		name: "issue2339",
   203  		in: `
   204  s: string
   205  if true {
   206  	out: "\(s)": 3
   207  }
   208  	`,
   209  		options: o(cue.ResolveReferences(true)),
   210  		out: `
   211  {
   212  	s: string
   213  	out: {
   214  		"\(s)": 3
   215  	}
   216  }
   217  	`,
   218  	}}
   219  	for _, tc := range testCases {
   220  		t.Run(tc.name, func(t *testing.T) {
   221  			ctx := cuecontext.New()
   222  
   223  			v := ctx.CompileString(tc.in)
   224  			v = v.LookupPath(cue.ParsePath(tc.path))
   225  
   226  			syntax := v.Syntax(tc.options...)
   227  			b, err := format.Node(syntax)
   228  			if err != nil {
   229  				t.Fatal(err)
   230  			}
   231  			got := strings.TrimSpace(string(b))
   232  			want := strings.TrimSpace(tc.out)
   233  			if got != want {
   234  				t.Errorf("got: %v; want %v", got, want)
   235  			}
   236  		})
   237  	}
   238  }
   239  

View as plain text