cuelang.org/go@v0.13.0/internal/core/export/self_test.go (about)

     1  // Copyright 2022 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 export_test
    16  
    17  import (
    18  	"bytes"
    19  	"slices"
    20  	"strings"
    21  	"testing"
    22  
    23  	"cuelang.org/go/cue"
    24  	"cuelang.org/go/cue/ast"
    25  	"cuelang.org/go/cue/build"
    26  	"cuelang.org/go/cue/cuecontext"
    27  	"cuelang.org/go/cue/errors"
    28  	"cuelang.org/go/cue/format"
    29  	"cuelang.org/go/internal/core/export"
    30  	"cuelang.org/go/internal/core/runtime"
    31  	"cuelang.org/go/internal/cuedebug"
    32  	"cuelang.org/go/internal/cuetdtest"
    33  	"cuelang.org/go/internal/cuetxtar"
    34  	"cuelang.org/go/internal/diff"
    35  	"cuelang.org/go/internal/types"
    36  	"golang.org/x/tools/txtar"
    37  )
    38  
    39  func TestSelfContained(t *testing.T) {
    40  	test := cuetxtar.TxTarTest{
    41  		Name: "self",
    42  		Root: "./testdata/selfcontained",
    43  
    44  		Matrix: cuetdtest.FullMatrix,
    45  
    46  		ToDo: map[string]string{
    47  			"self-v3/selfcontained/import": `wa: reference "_hidden_567475F3" not found:`,
    48  
    49  			"self/selfcontained/cyclic":            `reference not properly substituted`,
    50  			"self-v3/selfcontained/cyclic":         `reference not properly substituted`,
    51  			"self-v3-noshare/selfcontained/cyclic": `reference not properly substituted`,
    52  		},
    53  	}
    54  
    55  	test.Run(t, func(t *cuetxtar.Test) {
    56  		r := t.CueContext()
    57  
    58  		a := t.Instances()
    59  
    60  		v := buildFile(t.T, r, a[0])
    61  
    62  		p, ok := t.Value("path")
    63  		if ok {
    64  			v = v.LookupPath(cue.ParsePath(p))
    65  		}
    66  
    67  		var tValue types.Value
    68  		v.Core(&tValue)
    69  
    70  		self := *export.All
    71  		self.SelfContained = true
    72  
    73  		w := t.Writer("default")
    74  
    75  		test := func() {
    76  			file, errs := self.Def(tValue.R, "", tValue.V)
    77  
    78  			errors.Print(w, errs, nil)
    79  			_, _ = w.Write(formatNode(t.T, file))
    80  
    81  			vf := patch(t.T, r, t.Archive, file)
    82  			doDiff(t.T, v, vf)
    83  
    84  			v = v.Unify(vf)
    85  			doDiff(t.T, v, vf)
    86  		}
    87  		test()
    88  
    89  		if _, ok := t.Value("inlineImports"); ok {
    90  			w = t.Writer("expand_imports")
    91  			self.InlineImports = true
    92  			test()
    93  		}
    94  	})
    95  }
    96  
    97  func buildFile(t *testing.T, r *cue.Context, b *build.Instance) cue.Value {
    98  	t.Helper()
    99  	v := r.BuildInstance(b)
   100  	if err := v.Err(); err != nil {
   101  		t.Fatal(errors.Details(err, nil))
   102  	}
   103  	return v
   104  }
   105  
   106  // patch replaces the package at the root of the Archive with the given CUE
   107  // file.
   108  func patch(t *testing.T, r *cue.Context, orig *txtar.Archive, f *ast.File) cue.Value {
   109  	a := *orig
   110  	a.Files = slices.Clone(orig.Files)
   111  
   112  	k := 0
   113  	for _, f := range a.Files {
   114  		if strings.HasSuffix(f.Name, ".cue") && !strings.ContainsRune(f.Name, '/') {
   115  			continue
   116  		}
   117  		a.Files[k] = f
   118  		k++
   119  	}
   120  	b, err := format.Node(f)
   121  	if err != nil {
   122  		t.Error(err)
   123  	}
   124  
   125  	a.Files = append(a.Files, txtar.File{
   126  		Name: "in.cue",
   127  		Data: b,
   128  	})
   129  
   130  	instance := cuetxtar.Load(&a, t.TempDir())[0]
   131  	if instance.Err != nil {
   132  		t.Fatal(instance.Err)
   133  	}
   134  
   135  	vn := buildFile(t, r, instance)
   136  	if err := vn.Err(); err != nil {
   137  		t.Fatal(err)
   138  	}
   139  	return vn
   140  }
   141  
   142  func doDiff(t *testing.T, v, w cue.Value) {
   143  	var bb bytes.Buffer
   144  	p := diff.Schema
   145  	p.SkipHidden = true
   146  	d, script := p.Diff(v, w)
   147  	if d != diff.Identity {
   148  		diff.Print(&bb, script)
   149  		t.Error(bb.String())
   150  	}
   151  }
   152  
   153  // TestSC is for debugging purposes. Do not delete.
   154  func TestSC(t *testing.T) {
   155  	in := `
   156  -- cue.mod/module.cue --
   157  module: "example.com"
   158  language: version: "v0.9.0"
   159  -- in.cue --
   160  	`
   161  	if strings.HasSuffix(strings.TrimSpace(in), ".cue --") {
   162  		t.Skip()
   163  	}
   164  
   165  	a := txtar.Parse([]byte(in))
   166  	instance := cuetxtar.Load(a, t.TempDir())[0]
   167  	if instance.Err != nil {
   168  		t.Fatal(instance.Err)
   169  	}
   170  
   171  	version := cuecontext.EvalDefault
   172  	version = cuecontext.EvalExperiment // Uncomment for eval V3
   173  	r := cuecontext.New(cuecontext.EvaluatorVersion(version))
   174  	(*runtime.Runtime)(r).SetDebugOptions(&cuedebug.Config{
   175  		Sharing: true,
   176  		LogEval: 1,
   177  	})
   178  
   179  	v := buildFile(t, r, instance)
   180  
   181  	v = v.LookupPath(cue.ParsePath("a.b"))
   182  
   183  	var tValue types.Value
   184  	v.Core(&tValue)
   185  	self := export.All
   186  	self.SelfContained = true
   187  	self.InlineImports = true
   188  
   189  	file, errs := self.Def(tValue.R, "", tValue.V)
   190  	if errs != nil {
   191  		t.Fatal(errs)
   192  	}
   193  
   194  	b, _ := format.Node(file)
   195  	t.Error(string(b))
   196  
   197  	vf := patch(t, r, a, file)
   198  	doDiff(t, v, vf)
   199  }