diff options
author | EuAndreh <eu@euandre.org> | 2024-12-10 12:29:03 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-12-10 12:29:03 -0300 |
commit | 8359c047aaebe274a2d811d61922b571ca7d10df (patch) | |
tree | 070e0ed93d27a842776ada805eeb4270e7e3c806 /tester | |
parent | Start building test files (diff) | |
download | cotia-8359c047aaebe274a2d811d61922b571ca7d10df.tar.gz cotia-8359c047aaebe274a2d811d61922b571ca7d10df.tar.xz |
Namespace packages with "urubu/"
Diffstat (limited to 'tester')
-rw-r--r-- | tester/tester.go | 181 | ||||
-rw-r--r-- | tester/tester_test.go | 169 |
2 files changed, 0 insertions, 350 deletions
diff --git a/tester/tester.go b/tester/tester.go deleted file mode 100644 index fa9b806..0000000 --- a/tester/tester.go +++ /dev/null @@ -1,181 +0,0 @@ -package tester - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - "runtime/debug" - "strings" - - driver "driver/parser" - gspec "spec/grammar" - tspec "spec/test" -) - -type TestResult struct { - TestCasePath string - Error error - Diffs []*tspec.TreeDiff -} - -func (r *TestResult) String() string { - if r.Error != nil { - const indent1 = " " - const indent2 = indent1 + indent1 - - msgLines := strings.Split(r.Error.Error(), "\n") - msg := fmt.Sprintf("Failed %v:\n%v%v", r.TestCasePath, indent1, strings.Join(msgLines, "\n"+indent1)) - if len(r.Diffs) == 0 { - return msg - } - var diffLines []string - for _, diff := range r.Diffs { - diffLines = append(diffLines, diff.Message) - diffLines = append(diffLines, fmt.Sprintf("%vexpected path: %v", indent1, diff.ExpectedPath)) - diffLines = append(diffLines, fmt.Sprintf("%vactual path: %v", indent1, diff.ActualPath)) - } - return fmt.Sprintf("%v\n%v%v", msg, indent2, strings.Join(diffLines, "\n"+indent2)) - } - return fmt.Sprintf("Passed %v", r.TestCasePath) -} - -type TestCaseWithMetadata struct { - TestCase *tspec.TestCase - FilePath string - Error error -} - -func ListTestCases(testPath string) []*TestCaseWithMetadata { - fi, err := os.Stat(testPath) - if err != nil { - return []*TestCaseWithMetadata{ - { - FilePath: testPath, - Error: err, - }, - } - } - if !fi.IsDir() { - c, err := parseTestCase(testPath) - return []*TestCaseWithMetadata{ - { - TestCase: c, - FilePath: testPath, - Error: err, - }, - } - } - - es, err := os.ReadDir(testPath) - if err != nil { - return []*TestCaseWithMetadata{ - { - FilePath: testPath, - Error: err, - }, - } - } - var cases []*TestCaseWithMetadata - for _, e := range es { - cs := ListTestCases(filepath.Join(testPath, e.Name())) - cases = append(cases, cs...) - } - return cases -} - -func parseTestCase(testCasePath string) (*tspec.TestCase, error) { - f, err := os.Open(testCasePath) - if err != nil { - return nil, err - } - defer f.Close() - return tspec.ParseTestCase(f) -} - -type Tester struct { - Grammar *gspec.CompiledGrammar - Cases []*TestCaseWithMetadata -} - -func (t *Tester) Run() []*TestResult { - var rs []*TestResult - for _, c := range t.Cases { - rs = append(rs, runTest(t.Grammar, c)) - } - return rs -} - -func runTest(g *gspec.CompiledGrammar, c *TestCaseWithMetadata) *TestResult { - var p *driver.Parser - var tb *driver.DefaultSyntaxTreeBuilder - { - gram := driver.NewGrammar(g) - toks, err := driver.NewTokenStream(g, bytes.NewReader(c.TestCase.Source)) - if err != nil { - return &TestResult{ - TestCasePath: c.FilePath, - Error: err, - } - } - tb = driver.NewDefaultSyntaxTreeBuilder() - p, err = driver.NewParser(toks, gram, driver.SemanticAction(driver.NewASTActionSet(gram, tb))) - if err != nil { - return &TestResult{ - TestCasePath: c.FilePath, - Error: err, - } - } - } - - err := p.Parse() - if err != nil { - return &TestResult{ - TestCasePath: c.FilePath, - Error: err, - } - } - - if tb.Tree() == nil { - var err error - if len(p.SyntaxErrors()) > 0 { - err = fmt.Errorf("parse tree was not generated: syntax error occurred") - } else { - // The parser should always generate a parse tree in the vartan-test command, so if there is no parse - // tree, it is a bug. We also include a stack trace in the error message to be sure. - err = fmt.Errorf("parse tree was not generated: no syntax error:\n%v", string(debug.Stack())) - } - return &TestResult{ - TestCasePath: c.FilePath, - Error: err, - } - } - - // When a parse tree exists, the test continues regardless of whether or not syntax errors occurred. - diffs := tspec.DiffTree(c.TestCase.Output, ConvertSyntaxTreeToTestableTree(tb.Tree()).Fill()) - if len(diffs) > 0 { - return &TestResult{ - TestCasePath: c.FilePath, - Error: fmt.Errorf("output mismatch"), - Diffs: diffs, - } - } - return &TestResult{ - TestCasePath: c.FilePath, - } -} - -func ConvertSyntaxTreeToTestableTree(dTree *driver.Node) *tspec.Tree { - if dTree.Text != "" { - return tspec.NewTerminalNode(dTree.KindName, dTree.Text) - } - - var children []*tspec.Tree - if len(dTree.Children) > 0 { - children = make([]*tspec.Tree, len(dTree.Children)) - for i, c := range dTree.Children { - children[i] = ConvertSyntaxTreeToTestableTree(c) - } - } - return tspec.NewNonTerminalTree(dTree.KindName, children...) -} diff --git a/tester/tester_test.go b/tester/tester_test.go deleted file mode 100644 index df5cb07..0000000 --- a/tester/tester_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package tester - -import ( - "fmt" - "strings" - "testing" - - "grammar" - "spec/grammar/parser" - tspec "spec/test" -) - -func TestTester_Run(t *testing.T) { - grammarSrc1 := ` -#name test; - -s - : foo bar baz - | foo error baz #recover - ; - -ws #skip - : "[\u{0009}\u{0020}]+"; -foo - : 'foo'; -bar - : 'bar'; -baz - : 'baz'; -` - - grammarSrc2 := ` -#name test; - -s - : foos - ; -foos - : foos foo #ast foos... foo - | foo - ; - -ws #skip - : "[\u{0009}\u{0020}]+"; -foo - : 'foo'; -` - - tests := []struct { - grammarSrc string - testSrc string - error bool - }{ - { - grammarSrc: grammarSrc1, - testSrc: ` -Test ---- -foo bar baz ---- -(s - (foo 'foo') (bar 'bar') (baz 'baz')) -`, - }, - { - grammarSrc: grammarSrc1, - testSrc: ` -Test ---- -foo ? baz ---- -(s - (foo 'foo') (error) (baz 'baz')) -`, - }, - { - grammarSrc: grammarSrc1, - testSrc: ` -Test ---- -foo bar baz ---- -(s) -`, - error: true, - }, - { - grammarSrc: grammarSrc1, - testSrc: ` -Test ---- -foo bar baz ---- -(s - (foo) (bar)) -`, - error: true, - }, - { - grammarSrc: grammarSrc1, - testSrc: ` -Test ---- -foo bar baz ---- -(s - (foo) (bar) (xxx)) -`, - error: true, - }, - { - grammarSrc: grammarSrc2, - testSrc: ` -Test ---- -foo foo foo ---- -(s - (foos - (foo 'foo') (foo 'foo') (foo 'foo'))) -`, - }, - } - for i, tt := range tests { - t.Run(fmt.Sprintf("#%v", i), func(t *testing.T) { - ast, err := parser.Parse(strings.NewReader(tt.grammarSrc)) - if err != nil { - t.Fatal(err) - } - b := grammar.GrammarBuilder{ - AST: ast, - } - cg, _, err := b.Build() - if err != nil { - t.Fatal(err) - } - c, err := tspec.ParseTestCase(strings.NewReader(tt.testSrc)) - if err != nil { - t.Fatal(err) - } - tester := &Tester{ - Grammar: cg, - Cases: []*TestCaseWithMetadata{ - { - TestCase: c, - }, - }, - } - rs := tester.Run() - if tt.error { - errOccurred := false - for _, r := range rs { - if r.Error != nil { - errOccurred = true - } - } - if !errOccurred { - t.Fatal("this test must fail, but it passed") - } - } else { - for _, r := range rs { - if r.Error != nil { - t.Fatalf("unexpected error occurred: %v", r.Error) - } - } - } - }) - } -} |