Files
judge/runner/expander.go
2026-04-05 18:20:42 +03:00

120 lines
3.1 KiB
Go

package runner
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Mond1c/judge/dsl"
)
func expandPattern(pattern *dsl.Pattern, groupTimeout interface{ IsZero() bool }) ([]*dsl.Test, error) {
if pattern.IsDirMode() {
return expandDirPattern(pattern)
}
return expandGlobPattern(pattern)
}
func expandGlobPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
inputFiles, err := filepath.Glob(pattern.InputGlob)
if err != nil {
return nil, fmt.Errorf("invalid input glob %q: %w", pattern.InputGlob, 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)
var tests []*dsl.Test
for _, inputPath := range inputFiles {
wildcard := extractWildcard(inputPath, inputPrefix, inputSuffix)
outputPath := outputPrefix + wildcard + outputSuffix
inputContent, err := os.ReadFile(inputPath)
if err != nil {
return nil, fmt.Errorf("read input %q: %w", inputPath, err)
}
outputContent, err := os.ReadFile(outputPath)
if err != nil {
return nil, fmt.Errorf("read output %q: %w", outputPath, err)
}
name := fmt.Sprintf("pattern:%s", wildcard)
stdin := string(inputContent)
expected := string(outputContent)
tests = append(tests, &dsl.Test{
Name: name,
Stdin: &stdin,
Env: map[string]string{},
InFiles: map[string]string{},
OutFiles: map[string]string{},
Stdout: dsl.ExactMatcher{Value: expected},
Stderr: dsl.NoMatcher{},
})
}
return tests, nil
}
func expandDirPattern(pattern *dsl.Pattern) ([]*dsl.Test, error) {
dirs, err := filepath.Glob(pattern.DirsGlob)
if err != nil {
return nil, fmt.Errorf("invalid dirs glob %q: %w", pattern.DirsGlob, err)
}
if len(dirs) == 0 {
return nil, fmt.Errorf("no directories matched %q", pattern.DirsGlob)
}
var tests []*dsl.Test
for _, dir := range dirs {
info, err := os.Stat(dir)
if err != nil || !info.IsDir() {
continue
}
inputPath := filepath.Join(dir, pattern.InputFile)
outputPath := filepath.Join(dir, pattern.OutputFile)
inputContent, err := os.ReadFile(inputPath)
if err != nil {
return nil, fmt.Errorf("read %q: %w", inputPath, err)
}
outputContent, err := os.ReadFile(outputPath)
if err != nil {
return nil, fmt.Errorf("read %q: %w", outputPath, err)
}
name := fmt.Sprintf("pattern:%s", filepath.Base(dir))
stdin := string(inputContent)
expected := string(outputContent)
tests = append(tests, &dsl.Test{
Name: name,
Stdin: &stdin,
Env: map[string]string{},
InFiles: map[string]string{},
OutFiles: map[string]string{},
Stdout: dsl.ExactMatcher{Value: expected},
Stderr: dsl.NoMatcher{},
})
}
return tests, nil
}
func splitGlob(pattern string) (prefix, suffix string) {
idx := strings.Index(pattern, "*")
if idx < 0 {
return pattern, ""
}
return pattern[:idx], pattern[idx+1:]
}
func extractWildcard(path, prefix, suffix string) string {
s := strings.TrimPrefix(path, prefix)
s = strings.TrimSuffix(s, suffix)
return s
}