Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: codebase cleanup for avrogen and avrosv #305

Merged
merged 3 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions cmd/avrogen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,42 +24,42 @@ type config struct {
}

func main() {
os.Exit(realMain(os.Args, os.Stderr, os.Stdout))
os.Exit(realMain(os.Args, os.Stdout, os.Stderr))
}

func realMain(args []string, out, dumpout io.Writer) int {
func realMain(args []string, stdout, stderr io.Writer) int {
var cfg config
flgs := flag.NewFlagSet("avrogen", flag.ExitOnError)
flgs.SetOutput(out)
flgs.SetOutput(stderr)
flgs.StringVar(&cfg.Pkg, "pkg", "", "The package name of the output file.")
flgs.StringVar(&cfg.Out, "o", "", "The output file path to write to instead of stdout.")
flgs.StringVar(&cfg.Tags, "tags", "", "The additional field tags <tag-name>:{snake|camel|upper-camel|kebab}>[,...]")
flgs.BoolVar(&cfg.FullName, "fullname", false, "Use the full name of the Record schema to create the struct name.")
flgs.BoolVar(&cfg.Encoders, "encoders", false, "Generate encoders for the structs.")
flgs.StringVar(&cfg.Initialisms, "initialisms", "", "Custom initialisms <VAL>[,...] for struct and field names.")
flgs.Usage = func() {
_, _ = fmt.Fprintln(out, "Usage: avrogen [options] schemas")
_, _ = fmt.Fprintln(out, "Options:")
_, _ = fmt.Fprintln(stderr, "Usage: avrogen [options] schemas")
_, _ = fmt.Fprintln(stderr, "Options:")
flgs.PrintDefaults()
}
if err := flgs.Parse(args[1:]); err != nil {
return 1
}

if err := validateOpts(flgs.NArg(), cfg); err != nil {
_, _ = fmt.Fprintln(out, "Error: "+err.Error())
_, _ = fmt.Fprintln(stderr, "Error: "+err.Error())
return 1
}

tags, err := parseTags(cfg.Tags)
if err != nil {
_, _ = fmt.Fprintln(out, "Error: "+err.Error())
_, _ = fmt.Fprintln(stderr, "Error: "+err.Error())
return 1
}

initialisms, err := parseInitialisms(cfg.Initialisms)
if err != nil {
_, _ = fmt.Fprintln(out, "Error: "+err.Error())
_, _ = fmt.Fprintln(stderr, "Error: "+err.Error())
return 1
}

Expand All @@ -72,28 +72,28 @@ func realMain(args []string, out, dumpout io.Writer) int {
for _, file := range flgs.Args() {
schema, err := avro.ParseFiles(filepath.Clean(file))
if err != nil {
_, _ = fmt.Fprintf(out, "Error: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error: %v\n", err)
return 2
}
g.Parse(schema)
}

var buf bytes.Buffer
if err = g.Write(&buf); err != nil {
_, _ = fmt.Fprintf(out, "Error: could not generate code: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error: could not generate code: %v\n", err)
return 3
}
formatted, err := format.Source(buf.Bytes())
if err != nil {
_, _ = fmt.Fprintf(out, "Error: could not format code: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error: could not format code: %v\n", err)
return 3
}

writer := dumpout
writer := stdout
if cfg.Out != "" {
file, err := os.Create(cfg.Out)
if err != nil {
_, _ = fmt.Fprintf(out, "Error: could not create output file: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error: could not create output file: %v\n", err)
return 4
}
defer func() { _ = file.Close() }()
Expand All @@ -102,7 +102,7 @@ func realMain(args []string, out, dumpout io.Writer) int {
}

if _, err := writer.Write(formatted); err != nil {
_, _ = fmt.Fprintf(out, "Error: could not write code: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error: could not write code: %v\n", err)
return 4
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/avrogen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestAvroGen_GeneratesSchemaStdout(t *testing.T) {
var buf bytes.Buffer

args := []string{"avrogen", "-pkg", "testpkg", "testdata/schema.avsc"}
gotCode := realMain(args, io.Discard, &buf)
gotCode := realMain(args, &buf, io.Discard)
require.Equal(t, 0, gotCode)

want, err := os.ReadFile("testdata/golden.go")
Expand Down
18 changes: 9 additions & 9 deletions cmd/avrosv/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,36 @@ type config struct {
}

func main() {
os.Exit(realMain(os.Args, os.Stderr, os.Stdout))
os.Exit(realMain(os.Args, os.Stdout, os.Stderr))
}

func realMain(args []string, out, dumpout io.Writer) int {
func realMain(args []string, stdout, stderr io.Writer) int {
var cfg config
flgs := flag.NewFlagSet("avrosv", flag.ExitOnError)
flgs.SetOutput(out)
flgs.SetOutput(stderr)
flgs.BoolVar(&cfg.Verbose, "v", false, "Verbose output (dump final parsed schema).")
flgs.Usage = func() {
_, _ = fmt.Fprintln(out, "Usage: avrosv [options] schemas")
_, _ = fmt.Fprintln(out, "Options:")
_, _ = fmt.Fprintln(stderr, "Usage: avrosv [options] schemas")
_, _ = fmt.Fprintln(stderr, "Options:")
flgs.PrintDefaults()
_, _ = fmt.Fprintln(out, "\nSchemas are processed in the order they appear.")
_, _ = fmt.Fprintln(stderr, "\nSchemas are processed in the order they appear.")
}
if err := flgs.Parse(args[1:]); err != nil {
return 1
}
if flgs.NArg() < 1 {
_, _ = fmt.Fprintln(out, "Error: at least one schema is required")
_, _ = fmt.Fprintln(stderr, "Error: at least one schema is required")
return 1
}

schema, err := avro.ParseFiles(flgs.Args()...)
if err != nil {
_, _ = fmt.Fprintf(out, "Error: %v\n", err)
_, _ = fmt.Fprintf(stderr, "Error: %v\n", err)
return 2
}

if cfg.Verbose {
fmt.Fprintln(dumpout, schema)
fmt.Fprintln(stdout, schema)
}

return 0
Expand Down
115 changes: 57 additions & 58 deletions cmd/avrosv/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,24 @@ import (

func TestAvroSv_RequiredFlags(t *testing.T) {
tests := []struct {
name string
args []string
wantErr bool
name string
args []string
wantExitCode int
}{
{
name: "validates no schema is set",
args: []string{"avrosv"},
wantErr: true,
name: "validates no schema is set",
args: []string{"avrosv"},
wantExitCode: 1,
},
{
name: "validates single schema is set",
args: []string{"avrosv", "some/file"},
wantErr: true,
name: "validates single schema is set",
args: []string{"avrosv", "some/file"},
wantExitCode: 2,
},
{
name: "validates multiple schemas are set",
args: []string{"avrosv", "some/file", "some/other"},
wantErr: true,
name: "validates multiple schemas are set",
args: []string{"avrosv", "some/file", "some/other"},
wantExitCode: 2,
},
}

Expand All @@ -37,46 +37,41 @@ func TestAvroSv_RequiredFlags(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
got := realMain(test.args, io.Discard, io.Discard)

if !test.wantErr {
assert.Equal(t, 0, got)
return
}

assert.NotEqual(t, 0, got)
assert.Equal(t, test.wantExitCode, got)
})
}
}

func TestAvroSv_ValidatesSchema(t *testing.T) {
tests := []struct {
name string
args []string
wantErr bool
name string
args []string
wantExitCode int
}{
{
name: "validates a simple schema",
args: []string{"avrosv", "testdata/schema.avsc"},
wantErr: false,
name: "validates a simple schema",
args: []string{"avrosv", "testdata/schema.avsc"},
wantExitCode: 0,
},
{
name: "does not validate a bad schema",
args: []string{"avrosv", "testdata/bad-schema.avsc"},
wantErr: true,
name: "does not validate a bad schema",
args: []string{"avrosv", "testdata/bad-schema.avsc"},
wantExitCode: 2,
},
{
name: "does not validate a schema with a bad default",
args: []string{"avrosv", "testdata/bad-default-schema.avsc"},
wantErr: true,
name: "does not validate a schema with a bad default",
args: []string{"avrosv", "testdata/bad-default-schema.avsc"},
wantExitCode: 2,
},
{
name: "does not validate a schema with a reference to a missing schema",
args: []string{"avrosv", "testdata/withref-schema.avsc"},
wantErr: true,
name: "does not validate a schema with a reference to a missing schema",
args: []string{"avrosv", "testdata/withref-schema.avsc"},
wantExitCode: 2,
},
{
name: "validates a schema with a reference to an existing schema",
args: []string{"avrosv", "testdata/schema.avsc", "testdata/withref-schema.avsc"},
wantErr: false,
name: "validates a schema with a reference to an existing schema",
args: []string{"avrosv", "testdata/schema.avsc", "testdata/withref-schema.avsc"},
wantExitCode: 0,
},
}

Expand All @@ -86,45 +81,49 @@ func TestAvroSv_ValidatesSchema(t *testing.T) {
avro.DefaultSchemaCache = &avro.SchemaCache{} // reset the schema cache
got := realMain(test.args, io.Discard, io.Discard)

if !test.wantErr {
assert.Equal(t, 0, got)
return
}

assert.NotEqual(t, 0, got)
assert.Equal(t, test.wantExitCode, got)
})
}
}

func TestAvroSv_Verbose(t *testing.T) {
tests := []struct {
name string
args []string
out string
wantErr bool
name string
args []string
wantStdout string
wantExitCode int
}{
{
name: "dumps a simple schema",
args: []string{"avrosv", "-v", "testdata/schema.avsc"},
out: "{\"name\":\"test\",\"type\":\"record\",\"fields\":[{\"name\":\"someString\",\"type\":\"string\"}]}\n",
wantErr: false,
name: "dumps a simple schema",
args: []string{"avrosv", "-v", "testdata/schema.avsc"},
wantStdout: "{\"name\":\"test\",\"type\":\"record\",\"fields\":[{\"name\":\"someString\",\"type\":\"string\"}]}\n",
wantExitCode: 0,
},
{
name: "dumps a schema with a reference to an existing schema",
args: []string{"avrosv", "-v", "testdata/schema.avsc", "testdata/withref-schema.avsc"},
wantStdout: "{\"name\":\"testref\",\"type\":\"record\",\"fields\":[{\"name\":\"someref\",\"type\":{\"name\":\"test\",\"type\":\"record\",\"fields\":[{\"name\":\"someString\",\"type\":\"string\"}]}}]}\n",
wantExitCode: 0,
},
{
name: "dumps a schema with a reference to an existing schema",
args: []string{"avrosv", "-v", "testdata/schema.avsc", "testdata/withref-schema.avsc"},
out: "{\"name\":\"testref\",\"type\":\"record\",\"fields\":[{\"name\":\"someref\",\"type\":{\"name\":\"test\",\"type\":\"record\",\"fields\":[{\"name\":\"someString\",\"type\":\"string\"}]}}]}\n",
wantErr: false,
name: "does not dump any schema when the schema file is invalid",
args: []string{"avrosv", "-v", "testdata/bad-schema.avsc"},
wantStdout: "",
wantExitCode: 2,
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
var buf bytes.Buffer

avro.DefaultSchemaCache = &avro.SchemaCache{} // reset the schema cache
w := &bytes.Buffer{}
got := realMain(test.args, io.Discard, w)
assert.Equal(t, 0, got)
assert.Equal(t, test.out, w.String())

got := realMain(test.args, &buf, io.Discard)

assert.Equal(t, test.wantStdout, buf.String())
assert.Equal(t, test.wantExitCode, got)
})
}
}
Loading