Skip to content

Commit

Permalink
Use the original filename, rework error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
jhchabran committed Apr 12, 2021
1 parent c7a893a commit ccb39f3
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 59 deletions.
46 changes: 21 additions & 25 deletions cmd/examplar/examplar.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ package main

import (
"bufio"
"fmt"
"io"
"strings"
"text/template"
)

type Line struct {
Num int
Orig string
Text string
}

// Test is a list of statements.
type Test struct {
Name string
Num int
Orig string
Statements []*Statement
}

Expand All @@ -36,10 +37,15 @@ func (s Statement) expectationText() string {

// Examplar represents a group of tests and can optionally include setup code and teardown code.
type Examplar struct {
Name string
setup []Line
teardown []Line
examples []*Test
Name string
originalFilename string
setup []Line
teardown []Line
examples []*Test
}

func (ex *Examplar) origLoc(num int) string {
return fmt.Sprintf("%s:%d", ex.originalFilename, num)
}

// HasSetup returns true if setup code is provided.
Expand All @@ -55,38 +61,28 @@ func (ex *Examplar) HasTeardown() bool {
func (ex *Examplar) appendTest(name string, num int) *Test {
test := Test{
Name: name,
Num: num,
Orig: ex.origLoc(num),
}
ex.examples = append(ex.examples, &test)

return &test
}

// func (ex *Examplar) currentTest() *Test {
// return ex.examples[len(ex.examples)-1]
// }

// func (ex *Examplar) currentStatement() *Statement {
// test := ex.currentTest()
// return test.Statements[len(test.Statements)-1]
// }

// func (ex *Examplar) currentExpectation() *[]Line {
// return &ex.currentStatement().Expectation
// }

// Parse reads annotated textual data and transforms it into a
// structured representation. Only annotations are parsed, the
// textual data itself is irrelevant to this function.
//
// It will panic if an error is encountered.
func Parse(r io.Reader, name string) *Examplar {
scanner := &Scanner{}
func Parse(r io.Reader, name string, originalFilename string) *Examplar {
ex := Examplar{
Name: name,
originalFilename: originalFilename,
}

ex := scanner.Run(bufio.NewScanner(r))
ex.Name = name
scanner := &Scanner{ex: &ex}
scanner.Run(bufio.NewScanner(r))

return ex
return &ex
}

func normalizeTestName(name string) string {
Expand Down
10 changes: 5 additions & 5 deletions cmd/examplar/examplar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import (
func TestParse(t *testing.T) {
f, err := os.Open("extest1.sql")
require.NoError(t, err)
defer f.Close()

ex := Parse(f, "extest1")
defer f.Close()
ex := Parse(f, "extest1", "extest1.sql")

require.Equal(t, []Line{{2, "CREATE TABLE foo (a int);"}}, ex.setup)
require.Equal(t, []Line{{5, "DROP TABLE foo;"}}, ex.teardown)
require.Equal(t, []Line{{"extest1.sql:2", "CREATE TABLE foo (a int);"}}, ex.setup)
require.Equal(t, []Line{{"extest1.sql:5", "DROP TABLE foo;"}}, ex.teardown)

// first test
example := ex.examples[0]
Expand Down Expand Up @@ -64,7 +64,7 @@ func TestTemplate(t *testing.T) {
require.NoError(t, err)
defer f.Close()

ex := Parse(f, "foo bar")
ex := Parse(f, "foo bar", "extest1.sql")

var b strings.Builder

Expand Down
24 changes: 12 additions & 12 deletions cmd/examplar/extest1_test.go.gold
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestFooBar(t *testing.T) {

// teardown
teardown := func() {
// orig:5
// extest1.sql:5
q := `
DROP TABLE foo;
`
Expand All @@ -41,15 +41,15 @@ func TestFooBar(t *testing.T) {

// setup
setup := func() {
// orig:2
// extest1.sql:2
q := `
CREATE TABLE foo (a int);
`
err := db.Exec(q)
require.NoError(t, err)
}

// orig:7
// extest1.sql:7
t.Run("insert something", func(t *testing.T) {
t.Cleanup(teardown)
setup()
Expand All @@ -60,7 +60,7 @@ func TestFooBar(t *testing.T) {
var q string
var res *query.Result

// orig:8
// extest1.sql:8
q = `
INSERT INTO foo (a) VALUES (1);
SELECT * FROM foo;
Expand All @@ -73,9 +73,9 @@ func TestFooBar(t *testing.T) {
data = jsonResult(t, res)
require.NoError(t, err)

expected = `[{"a": 1}]` // orig:10
expected = `[{"a": 1}]` // extest1.sql:10
require.JSONEq(t, expected, string(data))
// orig:12
// extest1.sql:12
q = `
SELECT a, b FROM foo;
`
Expand All @@ -87,15 +87,15 @@ func TestFooBar(t *testing.T) {
data = jsonResult(t, res)
require.NoError(t, err)

// orig: 14
// extest1.sql:14
expected = `
[{
"a": 1,
"b": null
}]
`
require.JSONEq(t, expected, string(data))
// orig:20
// extest1.sql:20
q = `
SELECT z FROM foo;
`
Expand All @@ -107,11 +107,11 @@ func TestFooBar(t *testing.T) {
data = jsonResult(t, res)
require.NoError(t, err)

expected = `[{"z": null}]` // orig:21
expected = `[{"z": null}]` // extest1.sql:21
require.JSONEq(t, expected, string(data))
})

// orig:23
// extest1.sql:23
t.Run("something else", func(t *testing.T) {
t.Cleanup(teardown)
setup()
Expand All @@ -122,7 +122,7 @@ func TestFooBar(t *testing.T) {
var q string
var res *query.Result

// orig:24
// extest1.sql:24
q = `
INSERT INTO foo (c) VALUES (3);
SELECT * FROM foo;
Expand All @@ -135,7 +135,7 @@ func TestFooBar(t *testing.T) {
data = jsonResult(t, res)
require.NoError(t, err)

expected = `[{"c": 3}]` // orig:26
expected = `[{"c": 3}]` // extest1.sql:26
require.JSONEq(t, expected, string(data))
})

Expand Down
2 changes: 1 addition & 1 deletion cmd/examplar/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func genFile(p string, packageName string) error {
base := path.Base(p)
name := strings.TrimSuffix(base, path.Ext(p))

ex := Parse(in, name)
ex := Parse(in, name, base)

out, err := os.OpenFile(name+"_test.go", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
Expand Down
25 changes: 15 additions & 10 deletions cmd/examplar/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"bufio"
"fmt"
"regexp"
"strings"
)
Expand All @@ -23,11 +24,16 @@ type Scanner struct {
line string
num int
ex *Examplar
err error

curTest *Test
curStmt *Statement
}

func (s *Scanner) origLoc() string {
return s.ex.origLoc(s.num)
}

func initialState(s *Scanner) stateFn {
if tag, data := parseTag(s.line); tag != UNKNOWN {
switch tag {
Expand Down Expand Up @@ -61,7 +67,7 @@ func setupState(s *Scanner) stateFn {
}
}

s.ex.setup = append(s.ex.setup, Line{s.num, s.line})
s.ex.setup = append(s.ex.setup, Line{s.origLoc(), s.line})
return setupState
}

Expand All @@ -82,7 +88,7 @@ func teardownState(s *Scanner) stateFn {
}
}

s.ex.teardown = append(s.ex.teardown, Line{s.num, s.line})
s.ex.teardown = append(s.ex.teardown, Line{s.origLoc(), s.line})
return teardownState
}

Expand Down Expand Up @@ -111,14 +117,14 @@ func testState(s *Scanner) stateFn {

if assertion := parseSingleAssertion(s.line); len(assertion) > 0 {
exp := &s.curStmt.Expectation
*exp = []Line{{s.num, assertion}}
*exp = []Line{{s.origLoc(), assertion}}

// current statement is now finished
s.curStmt = nil
return testState
}

s.curStmt.Code = append(s.curStmt.Code, Line{s.num, s.line})
s.curStmt.Code = append(s.curStmt.Code, Line{s.origLoc(), s.line})

return testState
}
Expand All @@ -142,18 +148,17 @@ func multilineAssertionState(s *Scanner) stateFn {
}

exp := &s.curStmt.Expectation
*exp = append(*exp, Line{s.num, code})
*exp = append(*exp, Line{s.origLoc(), code})

return multilineAssertionState
}

func errorState(s *Scanner) stateFn {
panic(s.line)
s.err = fmt.Errorf(s.line)
return errorState
}

func (s *Scanner) Run(io *bufio.Scanner) *Examplar {
s.ex = &Examplar{}

func (s *Scanner) Run(io *bufio.Scanner) error {
for state := initialState; io.Scan(); {
s.line = io.Text()
s.line = strings.TrimSpace(s.line)
Expand All @@ -165,7 +170,7 @@ func (s *Scanner) Run(io *bufio.Scanner) *Examplar {
state = state(s)
}

return s.ex
return s.err
}

func parseTag(line string) (Tag, string) {
Expand Down
12 changes: 6 additions & 6 deletions cmd/examplar/test_template.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func Test{{ .TestName }}(t *testing.T) {

// teardown
teardown := func() {
// orig:{{ (index .Teardown 0).Num }}
// {{ (index .Teardown 0).Orig }}
q := `
{{- range .Teardown }}
{{ .Text }}
Expand All @@ -43,7 +43,7 @@ func Test{{ .TestName }}(t *testing.T) {

// setup
setup := func() {
// orig:{{ (index .Setup 0).Num }}
// {{ (index .Setup 0).Orig }}
q := `
{{- range .Setup }}
{{ .Text }}
Expand All @@ -54,7 +54,7 @@ func Test{{ .TestName }}(t *testing.T) {
}
{{ "" }}
{{- range .Tests }}
// orig:{{ .Num }}
// {{ .Orig }}
t.Run("{{ .Name }}", func(t *testing.T) {
t.Cleanup(teardown)
setup()
Expand All @@ -67,7 +67,7 @@ func Test{{ .TestName }}(t *testing.T) {
{{ "" }}

{{- range .Statements }}
// orig:{{ (index .Code 0).Num }}
// {{ (index .Code 0).Orig }}
q = `
{{- range .Code }}
{{ .Text }}
Expand All @@ -82,14 +82,14 @@ func Test{{ .TestName }}(t *testing.T) {
require.NoError(t, err)
{{ "" }}
{{- if gt (len .Expectation) 1 }}
// orig: {{ (index .Expectation 0).Num }}
// {{ (index .Expectation 0).Orig }}
expected = `
{{- range .Expectation }}
{{ .Text }}
{{- end }}
`
{{- else }}
expected = `{{ (index .Expectation 0).Text }}` // orig:{{ (index .Expectation 0).Num }}
expected = `{{ (index .Expectation 0).Text }}` // {{ (index .Expectation 0).Orig }}
{{- end }}
require.JSONEq(t, expected, string(data))
{{- end }}
Expand Down

0 comments on commit ccb39f3

Please sign in to comment.