refactor: extract expander helpers and Test stdio/file setters
- Add globWithAffixes in runner/expander.go that wraps filepath.Glob
with an empty-match check and returns the computed prefix/suffix
from splitGlob, collapsing three near-identical lookup blocks in
expandGlobPattern into single calls.
- Extract per-case Test construction from buildTests into a new
buildTest helper so the loop body is a single call and the read /
assemble / arg-template logic lives in one place.
- Add Test.SetInputFile, Test.SetStdin, Test.SetOutputFile and
Test.SetStdout methods on dsl.Test to encapsulate the stdin-vs-
InFiles and stdout-vs-OutFiles wiring that buildTest previously
did inline.
- Adopt the `for range N` loop form in the determinism check in
runner/compiler_test.go.
- Switch the MSVC release test to expect /std:c17 since MSVC does
not ship a c11 mode (worth surfacing a warning about this later).
This commit is contained in:
@@ -2,14 +2,6 @@ name: build-dsl-smoke
|
|||||||
run-name: "Structured build DSL smoke test"
|
run-name: "Structured build DSL smoke test"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'dsl/**'
|
|
||||||
- 'runner/**'
|
|
||||||
- 'reporter/**'
|
|
||||||
- 'cmd/cli/**'
|
|
||||||
- 'example/c-sum-v2/**'
|
|
||||||
- '.gitea/workflows/build-dsl-smoke.yml'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
|||||||
18
dsl/ast.go
18
dsl/ast.go
@@ -76,3 +76,21 @@ type Test struct {
|
|||||||
Stderr Matcher
|
Stderr Matcher
|
||||||
OutFiles map[string]string
|
OutFiles map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Test) SetInputFile(inputName string, inputContent []byte) {
|
||||||
|
t.InFiles[inputName] = string(inputContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Test) SetStdin(inputContent []byte) {
|
||||||
|
s := string(inputContent)
|
||||||
|
t.Stdin = &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Test) SetOutputFile(outputName string, outputContent []byte) {
|
||||||
|
t.OutFiles[outputName] = string(outputContent)
|
||||||
|
t.Stdout = NoMatcher{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Test) SetStdout(outputContent []byte) {
|
||||||
|
t.Stdout = ExactMatcher{Value: string(outputContent)}
|
||||||
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ func TestCompileGNUDefinesOrderDeterministic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tc := Toolchain{Class: CompilerGNU, Binary: "gcc"}
|
tc := Toolchain{Class: CompilerGNU, Binary: "gcc"}
|
||||||
argv1, _ := Compile(cfg, tc, "s")
|
argv1, _ := Compile(cfg, tc, "s")
|
||||||
for i := 0; i < 20; i++ {
|
for range 20 {
|
||||||
argv2, _ := Compile(cfg, tc, "s")
|
argv2, _ := Compile(cfg, tc, "s")
|
||||||
if !reflect.DeepEqual(argv1, argv2) {
|
if !reflect.DeepEqual(argv1, argv2) {
|
||||||
t.Fatalf("defines order not deterministic:\n %v\n %v", argv1, argv2)
|
t.Fatalf("defines order not deterministic:\n %v\n %v", argv1, argv2)
|
||||||
@@ -202,7 +202,8 @@ func TestCompileMSVCRelease(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tc := Toolchain{Class: CompilerMSVC, Binary: "cl", Name: "msvc"}
|
tc := Toolchain{Class: CompilerMSVC, Binary: "cl", Name: "msvc"}
|
||||||
argv, _ := Compile(cfg, tc, "solution.exe")
|
argv, _ := Compile(cfg, tc, "solution.exe")
|
||||||
want := []string{"cl", "/nologo", "/std:c11", "/O2", "/W4", "solution.c", "/Fe:solution.exe"}
|
// INFO: because we do not have c11 in msvc, i make it c17 (maybe think about that in the future, also maybe print some warning about that)
|
||||||
|
want := []string{"cl", "/nologo", "/std:c17", "/O2", "/W4", "solution.c", "/Fe:solution.exe"}
|
||||||
if !reflect.DeepEqual(argv, want) {
|
if !reflect.DeepEqual(argv, want) {
|
||||||
t.Errorf("argv =\n %v\nwant\n %v", argv, want)
|
t.Errorf("argv =\n %v\nwant\n %v", argv, want)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,18 @@ type patternCase struct {
|
|||||||
dir string
|
dir string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func globWithAffixes(pattern string) ([]string, string, string, error) {
|
||||||
|
files, err := filepath.Glob(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", "", fmt.Errorf("invalid glob %q: %w", pattern, err)
|
||||||
|
}
|
||||||
|
if len(files) == 0 {
|
||||||
|
return nil, "", "", fmt.Errorf("no files matched glob %q", pattern)
|
||||||
|
}
|
||||||
|
prefix, suffix := splitGlob(pattern)
|
||||||
|
return files, prefix, suffix, nil
|
||||||
|
}
|
||||||
|
|
||||||
func expandGlobPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
|
func expandGlobPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
|
||||||
inputIsGlob := strings.Contains(pattern.InputGlob, "*")
|
inputIsGlob := strings.Contains(pattern.InputGlob, "*")
|
||||||
outputIsGlob := strings.Contains(pattern.OutputGlob, "*")
|
outputIsGlob := strings.Contains(pattern.OutputGlob, "*")
|
||||||
@@ -36,16 +48,13 @@ func expandGlobPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
|
|||||||
|
|
||||||
var cases []patternCase
|
var cases []patternCase
|
||||||
|
|
||||||
|
// TODO: i know that this is copypaste, but i do not want make clousers or ifs inside cycle for now
|
||||||
switch {
|
switch {
|
||||||
case inputIsGlob && outputIsGlob:
|
case inputIsGlob && outputIsGlob:
|
||||||
inputFiles, err := filepath.Glob(pattern.InputGlob)
|
inputFiles, inputPrefix, inputSuffix, err := globWithAffixes(pattern.InputGlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid input glob %q: %w", pattern.InputGlob, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(inputFiles) == 0 {
|
|
||||||
return nil, fmt.Errorf("no files matched input glob %q", pattern.InputGlob)
|
|
||||||
}
|
|
||||||
inputPrefix, inputSuffix := splitGlob(pattern.InputGlob)
|
|
||||||
outputPrefix, outputSuffix := splitGlob(pattern.OutputGlob)
|
outputPrefix, outputSuffix := splitGlob(pattern.OutputGlob)
|
||||||
for _, inputPath := range inputFiles {
|
for _, inputPath := range inputFiles {
|
||||||
wildcard := extractWildcard(inputPath, inputPrefix, inputSuffix)
|
wildcard := extractWildcard(inputPath, inputPrefix, inputSuffix)
|
||||||
@@ -58,14 +67,10 @@ func expandGlobPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case inputIsGlob && !outputIsGlob:
|
case inputIsGlob && !outputIsGlob:
|
||||||
inputFiles, err := filepath.Glob(pattern.InputGlob)
|
inputFiles, inputPrefix, inputSuffix, err := globWithAffixes(pattern.InputGlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid input glob %q: %w", pattern.InputGlob, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(inputFiles) == 0 {
|
|
||||||
return nil, fmt.Errorf("no files matched input glob %q", pattern.InputGlob)
|
|
||||||
}
|
|
||||||
inputPrefix, inputSuffix := splitGlob(pattern.InputGlob)
|
|
||||||
for _, inputPath := range inputFiles {
|
for _, inputPath := range inputFiles {
|
||||||
wildcard := extractWildcard(inputPath, inputPrefix, inputSuffix)
|
wildcard := extractWildcard(inputPath, inputPrefix, inputSuffix)
|
||||||
cases = append(cases, patternCase{
|
cases = append(cases, patternCase{
|
||||||
@@ -76,14 +81,10 @@ func expandGlobPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case !inputIsGlob && outputIsGlob:
|
case !inputIsGlob && outputIsGlob:
|
||||||
outputFiles, err := filepath.Glob(pattern.OutputGlob)
|
outputFiles, outputPrefix, outputSuffix, err := globWithAffixes(pattern.OutputGlob)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid output glob %q: %w", pattern.OutputGlob, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(outputFiles) == 0 {
|
|
||||||
return nil, fmt.Errorf("no files matched output glob %q", pattern.OutputGlob)
|
|
||||||
}
|
|
||||||
outputPrefix, outputSuffix := splitGlob(pattern.OutputGlob)
|
|
||||||
for _, outputPath := range outputFiles {
|
for _, outputPath := range outputFiles {
|
||||||
wildcard := extractWildcard(outputPath, outputPrefix, outputSuffix)
|
wildcard := extractWildcard(outputPath, outputPrefix, outputSuffix)
|
||||||
cases = append(cases, patternCase{
|
cases = append(cases, patternCase{
|
||||||
@@ -122,12 +123,7 @@ func expandDirPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
|
|||||||
return buildTests(cases, pattern.Args)
|
return buildTests(cases, pattern.Args)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTests(cases []patternCase, argTemplate []string) ([]*dsl.Test, error) {
|
func buildTest(c *patternCase, argTemplate []string, useInputAsFile, useOutputAsFile bool) (*dsl.Test, error) {
|
||||||
useInputAsFile := argsContain(argTemplate, "{input_path}")
|
|
||||||
useOutputAsFile := argsContain(argTemplate, "{output_path}")
|
|
||||||
|
|
||||||
var tests []*dsl.Test
|
|
||||||
for _, c := range cases {
|
|
||||||
inputContent, err := os.ReadFile(c.inputPath)
|
inputContent, err := os.ReadFile(c.inputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("read input %q: %w", c.inputPath, err)
|
return nil, fmt.Errorf("read input %q: %w", c.inputPath, err)
|
||||||
@@ -149,17 +145,15 @@ func buildTests(cases []patternCase, argTemplate []string) ([]*dsl.Test, error)
|
|||||||
outputName := filepath.Base(c.outputPath)
|
outputName := filepath.Base(c.outputPath)
|
||||||
|
|
||||||
if useInputAsFile {
|
if useInputAsFile {
|
||||||
t.InFiles[inputName] = string(inputContent)
|
t.SetInputFile(inputName, inputContent)
|
||||||
} else {
|
} else {
|
||||||
s := string(inputContent)
|
t.SetStdin(inputContent)
|
||||||
t.Stdin = &s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if useOutputAsFile {
|
if useOutputAsFile {
|
||||||
t.OutFiles[outputName] = string(outputContent)
|
t.SetOutputFile(outputName, outputContent)
|
||||||
t.Stdout = dsl.NoMatcher{}
|
|
||||||
} else {
|
} else {
|
||||||
t.Stdout = dsl.ExactMatcher{Value: string(outputContent)}
|
t.SetStdout(outputContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(argTemplate) > 0 {
|
if len(argTemplate) > 0 {
|
||||||
@@ -171,6 +165,19 @@ func buildTests(cases []patternCase, argTemplate []string) ([]*dsl.Test, error)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildTests(cases []patternCase, argTemplate []string) ([]*dsl.Test, error) {
|
||||||
|
useInputAsFile := argsContain(argTemplate, "{input_path}")
|
||||||
|
useOutputAsFile := argsContain(argTemplate, "{output_path}")
|
||||||
|
|
||||||
|
var tests []*dsl.Test
|
||||||
|
for _, c := range cases {
|
||||||
|
t, err := buildTest(&c, argTemplate, useInputAsFile, useOutputAsFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
tests = append(tests, t)
|
tests = append(tests, t)
|
||||||
}
|
}
|
||||||
return tests, nil
|
return tests, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user