120 lines
3.1 KiB
Go
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
|
|
}
|