...

Source file src/cuelang.org/go/internal/core/adt/closed_test.go

Documentation: cuelang.org/go/internal/core/adt

     1  // Copyright 2020 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 adt_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"cuelang.org/go/cue/parser"
    21  	"cuelang.org/go/internal/core/adt"
    22  	"cuelang.org/go/internal/core/compile"
    23  	"cuelang.org/go/internal/core/eval"
    24  	"cuelang.org/go/internal/core/runtime"
    25  )
    26  
    27  // TestClosedness is a bootstrap and debugging test for developing the
    28  // closedness algorithm. Most details of closedness is tested in the standard
    29  // test suite.
    30  func TestClosedness(t *testing.T) {
    31  	r := runtime.New()
    32  	ctx := eval.NewContext(r, nil)
    33  
    34  	mkStruct := func(info adt.CloseInfo, s string) *adt.StructInfo {
    35  		x, err := parser.ParseExpr("", s)
    36  		if err != nil {
    37  			t.Fatal(err)
    38  		}
    39  		expr, err := compile.Expr(nil, r, "", x)
    40  		if err != nil {
    41  			t.Fatal(err)
    42  		}
    43  		st := expr.Elem().(*adt.StructLit)
    44  		st.Init()
    45  
    46  		return &adt.StructInfo{
    47  			StructLit: st,
    48  			CloseInfo: info,
    49  		}
    50  	}
    51  
    52  	mkRef := func(s string) adt.Expr {
    53  		f := adt.MakeIdentLabel(r, s, "")
    54  		return &adt.FieldReference{Label: f}
    55  	}
    56  
    57  	type test struct {
    58  		f     string
    59  		found bool
    60  	}
    61  
    62  	testCases := []struct {
    63  		desc     string
    64  		n        func() *adt.Vertex
    65  		tests    []test
    66  		required bool
    67  	}{{
    68  		desc: "simple embedding",
    69  		// test: {
    70  		//     a: 1
    71  		//     c: 1
    72  		//
    73  		//     def
    74  		// }
    75  		// def: {
    76  		//     c: 1
    77  		//     d: 1
    78  		// }
    79  		n: func() *adt.Vertex {
    80  			var (
    81  				root  adt.CloseInfo
    82  				embed = root.SpawnEmbed(mkRef("dummy"))
    83  				def   = embed.SpawnRef(nil, false, mkRef("def"))
    84  			)
    85  			return &adt.Vertex{
    86  				Structs: []*adt.StructInfo{
    87  					mkStruct(root, "{a: 1, c: 1}"),
    88  					mkStruct(def, "{c: 1, d: 1}"),
    89  				},
    90  			}
    91  		},
    92  		tests: []test{
    93  			{"a", true},
    94  			{"c", true},
    95  			{"d", true},
    96  			{"e", false}, // allowed, but not found
    97  		},
    98  		required: false,
    99  	}, {
   100  		desc: "closing embedding",
   101  		// test: {
   102  		//     a: 1
   103  		//     c: 1
   104  		//
   105  		//     #def
   106  		// }
   107  		// #def: {
   108  		//     c: 1
   109  		//     d: 1
   110  		// }
   111  		n: func() *adt.Vertex {
   112  			var (
   113  				root  adt.CloseInfo
   114  				embed = root.SpawnEmbed(mkRef("dummy"))
   115  				def   = embed.SpawnRef(nil, true, mkRef("#def"))
   116  			)
   117  			return &adt.Vertex{
   118  				Structs: []*adt.StructInfo{
   119  					mkStruct(root, "{a: 1, c: 1}"),
   120  					mkStruct(def, "{c: 1, d: 1}"),
   121  				},
   122  			}
   123  		},
   124  		tests: []test{
   125  			{"a", true},
   126  			{"c", true},
   127  			{"d", true},
   128  			{"e", false},
   129  		},
   130  		required: true,
   131  	}, {
   132  		desc: "narrow down definitions in subfields",
   133  		// test: #foo
   134  		// test: {
   135  		//     a: 1
   136  		//     b: 1
   137  		// }
   138  		// #foo: {
   139  		//     c: #bar
   140  		//     c: #baz
   141  		//     c: d: 1
   142  		//     c: e: 1
   143  		// }
   144  		// #bar: {
   145  		//     d: 1
   146  		//     e: 1
   147  		// }
   148  		// #baz: {
   149  		//     d: 1
   150  		//     f: 1
   151  		// }
   152  		n: func() *adt.Vertex {
   153  			var (
   154  				root adt.CloseInfo
   155  				foo  = root.SpawnRef(nil, true, mkRef("#foo"))
   156  				bar  = foo.SpawnRef(nil, true, mkRef("#bar"))
   157  				baz  = foo.SpawnRef(nil, true, mkRef("#baz"))
   158  			)
   159  			return &adt.Vertex{
   160  				Structs: []*adt.StructInfo{
   161  					mkStruct(root, "{a: 1, b:1}"),
   162  					mkStruct(foo, "{d: 1, e: 1}"),
   163  					mkStruct(bar, "{d: 1, e: 1}"),
   164  					mkStruct(baz, "{d: 1, f: 1}"),
   165  				},
   166  			}
   167  		},
   168  		tests: []test{
   169  			{"a", false},
   170  			{"b", false},
   171  			{"d", true},
   172  			{"e", false},
   173  			{"f", false},
   174  		},
   175  		required: true,
   176  	}, {
   177  		desc: "chained references",
   178  		// test: foo
   179  		// test: {
   180  		//     a: 1
   181  		//     b: 1
   182  		// }
   183  		// foo: bar
   184  		// bar: {
   185  		//     #baz
   186  		//     e: 1
   187  		// }
   188  		// #baz: {
   189  		//     c: 1
   190  		//     d: 1
   191  		// }
   192  		n: func() *adt.Vertex {
   193  			var (
   194  				root adt.CloseInfo
   195  				foo  = root.SpawnRef(nil, false, mkRef("foo"))
   196  				bar  = foo.SpawnRef(nil, false, mkRef("bar"))
   197  				baz  = bar.SpawnEmbed(mkRef("#baz"))
   198  				def  = baz.SpawnRef(nil, true, mkRef("#baz"))
   199  			)
   200  			return &adt.Vertex{
   201  				Structs: []*adt.StructInfo{
   202  					mkStruct(bar, "{e: 1}"),
   203  					mkStruct(def, "{c: 1, d: 1}"),
   204  					mkStruct(root, "{a: 1, c: 1}"),
   205  				},
   206  			}
   207  		},
   208  		tests: []test{
   209  			{"a", false},
   210  			{"c", true},
   211  			{"d", true},
   212  			{"e", true},
   213  			{"f", false},
   214  		},
   215  		required: true,
   216  	}, {
   217  		desc: "conjunction embedding",
   218  		// test: foo
   219  		// test: {
   220  		//     a: 1
   221  		//     b: 1
   222  		// }
   223  		// foo: {
   224  		//     #bar & #baz
   225  		//     f: 1
   226  		// }
   227  		// #bar: {
   228  		//     c: 1
   229  		//     d: 1
   230  		// }
   231  		// #baz: {
   232  		//     d: 1
   233  		// }
   234  		// #baz: {
   235  		//     e: 1
   236  		// }
   237  		n: func() *adt.Vertex {
   238  			var (
   239  				root  adt.CloseInfo
   240  				foo   = root.SpawnRef(nil, false, mkRef("foo"))
   241  				embed = foo.SpawnEmbed(mkRef("dummy"))
   242  				bar   = embed.SpawnRef(nil, true, mkRef("#bar"))
   243  				baz   = embed.SpawnRef(nil, true, mkRef("#baz"))
   244  			)
   245  			return &adt.Vertex{
   246  				Structs: []*adt.StructInfo{
   247  					mkStruct(root, "{a: 1, c: 1}"),
   248  					mkStruct(foo, "{f: 1}"),
   249  					mkStruct(bar, "{c: 1, d: 1}"),
   250  					mkStruct(baz, "{d: 1}"),
   251  					mkStruct(baz, "{e: 1}"),
   252  				},
   253  			}
   254  		},
   255  		tests: []test{
   256  			{"a", false},
   257  			{"c", false},
   258  			{"d", true},
   259  			{"e", false},
   260  			{"f", true},
   261  			{"g", false},
   262  		},
   263  		required: true,
   264  	}, {
   265  		desc: "local closing",
   266  		// test: {
   267  		//     #def
   268  		//     a: 1
   269  		//     b: 1
   270  		// }
   271  		// test: {
   272  		//     c: 1
   273  		//     d: 1
   274  		// }
   275  		// #def: {
   276  		//     c: 1
   277  		//     e: 1
   278  		// }
   279  		n: func() *adt.Vertex {
   280  			var (
   281  				root adt.CloseInfo
   282  				// isolate local struct.
   283  				spawned = root.SpawnRef(nil, false, mkRef("dummy"))
   284  				embed   = spawned.SpawnEmbed(mkRef("dummy"))
   285  				def     = embed.SpawnRef(nil, true, mkRef("#def"))
   286  			)
   287  			return &adt.Vertex{
   288  				Structs: []*adt.StructInfo{
   289  					mkStruct(spawned, "{a: 1, b: 1}"),
   290  					mkStruct(root, "{c: 1, d: 1}"),
   291  					mkStruct(def, "{c: 1, e: 1}"),
   292  				},
   293  			}
   294  		},
   295  		tests: []test{
   296  			{"d", false},
   297  			{"a", true},
   298  			{"c", true},
   299  			{"e", true},
   300  			{"f", false},
   301  		},
   302  		required: true,
   303  	}, {
   304  		desc: "local closing of def",
   305  		// #test: {
   306  		//     #def
   307  		//     a: 1
   308  		//     b: 1
   309  		// }
   310  		// #test: {
   311  		//     c: 1
   312  		//     d: 1
   313  		// }
   314  		// #def: {
   315  		//     c: 1
   316  		//     e: 1
   317  		// }
   318  		n: func() *adt.Vertex {
   319  			var (
   320  				root adt.CloseInfo
   321  				test = root.SpawnRef(nil, true, mkRef("#test"))
   322  				// isolate local struct.
   323  				spawned = test.SpawnRef(nil, false, mkRef("dummy"))
   324  				embed   = spawned.SpawnEmbed(mkRef("dummy"))
   325  				def     = embed.SpawnRef(nil, true, mkRef("#def"))
   326  			)
   327  			return &adt.Vertex{
   328  				Structs: []*adt.StructInfo{
   329  					mkStruct(spawned, "{a: 1, b: 1}"),
   330  					mkStruct(test, "{c: 1, d: 1}"),
   331  					mkStruct(def, "{c: 1, e: 1}"),
   332  				},
   333  			}
   334  		},
   335  		tests: []test{
   336  			{"a", true},
   337  			{"d", false},
   338  			{"c", true},
   339  			{"e", true},
   340  			{"f", false},
   341  		},
   342  		required: true,
   343  	}, {
   344  		desc: "branching",
   345  		// test: #foo
   346  		// #foo: {
   347  		//     c: #bar1
   348  		//     c: #bar2
   349  		// }
   350  		// #bar1: {
   351  		//     d: #baz1
   352  		//     d: #baz2
   353  		// }
   354  		// #bar2: {
   355  		//     d: #baz3
   356  		//     d: {#baz4}
   357  		// }
   358  		// #baz1: e: 1
   359  		// #baz2: e: 1
   360  		// #baz3: e: 1
   361  		// #baz4: e: 1
   362  		n: func() *adt.Vertex {
   363  			var (
   364  				root adt.CloseInfo
   365  				foo  = root.SpawnRef(nil, true, mkRef("#foo"))
   366  				bar1 = foo.SpawnRef(nil, true, mkRef("#bar1"))
   367  				bar2 = foo.SpawnRef(nil, true, mkRef("#bar2"))
   368  				baz1 = bar1.SpawnRef(nil, true, mkRef("#baz1"))
   369  				baz2 = bar1.SpawnRef(nil, true, mkRef("#baz2"))
   370  				baz3 = bar2.SpawnRef(nil, true, mkRef("#baz3"))
   371  				spw3 = bar2.SpawnRef(nil, false, mkRef("spw3"))
   372  				emb2 = spw3.SpawnEmbed(mkRef("emb"))
   373  				baz4 = emb2.SpawnRef(nil, true, mkRef("#baz4"))
   374  			)
   375  			return &adt.Vertex{
   376  				Structs: []*adt.StructInfo{
   377  					mkStruct(root, "{}"),
   378  					mkStruct(foo, "{}"),
   379  					mkStruct(bar1, "{}"),
   380  					mkStruct(bar2, "{}"),
   381  					mkStruct(baz1, "{e: 1, f: 1, g: 1}"),
   382  					mkStruct(baz2, "{e: 1, f: 1, g: 1}"),
   383  					mkStruct(baz3, "{e: 1, g: 1}"),
   384  					mkStruct(baz4, "{e: 1, f: 1}"),
   385  				},
   386  			}
   387  		},
   388  		tests: []test{
   389  			{"a", false},
   390  			{"e", true},
   391  			{"f", false},
   392  			{"g", false},
   393  		},
   394  		required: true,
   395  	}}
   396  	// TODO:
   397  	// dt1: {
   398  	// 	#Test: {
   399  	// 		#SSH:   !~"^ssh://"
   400  	// 		source: #SSH | #Test
   401  	// 	}
   402  
   403  	// 	foo: #Test & {
   404  	// 		source: "http://blablabla"
   405  	// 	}
   406  
   407  	// 	bar: #Test & {
   408  	// 		source: foo
   409  	// 	}
   410  	// }
   411  	//
   412  	// -----
   413  	for _, tc := range testCases {
   414  		t.Run(tc.desc, func(t *testing.T) {
   415  			n := tc.n()
   416  			for _, sub := range tc.tests {
   417  				t.Run(sub.f, func(t *testing.T) {
   418  					f := adt.MakeIdentLabel(r, sub.f, "")
   419  
   420  					ok, required := adt.Accept(ctx, n, f)
   421  					if ok != sub.found || required != tc.required {
   422  						t.Errorf("got (%v, %v); want (%v, %v)",
   423  							ok, required, sub.found, tc.required)
   424  					}
   425  				})
   426  			}
   427  		})
   428  	}
   429  }
   430  

View as plain text