Skip to content

Commit f2ad76c

Browse files
authored
Implement record/replay testing (#299)
* Factor out generate guts * Redo the end-to-end test * intenral/endtoend: Port gen_test to new test setup The existing tests in `gen_test` were unit tests that tested internal APIs. Port these tests to integration tests, encompassing an entire run of sqlc itself.
1 parent 285cfa8 commit f2ad76c

File tree

21 files changed

+519
-352
lines changed

21 files changed

+519
-352
lines changed

internal/cmd/cmd.go

Lines changed: 5 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package cmd
22

33
import (
4-
"bytes"
54
"encoding/json"
65
"fmt"
76
"io"
@@ -11,7 +10,6 @@ import (
1110
"path/filepath"
1211

1312
"github.com/kyleconroy/sqlc/internal/dinosql"
14-
"github.com/kyleconroy/sqlc/internal/mysql"
1513

1614
"github.com/davecgh/go-spew/spew"
1715
pg "github.com/lfittl/pg_query_go"
@@ -84,127 +82,26 @@ var initCmd = &cobra.Command{
8482
},
8583
}
8684

87-
const errMessageNoVersion = `The configuration file must have a version number.
88-
Set the version to 1 at the top of sqlc.json:
89-
90-
{
91-
"version": "1"
92-
...
93-
}
94-
`
95-
96-
const errMessageUnknownVersion = `The configuration file has an invalid version number.
97-
The only supported version is "1".
98-
`
99-
100-
const errMessageNoPackages = `No packages are configured`
101-
10285
var genCmd = &cobra.Command{
10386
Use: "generate",
10487
Short: "Generate Go code from SQL",
10588
Run: func(cmd *cobra.Command, args []string) {
106-
blob, err := ioutil.ReadFile("sqlc.json")
89+
stderr := cmd.ErrOrStderr()
90+
dir, err := os.Getwd()
10791
if err != nil {
108-
fmt.Fprintln(os.Stderr, "error parsing sqlc.json: file does not exist")
92+
fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist")
10993
os.Exit(1)
11094
}
11195

112-
settings, err := dinosql.ParseConfig(bytes.NewReader(blob))
96+
output, err := Generate(dir, stderr)
11397
if err != nil {
114-
switch err {
115-
case dinosql.ErrMissingVersion:
116-
fmt.Fprintf(os.Stderr, errMessageNoVersion)
117-
case dinosql.ErrUnknownVersion:
118-
fmt.Fprintf(os.Stderr, errMessageUnknownVersion)
119-
case dinosql.ErrNoPackages:
120-
fmt.Fprintf(os.Stderr, errMessageNoPackages)
121-
}
122-
fmt.Fprintf(os.Stderr, "error parsing sqlc.json: %s\n", err)
123-
os.Exit(1)
124-
}
125-
126-
var errored bool
127-
128-
output := map[string]string{}
129-
130-
for _, pkg := range settings.Packages {
131-
name := pkg.Name
132-
combo := dinosql.Combine(settings, pkg)
133-
var result dinosql.Generateable
134-
135-
switch pkg.Engine {
136-
137-
case dinosql.EngineMySQL:
138-
// Experimental MySQL support
139-
q, err := mysql.GeneratePkg(name, pkg.Schema, pkg.Queries, combo)
140-
if err != nil {
141-
fmt.Fprintf(os.Stderr, "# package %s\n", name)
142-
if parserErr, ok := err.(*dinosql.ParserErr); ok {
143-
for _, fileErr := range parserErr.Errs {
144-
fmt.Fprintf(os.Stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err)
145-
}
146-
} else {
147-
fmt.Fprintf(os.Stderr, "error parsing schema: %s\n", err)
148-
}
149-
errored = true
150-
continue
151-
}
152-
result = q
153-
154-
case dinosql.EnginePostgreSQL:
155-
c, err := dinosql.ParseCatalog(pkg.Schema)
156-
if err != nil {
157-
fmt.Fprintf(os.Stderr, "# package %s\n", name)
158-
if parserErr, ok := err.(*dinosql.ParserErr); ok {
159-
for _, fileErr := range parserErr.Errs {
160-
fmt.Fprintf(os.Stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err)
161-
}
162-
} else {
163-
fmt.Fprintf(os.Stderr, "error parsing schema: %s\n", err)
164-
}
165-
errored = true
166-
continue
167-
}
168-
169-
q, err := dinosql.ParseQueries(c, pkg)
170-
if err != nil {
171-
fmt.Fprintf(os.Stderr, "# package %s\n", name)
172-
if parserErr, ok := err.(*dinosql.ParserErr); ok {
173-
for _, fileErr := range parserErr.Errs {
174-
fmt.Fprintf(os.Stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err)
175-
}
176-
} else {
177-
fmt.Fprintf(os.Stderr, "error parsing queries: %s\n", err)
178-
}
179-
errored = true
180-
continue
181-
}
182-
result = q
183-
184-
}
185-
186-
files, err := dinosql.Generate(result, combo)
187-
if err != nil {
188-
fmt.Fprintf(os.Stderr, "# package %s\n", name)
189-
fmt.Fprintf(os.Stderr, "error generating code: %s\n", err)
190-
errored = true
191-
continue
192-
}
193-
194-
for n, source := range files {
195-
filename := filepath.Join(pkg.Path, n)
196-
output[filename] = source
197-
}
198-
}
199-
200-
if errored {
20198
os.Exit(1)
20299
}
203100

204101
for filename, source := range output {
205102
os.MkdirAll(filepath.Dir(filename), 0755)
206103
if err := ioutil.WriteFile(filename, []byte(source), 0644); err != nil {
207-
fmt.Fprintf(os.Stderr, "%s: %s\n", filename, err)
104+
fmt.Fprintf(stderr, "%s: %s\n", filename, err)
208105
os.Exit(1)
209106
}
210107
}

internal/cmd/generate.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"io/ioutil"
8+
"path/filepath"
9+
10+
"github.com/kyleconroy/sqlc/internal/dinosql"
11+
"github.com/kyleconroy/sqlc/internal/mysql"
12+
)
13+
14+
const errMessageNoVersion = `The configuration file must have a version number.
15+
Set the version to 1 at the top of sqlc.json:
16+
17+
{
18+
"version": "1"
19+
...
20+
}
21+
`
22+
23+
const errMessageUnknownVersion = `The configuration file has an invalid version number.
24+
The only supported version is "1".
25+
`
26+
27+
const errMessageNoPackages = `No packages are configured`
28+
29+
func Generate(dir string, stderr io.Writer) (map[string]string, error) {
30+
blob, err := ioutil.ReadFile(filepath.Join(dir, "sqlc.json"))
31+
if err != nil {
32+
fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist")
33+
return nil, err
34+
}
35+
36+
settings, err := dinosql.ParseConfig(bytes.NewReader(blob))
37+
if err != nil {
38+
switch err {
39+
case dinosql.ErrMissingVersion:
40+
fmt.Fprintf(stderr, errMessageNoVersion)
41+
case dinosql.ErrUnknownVersion:
42+
fmt.Fprintf(stderr, errMessageUnknownVersion)
43+
case dinosql.ErrNoPackages:
44+
fmt.Fprintf(stderr, errMessageNoPackages)
45+
}
46+
fmt.Fprintf(stderr, "error parsing sqlc.json: %s\n", err)
47+
return nil, err
48+
}
49+
50+
output := map[string]string{}
51+
errored := false
52+
53+
for _, pkg := range settings.Packages {
54+
name := pkg.Name
55+
combo := dinosql.Combine(settings, pkg)
56+
var result dinosql.Generateable
57+
58+
// TODO: This feels like a hack that will bite us later
59+
pkg.Schema = filepath.Join(dir, pkg.Schema)
60+
pkg.Queries = filepath.Join(dir, pkg.Queries)
61+
62+
switch pkg.Engine {
63+
64+
case dinosql.EngineMySQL:
65+
// Experimental MySQL support
66+
q, err := mysql.GeneratePkg(name, pkg.Schema, pkg.Queries, combo)
67+
if err != nil {
68+
fmt.Fprintf(stderr, "# package %s\n", name)
69+
if parserErr, ok := err.(*dinosql.ParserErr); ok {
70+
for _, fileErr := range parserErr.Errs {
71+
fmt.Fprintf(stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err)
72+
}
73+
} else {
74+
fmt.Fprintf(stderr, "error parsing schema: %s\n", err)
75+
}
76+
errored = true
77+
continue
78+
}
79+
result = q
80+
81+
case dinosql.EnginePostgreSQL:
82+
c, err := dinosql.ParseCatalog(pkg.Schema)
83+
if err != nil {
84+
fmt.Fprintf(stderr, "# package %s\n", name)
85+
if parserErr, ok := err.(*dinosql.ParserErr); ok {
86+
for _, fileErr := range parserErr.Errs {
87+
fmt.Fprintf(stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err)
88+
}
89+
} else {
90+
fmt.Fprintf(stderr, "error parsing schema: %s\n", err)
91+
}
92+
errored = true
93+
continue
94+
}
95+
96+
q, err := dinosql.ParseQueries(c, pkg)
97+
if err != nil {
98+
fmt.Fprintf(stderr, "# package %s\n", name)
99+
if parserErr, ok := err.(*dinosql.ParserErr); ok {
100+
for _, fileErr := range parserErr.Errs {
101+
fmt.Fprintf(stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err)
102+
}
103+
} else {
104+
fmt.Fprintf(stderr, "error parsing queries: %s\n", err)
105+
}
106+
errored = true
107+
continue
108+
}
109+
result = q
110+
111+
}
112+
113+
files, err := dinosql.Generate(result, combo)
114+
if err != nil {
115+
fmt.Fprintf(stderr, "# package %s\n", name)
116+
fmt.Fprintf(stderr, "error generating code: %s\n", err)
117+
errored = true
118+
continue
119+
}
120+
121+
for n, source := range files {
122+
filename := filepath.Join(dir, pkg.Path, n)
123+
output[filename] = source
124+
}
125+
}
126+
127+
if errored {
128+
return nil, fmt.Errorf("errored")
129+
}
130+
return output, nil
131+
}

0 commit comments

Comments
 (0)