package runner import ( "fmt" "os" "path/filepath" "strings" "github.com/Mond1c/judge/dsl" ) func expandPattern(pattern *dsl.Pattern) ([]*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) { before, after, found := strings.Cut(pattern, "*") if !found { return pattern, "" } return before, after } func extractWildcard(path, prefix, suffix string) string { s := strings.TrimPrefix(path, prefix) s = strings.TrimSuffix(s, suffix) return s }