Skip to content

Commit 826f28c

Browse files
committed
internal/cuetxtar: allow using a fallback golden set
This allows different implementations of the same functionality to share the same golden file set, if overlapping. This introduces a version type for the evaluator used by TestEvalAlpha. TestEvalAlpha is added as a test case for this. As the version has no effect as of now, it tests that the fallback mechanism works properly for all current tests. Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I71484daa6eb3817e575d3ada2320e4608b2a0f17 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1167861 Reviewed-by: Daniel Martí <[email protected]> Unity-Result: CUE porcuepine <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent ca254d6 commit 826f28c

File tree

3 files changed

+86
-13
lines changed

3 files changed

+86
-13
lines changed

internal/core/adt/context.go

+12
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,16 @@ func New(v *Vertex, cfg *Config) *OpContext {
197197
return ctx
198198
}
199199

200+
type EvaluatorVersion int
201+
202+
const (
203+
DefaultVersion EvaluatorVersion = iota
204+
205+
// The DevVersion is used for new implementations of the evaluator that
206+
// do not cover all features of the CUE language yet.
207+
DevVersion
208+
)
209+
200210
// An OpContext implements CUE's unification operation. It only
201211
// operates on values that are created with the Runtime with which an OpContext
202212
// is associated. An OpContext is not goroutine safe and only one goroutine may
@@ -205,6 +215,8 @@ type OpContext struct {
205215
Runtime
206216
Format func(Node) string
207217

218+
Version EvaluatorVersion
219+
208220
nest int
209221

210222
stats stats.Counts

internal/core/adt/eval_test.go

+37-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"cuelang.org/go/cue"
2626
"cuelang.org/go/cue/cuecontext"
27+
"cuelang.org/go/cue/errors"
2728
"cuelang.org/go/internal/core/adt"
2829
"cuelang.org/go/internal/core/debug"
2930
"cuelang.org/go/internal/core/eval"
@@ -51,7 +52,7 @@ func TestEval(t *testing.T) {
5152
}
5253

5354
test.Run(t, func(tc *cuetxtar.Test) {
54-
runEvalTest(tc)
55+
runEvalTest(tc, adt.DefaultVersion)
5556
})
5657
}
5758

@@ -63,7 +64,29 @@ var needFix = map[string]string{
6364
"DIR/NAME": "reason",
6465
}
6566

66-
func runEvalTest(t *cuetxtar.Test) {
67+
var todoAlpha = map[string]string{
68+
"DIR/NAME": "reason",
69+
}
70+
71+
func TestEvalAlpha(t *testing.T) {
72+
test := cuetxtar.TxTarTest{
73+
Root: "../../../cue/testdata",
74+
Name: "evalalpha",
75+
Fallback: "eval", // Allow eval golden files to pass these tests.
76+
Skip: alwaysSkip,
77+
ToDo: todoAlpha,
78+
}
79+
80+
if *todo {
81+
test.ToDo = nil
82+
}
83+
84+
test.Run(t, func(t *cuetxtar.Test) {
85+
runEvalTest(t, adt.DevVersion)
86+
})
87+
}
88+
89+
func runEvalTest(t *cuetxtar.Test, version adt.EvaluatorVersion) {
6790
a := t.Instance()
6891
r := runtime.New()
6992

@@ -75,6 +98,7 @@ func runEvalTest(t *cuetxtar.Test) {
7598

7699
e := eval.New(r)
77100
ctx := e.NewContext(v)
101+
ctx.Version = version
78102
v.Finalize(ctx)
79103

80104
stats := ctx.Stats()
@@ -103,8 +127,11 @@ func runEvalTest(t *cuetxtar.Test) {
103127

104128
// TestX is for debugging. Do not delete.
105129
func TestX(t *testing.T) {
106-
verbosity := 0
107-
verbosity = 1 // uncomment to turn logging off.
130+
var verbosity int
131+
verbosity = 1 // comment to turn logging off.
132+
133+
var version adt.EvaluatorVersion
134+
version = adt.DevVersion // comment to use default implementation.
108135

109136
in := `
110137
-- cue.mod/module.cue --
@@ -136,11 +163,15 @@ module: "mod.test"
136163

137164
e := eval.New(r)
138165
ctx := e.NewContext(v)
166+
ctx.Version = version
139167
v.Finalize(ctx)
140168
adt.Verbosity = 0
141169

142-
// b := validate.Validate(ctx, v, &validate.Config{Concrete: true})
143-
// t.Log(errors.Details(b.Err, nil))
170+
if b := validate.Validate(ctx, v, &validate.Config{
171+
AllErrors: true,
172+
}); b != nil {
173+
t.Log(errors.Details(b.Err, nil))
174+
}
144175

145176
t.Error(debug.NodeString(r, v, nil))
146177

internal/cuetxtar/txtar.go

+37-7
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ type TxTarTest struct {
4949
// TODO: by default derive from the current base directory name.
5050
Name string
5151

52+
// Fallback allows the golden tests named by Fallback to pass tests in
53+
// case the golden file corresponding to Name does not exist.
54+
// The feature can be used to have two implementations of the same
55+
// functionality share the same test sets.
56+
Fallback string
57+
5258
// Skip is a map of tests to skip; the key is the test name; the value is the
5359
// skip message.
5460
Skip map[string]string
@@ -92,6 +98,7 @@ type Test struct {
9298
*testing.T
9399

94100
prefix string
101+
fallback string
95102
buf *bytes.Buffer // the default buffer
96103
outFiles []file
97104

@@ -109,14 +116,15 @@ type Test struct {
109116
func (t *Test) Write(b []byte) (n int, err error) {
110117
if t.buf == nil {
111118
t.buf = &bytes.Buffer{}
112-
t.outFiles = append(t.outFiles, file{t.prefix, t.buf})
119+
t.outFiles = append(t.outFiles, file{t.prefix, t.fallback, t.buf})
113120
}
114121
return t.buf.Write(b)
115122
}
116123

117124
type file struct {
118-
name string
119-
buf *bytes.Buffer
125+
name string
126+
fallback string
127+
buf *bytes.Buffer
120128
}
121129

122130
// HasTag reports whether the tag with the given key is defined
@@ -201,10 +209,13 @@ func (t *Test) WriteFile(f *ast.File) {
201209
// in the txtar file. If name is empty, data will be written to the test
202210
// output and checked against "out/\(testName)".
203211
func (t *Test) Writer(name string) io.Writer {
212+
var fallback string
204213
switch name {
205214
case "":
206215
name = t.prefix
216+
fallback = t.fallback
207217
default:
218+
fallback = path.Join(t.fallback, name)
208219
name = path.Join(t.prefix, name)
209220
}
210221

@@ -215,7 +226,7 @@ func (t *Test) Writer(name string) io.Writer {
215226
}
216227

217228
w := &bytes.Buffer{}
218-
t.outFiles = append(t.outFiles, file{name, w})
229+
t.outFiles = append(t.outFiles, file{name, fallback, w})
219230

220231
if name == t.prefix {
221232
t.buf = w
@@ -326,6 +337,11 @@ func (x *TxTarTest) Run(t *testing.T, f func(tc *Test)) {
326337
prefix: path.Join("out", x.Name),
327338
LoadConfig: x.LoadConfig,
328339
}
340+
if x.Fallback != "" {
341+
tc.fallback = path.Join("out", x.Fallback)
342+
} else {
343+
tc.fallback = tc.prefix
344+
}
329345

330346
if tc.HasTag("skip") {
331347
t.Skip()
@@ -341,13 +357,14 @@ func (x *TxTarTest) Run(t *testing.T, f func(tc *Test)) {
341357
update := false
342358

343359
for i, f := range a.Files {
344-
345-
if strings.HasPrefix(f.Name, tc.prefix) && (f.Name == tc.prefix || f.Name[len(tc.prefix)] == '/') {
360+
hasPrefix := func(s string) bool {
346361
// It's either "\(tc.prefix)" or "\(tc.prefix)/..." but not some other name
347362
// that happens to start with tc.prefix.
348-
tc.hasGold = true
363+
return strings.HasPrefix(f.Name, s) && (f.Name == s || f.Name[len(s)] == '/')
349364
}
350365

366+
tc.hasGold = hasPrefix(tc.prefix) || hasPrefix(tc.fallback)
367+
351368
// Format CUE files as required
352369
if tc.HasTag("noformat") || !strings.HasSuffix(f.Name, ".cue") {
353370
continue
@@ -377,6 +394,10 @@ func (x *TxTarTest) Run(t *testing.T, f func(tc *Test)) {
377394
k = i
378395
break
379396
}
397+
if i, ok := index[sub.fallback]; ok {
398+
k = i
399+
break
400+
}
380401
}
381402

382403
files := a.Files[:k:k]
@@ -394,6 +415,15 @@ func (x *TxTarTest) Run(t *testing.T, f func(tc *Test)) {
394415
if bytes.Equal(gold.Data, result) {
395416
continue
396417
}
418+
} else if i, ok := index[sub.fallback]; ok {
419+
gold.Data = a.Files[i].Data
420+
421+
// Use the golden file of the fallback set if it matches.
422+
if bytes.Equal(gold.Data, result) {
423+
gold.Name = sub.fallback
424+
delete(index, sub.fallback)
425+
continue
426+
}
397427
}
398428

399429
if cuetest.UpdateGoldenFiles {

0 commit comments

Comments
 (0)