this repo has no description
0
fork

Configure Feed

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

internal/cuetxtar: fix two inline runner bugs

Fix two bugs in the inline test framework:

1. Generator (eqFillAttrStr): re-indenting
a multiline expression added the indent
prefix to blank lines, producing
whitespace-only lines that violated
CUE's multiline-string whitespace rule
("non-matching whitespace"). Fix: after
re-indentation, strip all-whitespace
lines back to empty.

2. isInlineMode: parser.ParseFile failure
on a file with a parse error in a @test
attribute body caused the file to be
skipped entirely, yielding a misleading
"archive has no @test directives" error.
Fix: use parser.AllErrors for
error-recovery parsing so @test
directives are still detected in the
partial AST.

Also fix the stray tab on the blank line
in the @test(eq, ...) body in
export/issue2119.txtar that triggered bug 1.

Add regression tests:
- testdata/inline/eq_fill_multiline_blank.txtar
(TestInlineUpdate, generator fix)
- TestIsInlineModeParsedError in
inline_test.go (isInlineMode fix)

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I91ef9020d7b065a177ed4813f4deb221d12d7951
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1235991
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>

+82 -5
+22 -3
cue/testdata/export/issue2119.txtar
··· 10 10 [R+""][0] 11 11 } 12 12 out: yaml.Marshal(x) 13 - @test(leq, {x: {d: ".*"}, out: string}) 13 + @test(eq, {x: {d: ".*"}, out: "d: .*\n"}) 14 14 } 15 15 16 16 original: { ··· 32 32 } 33 33 } 34 34 out: yaml.Marshal(rule) 35 - // TODO(inline): support multi-line strings. 36 - @test(leq, {out: string}) 35 + @test(eq, { 36 + #testableRegexp: { 37 + string 38 + #test: { 39 + in: string 40 + out: _|_ @test(err, code=incomplete, contains="original.#testableRegexp.#test.out: non-concrete value string in operand to +", pos=[21:29, 16:21, 17:3]) 41 + } 42 + } 43 + rule: { 44 + #patterns: { 45 + bar: { 46 + "(.*)" 47 + #test: {in: "testcontent", out: "testcontent"} 48 + } 49 + } 50 + } 51 + out: """ 52 + {} 53 + 54 + """ 55 + }) 37 56 } 38 57 -- out/errors.txt -- 39 58 [incomplete] original.#testableRegexp.#test.out: non-concrete value string in operand to +:
+6 -2
internal/cuetxtar/inline_attr.go
··· 589 589 if !strings.HasSuffix(f.Name, ".cue") { 590 590 continue 591 591 } 592 - af, err := parser.ParseFile(f.Name, f.Data) 593 - if err != nil { 592 + // Use error-recovery parsing so that @test directives are detected 593 + // even when the file has parse errors. Without this, a parse error 594 + // causes us to skip the file entirely, resulting in a misleading 595 + // "archive has no @test directives" report. 596 + af, _ := parser.ParseFile(f.Name, f.Data, parser.AllErrors) 597 + if af == nil { 594 598 continue 595 599 } 596 600 if declsHaveTestAttrs(af.Decls) {
+11
internal/cuetxtar/inline_format.go
··· 72 72 } else { 73 73 indent := r.attrLineIndent(pa) 74 74 exprStr = strings.ReplaceAll(exprStr, "\n", "\n"+indent) 75 + // Strip trailing whitespace from blank lines to avoid 76 + // "non-matching whitespace" parse errors in multiline strings: 77 + // a blank line that is all-whitespace must have zero characters 78 + // (not indentation spaces) to satisfy CUE's multiline string rules. 79 + lines := strings.Split(exprStr, "\n") 80 + for i, line := range lines { 81 + if strings.TrimSpace(line) == "" { 82 + lines[i] = "" 83 + } 84 + } 85 + exprStr = strings.Join(lines, "\n") 75 86 } 76 87 } 77 88 if atStr != "" {
+20
internal/cuetxtar/inline_test.go
··· 19 19 "strings" 20 20 "testing" 21 21 22 + "golang.org/x/tools/txtar" 23 + 22 24 "cuelang.org/go/cue" 23 25 "cuelang.org/go/cue/ast" 24 26 "cuelang.org/go/cue/cuecontext" ··· 863 865 } 864 866 }) 865 867 } 868 + 869 + // TestIsInlineModeParsedError verifies that isInlineMode returns true for an 870 + // archive whose CUE file has a parse error in a @test attribute body. Before 871 + // the AllErrors fix, isInlineMode skipped files with parse errors and returned 872 + // false, producing a misleading "archive has no @test directives" error. 873 + func TestIsInlineModeParsedError(t *testing.T) { 874 + // A @test attribute whose argument is a multiline string with whitespace 875 + // mismatch: the blank line has 1 tab but the closing """ has 2 tabs. 876 + // parser.ParseFile fails on this input, but the partial AST still 877 + // contains the @test attribute. 878 + src := "x: 1 @test(eq, \"\"\"\n\t\thello\n\t\n\t\t\"\"\")" 879 + ar := &txtar.Archive{ 880 + Files: []txtar.File{{Name: "test.cue", Data: []byte(src)}}, 881 + } 882 + if !isInlineMode(ar) { 883 + t.Error("isInlineMode returned false for archive with @test in parse-error file; want true") 884 + } 885 + }
+23
internal/cuetxtar/testdata/inline/eq_fill_multiline_blank.txtar
··· 1 + # Tests that CUE_UPDATE=1 generates valid (parseable) @test(eq, ...) output when 2 + # the filled value contains a string with an embedded blank line. The generator 3 + # re-indents the multiline expression; blank lines must remain completely empty 4 + # (no trailing whitespace) so CUE's multiline-string whitespace rule is satisfied. 5 + -- in/test.cue -- 6 + outer: { 7 + x: { 8 + s: "line1\n\nline2" 9 + } @test(eq) 10 + } 11 + -- out/update/test.cue -- 12 + outer: { 13 + x: { 14 + s: "line1\n\nline2" 15 + } @test(eq, {s: """ 16 + line1 17 + 18 + line2 19 + """}) 20 + } 21 + -- out/status.txt -- 22 + update: output passes run 23 + force: identical to update