Skip to content

Commit 8c6b724

Browse files
authored
Merge pull request #57 from chermehdi/features/checkers-token-checker
Add customizable checkers
2 parents 51bed63 + e0a7785 commit 8c6b724

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

commands/run.go

+52-9
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,32 @@ func (c *DiffChecker) Check(got, expected string) error {
6565
return nil
6666
}
6767

68+
// Implementation of a slightly smarter checker.
69+
// This checker tokenizes the input and expected output and compares them token
70+
// by token ignoring spaces and empty lines.
71+
type TokenChecker struct {
72+
}
73+
74+
func (c *TokenChecker) Check(got, expected string) error {
75+
inputTokens := strings.Fields(got)
76+
outputTokens := strings.Fields(expected)
77+
if len(inputTokens) != len(outputTokens) {
78+
return errors.New(fmt.Sprintf("Checker failed, number of tokens different: expected %d, got %d\n\r",
79+
len(outputTokens), len(inputTokens)))
80+
}
81+
i := 0
82+
n := len(inputTokens)
83+
for i < n {
84+
if inputTokens[i] != outputTokens[i] {
85+
return errors.New(fmt.Sprintf("Checker failed, token %d does not match: expected %s, got %s\n\r",
86+
i, outputTokens[i], inputTokens[i]))
87+
}
88+
i = i + 1
89+
}
90+
// everything matched.
91+
return nil
92+
}
93+
6894
// Case description contains minimum information required to run one test case.
6995
type CaseDescription struct {
7096
InputFile string
@@ -474,21 +500,29 @@ func (judge *PythonJudge) Cleanup() error {
474500
}
475501

476502
// Creates and returns a Judge implementation corresponding to the given language
477-
func NewJudgeFor(meta config.EgorMeta, configuration *config.Config) (Judge, error) {
503+
func NewJudgeFor(meta config.EgorMeta, configuration *config.Config, checker Checker) (Judge, error) {
478504
switch meta.TaskLang {
479505
case "java":
480-
return &JavaJudge{Meta: meta, checker: &DiffChecker{}}, nil
506+
return &JavaJudge{Meta: meta, checker: checker}, nil
481507
case "cpp":
482-
return &CppJudge{Meta: meta, checker: &DiffChecker{}, hasLibrary: configuration.HasCppLibrary(), LibraryLocation: configuration.CppLibraryLocation}, nil
508+
return &CppJudge{Meta: meta, checker: checker, hasLibrary: configuration.HasCppLibrary(), LibraryLocation: configuration.CppLibraryLocation}, nil
483509
case "c":
484-
return &CppJudge{Meta: meta, checker: &DiffChecker{}, hasLibrary: configuration.HasCppLibrary(), LibraryLocation: configuration.CppLibraryLocation}, nil
510+
return &CppJudge{Meta: meta, checker: checker, hasLibrary: configuration.HasCppLibrary(), LibraryLocation: configuration.CppLibraryLocation}, nil
485511
case "python":
486-
return &PythonJudge{Meta: meta, checker: &DiffChecker{}}, nil
512+
return &PythonJudge{Meta: meta, checker: checker}, nil
487513
}
488514
return nil, errors.New(fmt.Sprintf("Cannot find judge for the given lang %s", meta.TaskLang))
489515
}
490516

491-
func RunAction(_ *cli.Context) error {
517+
// Resolve the checker by name, otherwise fallback to the DiffChecker
518+
func getChecker(name string) Checker {
519+
if name == "tokens" {
520+
return &TokenChecker{}
521+
}
522+
return &DiffChecker{}
523+
}
524+
525+
func RunAction(context *cli.Context) error {
492526
configuration, err := config.LoadDefaultConfiguration()
493527
if err != nil {
494528
return err
@@ -503,7 +537,7 @@ func RunAction(_ *cli.Context) error {
503537
return err
504538
}
505539

506-
judge, err := NewJudgeFor(egorMeta, configuration)
540+
judge, err := NewJudgeFor(egorMeta, configuration, getChecker(context.String("checker")))
507541
if err != nil {
508542
return err
509543
}
@@ -524,8 +558,17 @@ func RunAction(_ *cli.Context) error {
524558
}
525559

526560
var TestCommand = cli.Command{
527-
Name: "test",
528-
Aliases: []string{"r"},
561+
Name: "test",
562+
Aliases: []string{"r"},
563+
Flags: []cli.Flag{
564+
&cli.StringFlag{
565+
Name: "checker",
566+
// Add new checker values.
567+
Usage: "Override the default checker, available values (diff, tokens)",
568+
Aliases: []string{"io", "fio"},
569+
Value: "diff",
570+
},
571+
},
529572
Usage: "Run test cases using the provided solution",
530573
UsageText: "egor test",
531574
Action: RunAction,

commands/run_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,23 @@ func TestTimedExecution(t *testing.T) {
2020
assert.Equal(t, err, nil)
2121
assert.Equal(t, status, OK)
2222
}
23+
24+
func TestChecker_TokenBasedCheckerShouldIgnoreSpaces(t *testing.T) {
25+
checker := &TokenChecker{}
26+
assert.Nil(t, checker.Check("a b c", "a b c"))
27+
}
28+
29+
func TestChecker_TokenBasedCheckerShouldIgnoreNewLines(t *testing.T) {
30+
checker := &TokenChecker{}
31+
assert.Nil(t, checker.Check("a b c", "a b \nc"))
32+
}
33+
34+
func TestChecker_TokenBasedCheckerShouldFailOnMismatchedNumberOfTokens(t *testing.T) {
35+
checker := &TokenChecker{}
36+
assert.NotNil(t, checker.Check("a b c", "ab d"))
37+
}
38+
39+
func TestChecker_TokenBasedCheckerShouldFailOnDifferentToken(t *testing.T) {
40+
checker := &TokenChecker{}
41+
assert.NotNil(t, checker.Check("a b c", "a b d"))
42+
}

0 commit comments

Comments
 (0)