this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <mpvl@gmail.com>
Change-Id: I71484daa6eb3817e575d3ada2320e4608b2a0f17
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1167861
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+86 -13
+12
internal/core/adt/context.go
··· 197 197 return ctx 198 198 } 199 199 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 + 200 210 // An OpContext implements CUE's unification operation. It only 201 211 // operates on values that are created with the Runtime with which an OpContext 202 212 // is associated. An OpContext is not goroutine safe and only one goroutine may ··· 204 214 type OpContext struct { 205 215 Runtime 206 216 Format func(Node) string 217 + 218 + Version EvaluatorVersion 207 219 208 220 nest int 209 221
+37 -6
internal/core/adt/eval_test.go
··· 24 24 25 25 "cuelang.org/go/cue" 26 26 "cuelang.org/go/cue/cuecontext" 27 + "cuelang.org/go/cue/errors" 27 28 "cuelang.org/go/internal/core/adt" 28 29 "cuelang.org/go/internal/core/debug" 29 30 "cuelang.org/go/internal/core/eval" ··· 51 52 } 52 53 53 54 test.Run(t, func(tc *cuetxtar.Test) { 54 - runEvalTest(tc) 55 + runEvalTest(tc, adt.DefaultVersion) 55 56 }) 56 57 } 57 58 ··· 63 64 "DIR/NAME": "reason", 64 65 } 65 66 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) { 67 90 a := t.Instance() 68 91 r := runtime.New() 69 92 ··· 75 98 76 99 e := eval.New(r) 77 100 ctx := e.NewContext(v) 101 + ctx.Version = version 78 102 v.Finalize(ctx) 79 103 80 104 stats := ctx.Stats() ··· 103 127 104 128 // TestX is for debugging. Do not delete. 105 129 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. 108 135 109 136 in := ` 110 137 -- cue.mod/module.cue -- ··· 136 163 137 164 e := eval.New(r) 138 165 ctx := e.NewContext(v) 166 + ctx.Version = version 139 167 v.Finalize(ctx) 140 168 adt.Verbosity = 0 141 169 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 + } 144 175 145 176 t.Error(debug.NodeString(r, v, nil)) 146 177
+37 -7
internal/cuetxtar/txtar.go
··· 49 49 // TODO: by default derive from the current base directory name. 50 50 Name string 51 51 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 + 52 58 // Skip is a map of tests to skip; the key is the test name; the value is the 53 59 // skip message. 54 60 Skip map[string]string ··· 92 98 *testing.T 93 99 94 100 prefix string 101 + fallback string 95 102 buf *bytes.Buffer // the default buffer 96 103 outFiles []file 97 104 ··· 109 116 func (t *Test) Write(b []byte) (n int, err error) { 110 117 if t.buf == nil { 111 118 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}) 113 120 } 114 121 return t.buf.Write(b) 115 122 } 116 123 117 124 type file struct { 118 - name string 119 - buf *bytes.Buffer 125 + name string 126 + fallback string 127 + buf *bytes.Buffer 120 128 } 121 129 122 130 // HasTag reports whether the tag with the given key is defined ··· 201 209 // in the txtar file. If name is empty, data will be written to the test 202 210 // output and checked against "out/\(testName)". 203 211 func (t *Test) Writer(name string) io.Writer { 212 + var fallback string 204 213 switch name { 205 214 case "": 206 215 name = t.prefix 216 + fallback = t.fallback 207 217 default: 218 + fallback = path.Join(t.fallback, name) 208 219 name = path.Join(t.prefix, name) 209 220 } 210 221 ··· 215 226 } 216 227 217 228 w := &bytes.Buffer{} 218 - t.outFiles = append(t.outFiles, file{name, w}) 229 + t.outFiles = append(t.outFiles, file{name, fallback, w}) 219 230 220 231 if name == t.prefix { 221 232 t.buf = w ··· 326 337 prefix: path.Join("out", x.Name), 327 338 LoadConfig: x.LoadConfig, 328 339 } 340 + if x.Fallback != "" { 341 + tc.fallback = path.Join("out", x.Fallback) 342 + } else { 343 + tc.fallback = tc.prefix 344 + } 329 345 330 346 if tc.HasTag("skip") { 331 347 t.Skip() ··· 341 357 update := false 342 358 343 359 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 { 346 361 // It's either "\(tc.prefix)" or "\(tc.prefix)/..." but not some other name 347 362 // 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)] == '/') 349 364 } 365 + 366 + tc.hasGold = hasPrefix(tc.prefix) || hasPrefix(tc.fallback) 350 367 351 368 // Format CUE files as required 352 369 if tc.HasTag("noformat") || !strings.HasSuffix(f.Name, ".cue") { ··· 377 394 k = i 378 395 break 379 396 } 397 + if i, ok := index[sub.fallback]; ok { 398 + k = i 399 + break 400 + } 380 401 } 381 402 382 403 files := a.Files[:k:k] ··· 392 413 delete(index, sub.name) 393 414 394 415 if bytes.Equal(gold.Data, result) { 416 + continue 417 + } 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) 395 425 continue 396 426 } 397 427 }