diff --git a/README.md b/README.md index 0651797..91d9fcb 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,20 @@ var ( ) ``` +It also works with raw `iota` enums: + +```go +type Size uint8 + +//go:generate go-enum-encoding -type=Size +const ( + UndefinedSize Size = iota // json:"" + Small // json:"small" + Large // json:"large" + XLarge // json:"xlarge" +) +``` + ## Related Work and References - http://github.com/zarldev/goenums - does much more advanced struct generation, generates all enum utilities besides encoding, does not generate tests, uses similar notation to trigger go:generate but with different comment directives (non-json field tags) diff --git a/internal/testdata/color2_enum_encoding.go b/internal/testdata/color2_enum_encoding.go new file mode 100644 index 0000000..7f46d7a --- /dev/null +++ b/internal/testdata/color2_enum_encoding.go @@ -0,0 +1,43 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import "errors" + +var ErrUnknownColor2 = errors.New("unknown Color2") + +func (s *Color2) UnmarshalText(text []byte) error { + switch string(text) { + case "": + *s = UndefinedColor + case "red": + *s = Red + case "": + *s = UndefCurrency + case "SGD": + *s = SGD + case "USD": + *s = USD + default: + return ErrUnknownColor2 + } + return nil +} + +var json_bytes_Color2 = [...][]byte{[]byte(""), []byte("red"), []byte(""), []byte("SGD"), []byte("USD")} + +func (s Color2) MarshalText() ([]byte, error) { + switch s { + case UndefinedColor: + return json_bytes_Color2[0], nil + case Red: + return json_bytes_Color2[1], nil + case UndefCurrency: + return json_bytes_Color2[2], nil + case SGD: + return json_bytes_Color2[3], nil + case USD: + return json_bytes_Color2[4], nil + default: + return nil, ErrUnknownColor2 + } +} diff --git a/internal/testdata/color2_enum_encoding_test.go b/internal/testdata/color2_enum_encoding_test.go new file mode 100644 index 0000000..0c21460 --- /dev/null +++ b/internal/testdata/color2_enum_encoding_test.go @@ -0,0 +1,74 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import ( + "encoding/json" + "errors" + "slices" + "testing" +) + +func TestJSON_Color2(t *testing.T) { + type V struct { + Values []Color2 `json:"values"` + } + + values := []Color2{UndefinedColor, Red, UndefCurrency, SGD, USD} + + var v V + s := `{"values":["","red","","SGD","USD"]}` + json.Unmarshal([]byte(s), &v) + + if len(v.Values) != len(values) { + t.Errorf("cannot decode: %d", len(v.Values)) + } + if !slices.Equal(v.Values, values) { + t.Errorf("wrong decoded: %v", v.Values) + } + + b, err := json.Marshal(v) + if err != nil { + t.Fatalf("cannot encode: %s", err) + } + if string(b) != s { + t.Errorf("wrong encoded: %s != %s", string(b), s) + } + + t.Run("when unknown value, then error", func(t *testing.T) { + s := `{"values":["something"]}` + var v V + err := json.Unmarshal([]byte(s), &v) + if err == nil { + t.Errorf("must be error") + } + if !errors.Is(err, ErrUnknownColor2) { + t.Errorf("wrong error: %s", err) + } + }) +} + +func BenchmarkMarshalText_Color2(b *testing.B) { + var v []byte + var err error + for i := 0; i < b.N; i++ { + for _, c := range []Color2{UndefinedColor, Red, UndefCurrency, SGD, USD} { + if v, err = c.MarshalText(); err != nil { + b.Fatal("empty") + } + } + } + if len(v) > 1000 { + b.Fatal("noop") + } +} + +func BenchmarkUnmarshalText_Color2(b *testing.B) { + var x Color2 + for i := 0; i < b.N; i++ { + for _, c := range []string{"", "red", "", "SGD", "USD"} { + if err := x.UnmarshalText([]byte(c)); err != nil { + b.Fatal("cannot decode") + } + } + } +} diff --git a/internal/testdata/currency2_enum_encoding.go b/internal/testdata/currency2_enum_encoding.go new file mode 100644 index 0000000..e7b9099 --- /dev/null +++ b/internal/testdata/currency2_enum_encoding.go @@ -0,0 +1,43 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import "errors" + +var ErrUnknownCurrency2 = errors.New("unknown Currency2") + +func (s *Currency2) UnmarshalText(text []byte) error { + switch string(text) { + case "": + *s = UndefinedColor + case "red": + *s = Red + case "": + *s = UndefCurrency + case "SGD": + *s = SGD + case "USD": + *s = USD + default: + return ErrUnknownCurrency2 + } + return nil +} + +var json_bytes_Currency2 = [...][]byte{[]byte(""), []byte("red"), []byte(""), []byte("SGD"), []byte("USD")} + +func (s Currency2) MarshalText() ([]byte, error) { + switch s { + case UndefinedColor: + return json_bytes_Currency2[0], nil + case Red: + return json_bytes_Currency2[1], nil + case UndefCurrency: + return json_bytes_Currency2[2], nil + case SGD: + return json_bytes_Currency2[3], nil + case USD: + return json_bytes_Currency2[4], nil + default: + return nil, ErrUnknownCurrency2 + } +} diff --git a/internal/testdata/currency2_enum_encoding_test.go b/internal/testdata/currency2_enum_encoding_test.go new file mode 100644 index 0000000..c49540c --- /dev/null +++ b/internal/testdata/currency2_enum_encoding_test.go @@ -0,0 +1,74 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import ( + "encoding/json" + "errors" + "slices" + "testing" +) + +func TestJSON_Currency2(t *testing.T) { + type V struct { + Values []Currency2 `json:"values"` + } + + values := []Currency2{UndefinedColor, Red, UndefCurrency, SGD, USD} + + var v V + s := `{"values":["","red","","SGD","USD"]}` + json.Unmarshal([]byte(s), &v) + + if len(v.Values) != len(values) { + t.Errorf("cannot decode: %d", len(v.Values)) + } + if !slices.Equal(v.Values, values) { + t.Errorf("wrong decoded: %v", v.Values) + } + + b, err := json.Marshal(v) + if err != nil { + t.Fatalf("cannot encode: %s", err) + } + if string(b) != s { + t.Errorf("wrong encoded: %s != %s", string(b), s) + } + + t.Run("when unknown value, then error", func(t *testing.T) { + s := `{"values":["something"]}` + var v V + err := json.Unmarshal([]byte(s), &v) + if err == nil { + t.Errorf("must be error") + } + if !errors.Is(err, ErrUnknownCurrency2) { + t.Errorf("wrong error: %s", err) + } + }) +} + +func BenchmarkMarshalText_Currency2(b *testing.B) { + var v []byte + var err error + for i := 0; i < b.N; i++ { + for _, c := range []Currency2{UndefinedColor, Red, UndefCurrency, SGD, USD} { + if v, err = c.MarshalText(); err != nil { + b.Fatal("empty") + } + } + } + if len(v) > 1000 { + b.Fatal("noop") + } +} + +func BenchmarkUnmarshalText_Currency2(b *testing.B) { + var x Currency2 + for i := 0; i < b.N; i++ { + for _, c := range []string{"", "red", "", "SGD", "USD"} { + if err := x.UnmarshalText([]byte(c)); err != nil { + b.Fatal("cannot decode") + } + } + } +} diff --git a/internal/testdata/exp/color2_enum_encoding.go b/internal/testdata/exp/color2_enum_encoding.go new file mode 100644 index 0000000..21775a9 --- /dev/null +++ b/internal/testdata/exp/color2_enum_encoding.go @@ -0,0 +1,31 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import "errors" + +var ErrUnknownColor2 = errors.New("unknown Color2") + +func (s *Color2) UnmarshalText(text []byte) error { + switch string(text) { + case "": + *s = UndefinedColor + case "red": + *s = Red + default: + return ErrUnknownColor2 + } + return nil +} + +var json_bytes_Color2 = [...][]byte{[]byte(""), []byte("red")} + +func (s Color2) MarshalText() ([]byte, error) { + switch s { + case UndefinedColor: + return json_bytes_Color2[0], nil + case Red: + return json_bytes_Color2[1], nil + default: + return nil, ErrUnknownColor2 + } +} diff --git a/internal/testdata/exp/color2_enum_encoding_test.go b/internal/testdata/exp/color2_enum_encoding_test.go new file mode 100644 index 0000000..6319f5d --- /dev/null +++ b/internal/testdata/exp/color2_enum_encoding_test.go @@ -0,0 +1,74 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import ( + "encoding/json" + "errors" + "slices" + "testing" +) + +func TestJSON_Color2(t *testing.T) { + type V struct { + Values []Color2 `json:"values"` + } + + values := []Color2{UndefinedColor, Red} + + var v V + s := `{"values":["","red"]}` + json.Unmarshal([]byte(s), &v) + + if len(v.Values) != len(values) { + t.Errorf("cannot decode: %d", len(v.Values)) + } + if !slices.Equal(v.Values, values) { + t.Errorf("wrong decoded: %v", v.Values) + } + + b, err := json.Marshal(v) + if err != nil { + t.Fatalf("cannot encode: %s", err) + } + if string(b) != s { + t.Errorf("wrong encoded: %s != %s", string(b), s) + } + + t.Run("when unknown value, then error", func(t *testing.T) { + s := `{"values":["something"]}` + var v V + err := json.Unmarshal([]byte(s), &v) + if err == nil { + t.Errorf("must be error") + } + if !errors.Is(err, ErrUnknownColor2) { + t.Errorf("wrong error: %s", err) + } + }) +} + +func BenchmarkMarshalText_Color2(b *testing.B) { + var v []byte + var err error + for i := 0; i < b.N; i++ { + for _, c := range []Color2{UndefinedColor, Red} { + if v, err = c.MarshalText(); err != nil { + b.Fatal("empty") + } + } + } + if len(v) > 1000 { + b.Fatal("noop") + } +} + +func BenchmarkUnmarshalText_Color2(b *testing.B) { + var x Color2 + for i := 0; i < b.N; i++ { + for _, c := range []string{"", "red"} { + if err := x.UnmarshalText([]byte(c)); err != nil { + b.Fatal("cannot decode") + } + } + } +} diff --git a/internal/testdata/exp/currency2_enum_encoding.go b/internal/testdata/exp/currency2_enum_encoding.go new file mode 100644 index 0000000..8c8f320 --- /dev/null +++ b/internal/testdata/exp/currency2_enum_encoding.go @@ -0,0 +1,35 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import "errors" + +var ErrUnknownCurrency2 = errors.New("unknown Currency2") + +func (s *Currency2) UnmarshalText(text []byte) error { + switch string(text) { + case "": + *s = UndefCurrency + case "SGD": + *s = SGD + case "USD": + *s = USD + default: + return ErrUnknownCurrency2 + } + return nil +} + +var json_bytes_Currency2 = [...][]byte{[]byte(""), []byte("SGD"), []byte("USD")} + +func (s Currency2) MarshalText() ([]byte, error) { + switch s { + case UndefCurrency: + return json_bytes_Currency2[0], nil + case SGD: + return json_bytes_Currency2[1], nil + case USD: + return json_bytes_Currency2[2], nil + default: + return nil, ErrUnknownCurrency2 + } +} diff --git a/internal/testdata/exp/currency2_enum_encoding_test.go b/internal/testdata/exp/currency2_enum_encoding_test.go new file mode 100644 index 0000000..31ea490 --- /dev/null +++ b/internal/testdata/exp/currency2_enum_encoding_test.go @@ -0,0 +1,74 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import ( + "encoding/json" + "errors" + "slices" + "testing" +) + +func TestJSON_Currency2(t *testing.T) { + type V struct { + Values []Currency2 `json:"values"` + } + + values := []Currency2{UndefCurrency, SGD, USD} + + var v V + s := `{"values":["","SGD","USD"]}` + json.Unmarshal([]byte(s), &v) + + if len(v.Values) != len(values) { + t.Errorf("cannot decode: %d", len(v.Values)) + } + if !slices.Equal(v.Values, values) { + t.Errorf("wrong decoded: %v", v.Values) + } + + b, err := json.Marshal(v) + if err != nil { + t.Fatalf("cannot encode: %s", err) + } + if string(b) != s { + t.Errorf("wrong encoded: %s != %s", string(b), s) + } + + t.Run("when unknown value, then error", func(t *testing.T) { + s := `{"values":["something"]}` + var v V + err := json.Unmarshal([]byte(s), &v) + if err == nil { + t.Errorf("must be error") + } + if !errors.Is(err, ErrUnknownCurrency2) { + t.Errorf("wrong error: %s", err) + } + }) +} + +func BenchmarkMarshalText_Currency2(b *testing.B) { + var v []byte + var err error + for i := 0; i < b.N; i++ { + for _, c := range []Currency2{UndefCurrency, SGD, USD} { + if v, err = c.MarshalText(); err != nil { + b.Fatal("empty") + } + } + } + if len(v) > 1000 { + b.Fatal("noop") + } +} + +func BenchmarkUnmarshalText_Currency2(b *testing.B) { + var x Currency2 + for i := 0; i < b.N; i++ { + for _, c := range []string{"", "SGD", "USD"} { + if err := x.UnmarshalText([]byte(c)); err != nil { + b.Fatal("cannot decode") + } + } + } +} diff --git a/internal/testdata/multiple.go b/internal/testdata/multiple.go new file mode 100644 index 0000000..e601dec --- /dev/null +++ b/internal/testdata/multiple.go @@ -0,0 +1,19 @@ +package color + +type Color2 struct{ c uint8 } + +//go:generate go-enum-encoding -type=Color2 +var ( + UndefinedColor = Color2{} // json:"" + Red = Color2{1} // json:"red" + Purple, Orange = Color2{2}, Color2{3} // json:"blue" +) + +type Currency2 uint8 + +//go:generate go-enum-encoding -type=Currency2 +const ( + UndefCurrency Currency2 = iota // json:"" + SGD // json:"SGD" + USD // json:"USD" +) diff --git a/internal/testdata/size.go b/internal/testdata/size.go new file mode 100644 index 0000000..c8c4e24 --- /dev/null +++ b/internal/testdata/size.go @@ -0,0 +1,11 @@ +package color + +type Size uint8 + +//go:generate go-enum-encoding -type=Size +const ( + UndefinedSize Size = iota // json:"" + Small // json:"small" + Large // json:"large" + XLarge // json:"xlarge" +) diff --git a/internal/testdata/size_enum_encoding.go b/internal/testdata/size_enum_encoding.go new file mode 100644 index 0000000..a8887c3 --- /dev/null +++ b/internal/testdata/size_enum_encoding.go @@ -0,0 +1,39 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import "errors" + +var ErrUnknownSize = errors.New("unknown Size") + +func (s *Size) UnmarshalText(text []byte) error { + switch string(text) { + case "": + *s = UndefinedSize + case "small": + *s = Small + case "large": + *s = Large + case "xlarge": + *s = XLarge + default: + return ErrUnknownSize + } + return nil +} + +var json_bytes_Size = [...][]byte{[]byte(""), []byte("small"), []byte("large"), []byte("xlarge")} + +func (s Size) MarshalText() ([]byte, error) { + switch s { + case UndefinedSize: + return json_bytes_Size[0], nil + case Small: + return json_bytes_Size[1], nil + case Large: + return json_bytes_Size[2], nil + case XLarge: + return json_bytes_Size[3], nil + default: + return nil, ErrUnknownSize + } +} diff --git a/internal/testdata/size_enum_encoding_test.go b/internal/testdata/size_enum_encoding_test.go new file mode 100644 index 0000000..2d34d83 --- /dev/null +++ b/internal/testdata/size_enum_encoding_test.go @@ -0,0 +1,74 @@ +// Code generated by go-enum-encoding DO NOT EDIT +package color + +import ( + "encoding/json" + "errors" + "slices" + "testing" +) + +func TestJSON_Size(t *testing.T) { + type V struct { + Values []Size `json:"values"` + } + + values := []Size{UndefinedSize, Small, Large, XLarge} + + var v V + s := `{"values":["","small","large","xlarge"]}` + json.Unmarshal([]byte(s), &v) + + if len(v.Values) != len(values) { + t.Errorf("cannot decode: %d", len(v.Values)) + } + if !slices.Equal(v.Values, values) { + t.Errorf("wrong decoded: %v", v.Values) + } + + b, err := json.Marshal(v) + if err != nil { + t.Fatalf("cannot encode: %s", err) + } + if string(b) != s { + t.Errorf("wrong encoded: %s != %s", string(b), s) + } + + t.Run("when unknown value, then error", func(t *testing.T) { + s := `{"values":["something"]}` + var v V + err := json.Unmarshal([]byte(s), &v) + if err == nil { + t.Errorf("must be error") + } + if !errors.Is(err, ErrUnknownSize) { + t.Errorf("wrong error: %s", err) + } + }) +} + +func BenchmarkMarshalText_Size(b *testing.B) { + var v []byte + var err error + for i := 0; i < b.N; i++ { + for _, c := range []Size{UndefinedSize, Small, Large, XLarge} { + if v, err = c.MarshalText(); err != nil { + b.Fatal("empty") + } + } + } + if len(v) > 1000 { + b.Fatal("noop") + } +} + +func BenchmarkUnmarshalText_Size(b *testing.B) { + var x Size + for i := 0; i < b.N; i++ { + for _, c := range []string{"", "small", "large", "xlarge"} { + if err := x.UnmarshalText([]byte(c)); err != nil { + b.Fatal("cannot decode") + } + } + } +} diff --git a/main.go b/main.go index c5cb112..0aba429 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( _ "embed" "errors" "flag" + "fmt" "go/ast" "go/format" "go/parser" @@ -28,19 +29,20 @@ func main() { typeName string mode string fileName = os.Getenv("GOFILE") + lineNum = os.Getenv("GOLINE") packageName = os.Getenv("GOPACKAGE") ) flag.StringVar(&typeName, "type", "", "type to be generated for") flag.StringVar(&mode, "mode", "auto", "what kind of strategy used (short, long, auto)") flag.Parse() - if err := process(typeName, fileName, packageName, mode); err != nil { + if err := process(typeName, fileName, lineNum, packageName, mode); err != nil { os.Stderr.WriteString(err.Error()) os.Exit(1) } } -func process(typeName string, fileName string, packageName string, mode string) error { +func process(typeName, fileName, lineNum, packageName, mode string) error { if typeName == "" || fileName == "" || packageName == "" { return errors.New("type, file and package name must be provided") } @@ -50,37 +52,57 @@ func process(typeName string, fileName string, packageName string, mode string) return err } - f, err := parser.ParseFile(token.NewFileSet(), fileName, inputCode, parser.ParseComments) + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, fileName, inputCode, parser.ParseComments) if err != nil { return err } + expectedLine, _ := strconv.Atoi(lineNum) + expectedLine += 1 + var specs [][2]string - ast.Inspect(f, func(node ast.Node) bool { - spec, ok := node.(*ast.ValueSpec) - if !ok { + ast.Inspect(f, func(astNode ast.Node) bool { + node, ok := astNode.(*ast.GenDecl) + if !ok || (node.Tok != token.CONST && node.Tok != token.VAR) { return true } - if len(spec.Names) != 1 { + position := fset.Position(node.Pos()) + if position.Line != expectedLine { return false } - // TODO: check that type matches - tag, ok := "", false - for _, field := range strings.Fields(spec.Comment.Text()) { - if strings.HasPrefix(field, "json:") { - tag, ok = field[len("json:\""):len(field)-1], true + for _, astSpec := range node.Specs { + spec, ok := astSpec.(*ast.ValueSpec) + if !ok { + continue + } + + if len(spec.Names) != 1 { break } + + tag, ok := "", false + for _, field := range strings.Fields(spec.Comment.Text()) { + if strings.HasPrefix(field, "json:") { + tag, ok = field[len("json:\""):len(field)-1], true + break + } + } + if ok { + specs = append(specs, [2]string{spec.Names[0].Name, tag}) + } } - if ok { - specs = append(specs, [2]string{spec.Names[0].Name, tag}) - } + return false }) + if len(specs) == 0 { + return fmt.Errorf("%s: unable to find values for enum type %q", fileName, typeName) + } + code := templateCode if mode == "auto" { diff --git a/main_test.go b/main_test.go index c685925..cd43ba4 100644 --- a/main_test.go +++ b/main_test.go @@ -34,7 +34,7 @@ func TestMain(t *testing.T) { t.Run("when ok, then file matches expected", func(t *testing.T) { t.Run("when short mode, then file matches expected", func(t *testing.T) { cmd := exec.Command(testbin, "--type", "Color") - cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOLINE=5", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) cmd.Run() assertEqFile(t, "internal/testdata/color_enum_encoding.go", "internal/testdata/exp/color_enum_encoding.go") @@ -43,17 +43,41 @@ func TestMain(t *testing.T) { t.Run("when auto mode, then long can be detected and file matches expected", func(t *testing.T) { cmd := exec.Command(testbin, "--type", "Currency") - cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/currency.go", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/currency.go", "GOLINE=5", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) cmd.Run() assertEqFile(t, "internal/testdata/currency_enum_encoding.go", "internal/testdata/exp/currency_enum_encoding.go") assertEqFile(t, "internal/testdata/currency_enum_encoding_test.go", "internal/testdata/exp/currency_enum_encoding_test.go") }) + + t.Run("when multiple enums in same file, then file matches expected for each", func(t *testing.T) { + cmd := exec.Command(testbin, "--type", "Color2") + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/multiple.go", "GOLINE=5", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Run() + + assertEqFile(t, "internal/testdata/color2_enum_encoding.go", "internal/testdata/exp/color2_enum_encoding.go") + assertEqFile(t, "internal/testdata/color2_enum_encoding_test.go", "internal/testdata/exp/color2_enum_encoding_test.go") + + cmd = exec.Command(testbin, "--type", "Currency2") + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/multiple.go", "GOLINE=14", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Run() + + assertEqFile(t, "internal/testdata/currency2_enum_encoding.go", "internal/testdata/exp/currency2_enum_encoding.go") + assertEqFile(t, "internal/testdata/currency2_enum_encoding_test.go", "internal/testdata/exp/currency2_enum_encoding_test.go") + }) }) t.Run("when bad go file, then error", func(t *testing.T) { cmd := exec.Command(testbin, "--type", "Color") - cmd.Env = append(cmd.Environ(), "GOFILE=README.md", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Env = append(cmd.Environ(), "GOFILE=README.md", "GOLINE=5", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + if err := cmd.Run(); err == nil { + t.Fatal("must be error") + } + }) + + t.Run("when enum values not immediately after go:generate line, then error", func(t *testing.T) { + cmd := exec.Command(testbin, "--type", "Color") + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOLINE=1", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) if err := cmd.Run(); err == nil { t.Fatal("must be error") } @@ -61,7 +85,7 @@ func TestMain(t *testing.T) { t.Run("when invalid package name, then error", func(t *testing.T) { cmd := exec.Command(testbin, "--type", "Color") - cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOPACKAGE=\"", "GOCOVERDIR="+coverdir) + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOLINE=5", "GOPACKAGE=\"", "GOCOVERDIR="+coverdir) if err := cmd.Run(); err == nil { t.Fatal("must be error") } @@ -69,7 +93,7 @@ func TestMain(t *testing.T) { t.Run("when not found file, then error", func(t *testing.T) { cmd := exec.Command(testbin, "--type", "Color") - cmd.Env = append(cmd.Environ(), "GOFILE=asdf.asdf", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Env = append(cmd.Environ(), "GOFILE=asdf.asdf", "GOPACKAGE=color", "GOLINE=5", "GOCOVERDIR="+coverdir) if err := cmd.Run(); err == nil { t.Fatal("must be error") } @@ -77,7 +101,7 @@ func TestMain(t *testing.T) { t.Run("when wrong params, then error", func(t *testing.T) { cmd := exec.Command(testbin) - cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) + cmd.Env = append(cmd.Environ(), "GOFILE=internal/testdata/color.go", "GOLINE=5", "GOPACKAGE=color", "GOCOVERDIR="+coverdir) if err := cmd.Run(); err == nil { t.Fatal("must be error") } @@ -88,6 +112,6 @@ func assertEqFile(t *testing.T, a, b string) { fa, _ := os.ReadFile(a) fb, _ := os.ReadFile(b) if string(fa) != string(fb) { - t.Error("files are different") + t.Error("files are different (" + a + " <> " + b + ")") } }