...

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

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

     1  // Copyright 2023 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
    16  
    17  import "strings"
    18  
    19  // The functions and types in this file are use to construct test cases for
    20  // fields_test.go and constraints_test.
    21  
    22  // MatchPatternValue exports matchPatternValue for testing.
    23  func MatchPatternValue(ctx *OpContext, p Value, f Feature, label Value) bool {
    24  	return matchPatternValue(ctx, p, f, label)
    25  }
    26  
    27  // FieldTester is used low-level testing of field insertion. It simulates
    28  // how the evaluator inserts fields. This allows the closedness algorithm to be
    29  // tested independently of the underlying evaluator implementation.
    30  type FieldTester struct {
    31  	*OpContext
    32  	n    *nodeContext
    33  	cc   *closeContext
    34  	Root *Vertex
    35  }
    36  
    37  func NewFieldTester(r Runtime) *FieldTester {
    38  	v := &Vertex{}
    39  	ctx := New(v, &Config{Runtime: r})
    40  	n := v.getNodeContext(ctx, 1)
    41  
    42  	return &FieldTester{
    43  		OpContext: ctx,
    44  		n:         n,
    45  		cc:        v.rootCloseContext(),
    46  		Root:      v,
    47  	}
    48  }
    49  
    50  func (x *FieldTester) Error() string {
    51  	if b, ok := x.n.node.BaseValue.(*Bottom); ok && b.Err != nil {
    52  		return b.Err.Error()
    53  	}
    54  	var errs []string
    55  	for _, a := range x.n.node.Arcs {
    56  		if b, ok := a.BaseValue.(*Bottom); ok && b.Err != nil {
    57  			errs = append(errs, b.Err.Error())
    58  		}
    59  	}
    60  	return strings.Join(errs, "\n")
    61  }
    62  
    63  type declaration func(cc *closeContext)
    64  
    65  // Run simulates a CUE evaluation of the given declarations.
    66  func (x *FieldTester) Run(sub ...declaration) {
    67  	x.cc.incDependent(TEST, nil)
    68  	for i, s := range sub {
    69  		// We want to have i around for debugging purposes. Use i to avoid
    70  		// compiler error.
    71  		_ = i
    72  		s(x.cc)
    73  	}
    74  	x.cc.decDependent(x.n.ctx, TEST, nil)
    75  	x.cc.decDependent(x.n.ctx, ROOT, nil) // REF(decrement:nodeDone)
    76  }
    77  
    78  // Def represents fields that define a definition, such that
    79  // Def(Field("a", "foo"), Field("b", "bar")) represents:
    80  //
    81  //	#D: {
    82  //		a: "foo"
    83  //		b: "bar"
    84  //	}
    85  //
    86  // For some unique #D.
    87  func (x *FieldTester) Def(sub ...declaration) declaration {
    88  	return x.spawn(closeDef, sub...)
    89  }
    90  
    91  func (x *FieldTester) spawn(t closeNodeType, sub ...declaration) declaration {
    92  	return func(cc *closeContext) {
    93  		ci := CloseInfo{cc: cc}
    94  		ci, dc := ci.spawnCloseContext(t)
    95  
    96  		dc.incDependent(TEST, nil)
    97  		for _, sfn := range sub {
    98  			sfn(dc)
    99  		}
   100  		dc.decDependent(x.n.ctx, TEST, nil)
   101  	}
   102  }
   103  
   104  // Embed represents fields embedded within the current node, such that
   105  // Embed(Field("a", "foo"), Def(Field("b", "bar"))) represents:
   106  //
   107  //	{
   108  //		{
   109  //			a: "foo"
   110  //			#D
   111  //		}
   112  //	}
   113  //
   114  // For some #D: b: "bar".
   115  func (x *FieldTester) Embed(sub ...declaration) declaration {
   116  	return x.spawn(closeEmbed, sub...)
   117  }
   118  
   119  // Group represents fields and embeddings within a single set of curly braces.
   120  // This is used to test that an embedding of a closed value closes the struct
   121  // in which it is embedded.
   122  func (x *FieldTester) Group(sub ...declaration) declaration {
   123  	return x.spawn(0, sub...)
   124  }
   125  
   126  // EmbedDef represents fields that define a struct and embedded within the
   127  // current node.
   128  func (x *FieldTester) EmbedDef(sub ...declaration) declaration {
   129  	return x.Embed(x.Def(sub...))
   130  }
   131  
   132  // Field defines a field declaration such that Field("a", "foo") represents
   133  //
   134  //	a: "foo"
   135  //
   136  // The value can be of type string, int64, bool, or Expr.
   137  // Duplicate values (conjuncts) are retained as the deduplication check is
   138  // bypassed for this.
   139  func (x *FieldTester) Field(label string, a any) declaration {
   140  	return x.field(label, a, false)
   141  }
   142  
   143  // FieldDedup is like Field, but enables conjunct deduplication.
   144  func (x *FieldTester) FieldDedup(label string, a any) declaration {
   145  	return x.field(label, a, true)
   146  }
   147  
   148  func (x *FieldTester) field(label string, a any, dedup bool) declaration {
   149  	f := x.StringLabel(label)
   150  
   151  	var v Expr
   152  	switch a := a.(type) {
   153  	case Expr:
   154  		v = a
   155  	case string:
   156  		v = x.NewString(a)
   157  	case int:
   158  		v = x.NewInt64(int64(a))
   159  	case bool:
   160  		v = x.newBool(a)
   161  	default:
   162  		panic("type not supported")
   163  	}
   164  
   165  	return func(cc *closeContext) {
   166  		var c Conjunct
   167  		c.Env = &Environment{Vertex: x.Root}
   168  		c.CloseInfo.cc = cc
   169  		c.x = v
   170  		c.CloseInfo.FromDef = cc.isDef
   171  		c.CloseInfo.FromEmbed = cc.isEmbed
   172  
   173  		x.n.insertArc(f, ArcMember, c, c.CloseInfo, dedup)
   174  	}
   175  }
   176  
   177  // Pat represents a pattern constraint, such that Pat(`<"a"`, "foo") represents
   178  //
   179  //	[<"a"]: "foo"
   180  func (x *FieldTester) Pat(pattern Value, v Expr) declaration {
   181  	if pattern == nil {
   182  		panic("nil pattern")
   183  	}
   184  	if v == nil {
   185  		panic("nil expr")
   186  	}
   187  	return func(cc *closeContext) {
   188  		var c Conjunct
   189  		c.Env = &Environment{Vertex: x.Root}
   190  		c.CloseInfo.cc = cc
   191  		c.x = v
   192  		c.CloseInfo.FromDef = cc.isDef
   193  		c.CloseInfo.FromEmbed = cc.isEmbed
   194  
   195  		x.n.insertPattern(pattern, c)
   196  	}
   197  }
   198  

View as plain text