From c14a1962b037f5e38e9da1ff3cee37514c7f5214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E5=8F=AF?= Date: Thu, 26 Dec 2024 11:54:06 +0800 Subject: [PATCH] feat: improve test coverage (#265) --- Taskfile.yml | 1 - cmd/kod/internal/format_test.go | 69 ++++++++++++++++++++++++ cmd/kod/internal/generate.go | 4 +- cmd/kod/internal/generate_generator.go | 6 +-- cmd/kod/internal/generate_test.go | 65 ++++++++++++++++++++-- cmd/kod/internal/watcher_test.go | 75 ++++++++++++++++++++++++++ examples/helloworld/kod_gen.go | 2 +- internal/version/version_test.go | 17 ++++++ tests/case1/kod_gen.go | 2 +- tests/case2/kod_gen.go | 2 +- tests/case3/kod_gen.go | 2 +- tests/case4/kod_gen.go | 2 +- tests/case5/kod_gen.go | 2 +- tests/graphcase/kod_gen.go | 2 +- 14 files changed, 233 insertions(+), 18 deletions(-) create mode 100644 cmd/kod/internal/format_test.go create mode 100644 internal/version/version_test.go diff --git a/Taskfile.yml b/Taskfile.yml index 804231c..2b32526 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -40,7 +40,6 @@ tasks: -covermode=atomic ./... ./tests/... \ -coverpkg .,./cmd/...,./internal/...,./interceptor/... git checkout tests/case1/kod_gen_mock.go - git checkout tests/graphcase/kod_gen.go sources: - "**/**.go" generates: diff --git a/cmd/kod/internal/format_test.go b/cmd/kod/internal/format_test.go new file mode 100644 index 0000000..e7eb3c9 --- /dev/null +++ b/cmd/kod/internal/format_test.go @@ -0,0 +1,69 @@ +package internal + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestImportsCode(t *testing.T) { + tests := []struct { + name string + code string + want string + wantErr bool + }{ + { + name: "simple format", + code: `package main +import "fmt" +func main(){ +fmt.Println("hello")}`, + want: `package main + +import "fmt" + +func main() { + fmt.Println("hello") +} +`, + wantErr: false, + }, + { + name: "invalid code", + code: "invalid{", + wantErr: true, + }, + { + name: "already formatted", + code: `package main + +import "fmt" + +func main() { + fmt.Println("hello") +}`, + want: `package main + +import "fmt" + +func main() { + fmt.Println("hello") +} +`, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ImportsCode(tt.code) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, string(got)) + }) + } +} diff --git a/cmd/kod/internal/generate.go b/cmd/kod/internal/generate.go index bf4db35..f285c94 100644 --- a/cmd/kod/internal/generate.go +++ b/cmd/kod/internal/generate.go @@ -43,7 +43,7 @@ func doGenerate(cmd *cobra.Command, dir string, args []string) { if s2i, _ := cmd.Flags().GetBool("struct2interface"); s2i { if err := Struct2Interface(cmd, dir); err != nil { - fmt.Println(err) + fmt.Fprint(cmd.ErrOrStderr(), err) return } fmt.Printf("[struct2interface] %s \n", time.Since(startTime).String()) @@ -52,7 +52,7 @@ func doGenerate(cmd *cobra.Command, dir string, args []string) { startTime = time.Now() if err := Generate(dir, args, Options{}); err != nil { - fmt.Println(err) + fmt.Fprint(cmd.ErrOrStderr(), err) return } diff --git a/cmd/kod/internal/generate_generator.go b/cmd/kod/internal/generate_generator.go index 0069678..64f7b20 100644 --- a/cmd/kod/internal/generate_generator.go +++ b/cmd/kod/internal/generate_generator.go @@ -675,14 +675,14 @@ func (g *generator) generateFullMethodNames(p printFn) { } func (g *generator) generateVersionCheck(p printFn) { - selfVersion := version.SelfVersion() + // selfVersion := version.SelfVersion() p(``) p(`// CodeGen version check.`) p("var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[%d][%d]struct{}](%s)", version.CodeGenMajor, version.CodeGenMinor, fmt.Sprintf("`"+` -ERROR: You generated this file with 'kod generate' %s (codegen +ERROR: You generated this file with 'kod generate' (codegen version %s). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. @@ -697,7 +697,7 @@ running the following. Then, re-run 'kod generate' and re-build your code. If the problem persists, please file an issue at https://github.com/go-kod/kod/issues. -`+"`", selfVersion, version.CodeGenSemVersion)) +`+"`", version.CodeGenSemVersion)) } // generateInstanceChecks generates code that checks that every component diff --git a/cmd/kod/internal/generate_test.go b/cmd/kod/internal/generate_test.go index 9e543a2..e041bf5 100644 --- a/cmd/kod/internal/generate_test.go +++ b/cmd/kod/internal/generate_test.go @@ -2,20 +2,75 @@ package internal import ( "context" + "path/filepath" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestGenerate(t *testing.T) { - execute(t, "generate github.com/go-kod/kod/tests/graphcase/... -v") + t.Run("generate basic case", func(t *testing.T) { + err := execute(t, "generate github.com/go-kod/kod/tests/graphcase/... -v") + require.Empty(t, err) + + // Verify generated files exist + require.FileExists(t, filepath.Join("../../../tests/graphcase", "kod_gen.go")) + }) + + t.Run("generate with invalid path", func(t *testing.T) { + err := execute(t, "generate invalid/path") + require.NotEmpty(t, err) + }) + + t.Run("generate without path", func(t *testing.T) { + err := execute(t, "generate") + require.Empty(t, err) + }) } func TestGenerateWithStruct2Interface(t *testing.T) { - execute(t, "generate -s github.com/go-kod/kod/tests/graphcase/... -v") + t.Run("struct2interface basic case", func(t *testing.T) { + err := execute(t, "generate -s github.com/go-kod/kod/tests/graphcase/... -v") + require.Empty(t, err) + }) + + t.Run("struct2interface with invalid path", func(t *testing.T) { + err := execute(t, "generate -s invalid/path") + require.NotEmpty(t, err) + }) } func TestStartWatch(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second) - defer cancel() - startWatcher(ctx, generate, []string{"github.com/go-kod/kod/tests/graphcase/..."}) + t.Run("watch with timeout", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + startWatcher(ctx, generate, []string{"github.com/go-kod/kod/tests/graphcase/..."}) + }) + + t.Run("watch without path", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + startWatcher(ctx, generate, nil) + }) + + t.Run("watch with invalid path", func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + startWatcher(ctx, generate, []string{"invalid/path"}) + }) +} + +func TestGenerateOptions(t *testing.T) { + t.Run("generate with custom warn function", func(t *testing.T) { + var warnings []error + opt := Options{ + Warn: func(err error) { + warnings = append(warnings, err) + }, + } + + err := Generate(".", []string{"github.com/go-kod/kod/tests/graphcase/..."}, opt) + require.NoError(t, err) + }) } diff --git a/cmd/kod/internal/watcher_test.go b/cmd/kod/internal/watcher_test.go index f5e06bd..0bb08ab 100644 --- a/cmd/kod/internal/watcher_test.go +++ b/cmd/kod/internal/watcher_test.go @@ -3,10 +3,13 @@ package internal import ( "context" "errors" + "os" + "path/filepath" "testing" "time" "github.com/fsnotify/fsnotify" + "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" ) @@ -221,3 +224,75 @@ func TestWatcherFilterGenPath(t *testing.T) { Watch(w, ".", func(fsnotify.Event) {}, true) } + +func TestWatch(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + t.Run("watch directory", func(t *testing.T) { + dir := t.TempDir() + mockWatcher := NewMockWatcher(ctrl) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + mockWatcher.EXPECT().Context().Return(ctx).AnyTimes() + mockWatcher.EXPECT().Add(dir).Return(nil) + mockWatcher.EXPECT().Events().Return(make(chan fsnotify.Event)).AnyTimes() + mockWatcher.EXPECT().Errors().Return(make(chan error)).AnyTimes() + + var called bool + Watch(mockWatcher, dir, func(event fsnotify.Event) { + called = true + }, true) + + require.False(t, called) // No events happened + }) + + t.Run("watch file changes", func(t *testing.T) { + dir := t.TempDir() + file := filepath.Join(dir, "test.go") + require.NoError(t, os.WriteFile(file, []byte("package test"), 0o644)) + + mockWatcher := NewMockWatcher(ctrl) + events := make(chan fsnotify.Event, 1) + errors := make(chan error) + + events <- fsnotify.Event{ + Name: file, + Op: fsnotify.Write, + } + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + mockWatcher.EXPECT().Context().Return(ctx).AnyTimes() + mockWatcher.EXPECT().Add(dir).Return(nil) + mockWatcher.EXPECT().Events().Return(events).AnyTimes() + mockWatcher.EXPECT().Errors().Return(errors).AnyTimes() + + var eventReceived fsnotify.Event + Watch(mockWatcher, dir, func(event fsnotify.Event) { + eventReceived = event + }, true) + + time.Sleep(100 * time.Millisecond) + require.Equal(t, file, eventReceived.Name) + require.Equal(t, fsnotify.Write, eventReceived.Op) + }) + + t.Run("watch errors", func(t *testing.T) { + mockWatcher := NewMockWatcher(ctrl) + events := make(chan fsnotify.Event) + errors := make(chan error, 1) + + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + mockWatcher.EXPECT().Context().Return(ctx).AnyTimes() + mockWatcher.EXPECT().Events().Return(events).AnyTimes() + mockWatcher.EXPECT().Errors().Return(errors).AnyTimes() + + Watch(mockWatcher, "invalid", func(event fsnotify.Event) {}, true) + }) +} diff --git a/examples/helloworld/kod_gen.go b/examples/helloworld/kod_gen.go index 4dc8266..c05bc12 100644 --- a/examples/helloworld/kod_gen.go +++ b/examples/helloworld/kod_gen.go @@ -70,7 +70,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. diff --git a/internal/version/version_test.go b/internal/version/version_test.go new file mode 100644 index 0000000..7ffeca4 --- /dev/null +++ b/internal/version/version_test.go @@ -0,0 +1,17 @@ +package version + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestVersion(t *testing.T) { + t.Run("version", func(t *testing.T) { + require.Equal(t, "v1.0.0", SemVer{Major: 1}.String()) + }) + + t.Run("self version", func(t *testing.T) { + require.Empty(t, SelfVersion()) + }) +} diff --git a/tests/case1/kod_gen.go b/tests/case1/kod_gen.go index 2b549eb..8588b8e 100644 --- a/tests/case1/kod_gen.go +++ b/tests/case1/kod_gen.go @@ -241,7 +241,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. diff --git a/tests/case2/kod_gen.go b/tests/case2/kod_gen.go index 0d05a03..81f9abd 100644 --- a/tests/case2/kod_gen.go +++ b/tests/case2/kod_gen.go @@ -54,7 +54,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. diff --git a/tests/case3/kod_gen.go b/tests/case3/kod_gen.go index f0fa75f..4ee7936 100644 --- a/tests/case3/kod_gen.go +++ b/tests/case3/kod_gen.go @@ -69,7 +69,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. diff --git a/tests/case4/kod_gen.go b/tests/case4/kod_gen.go index 54dcb5f..62a0267 100644 --- a/tests/case4/kod_gen.go +++ b/tests/case4/kod_gen.go @@ -69,7 +69,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. diff --git a/tests/case5/kod_gen.go b/tests/case5/kod_gen.go index 65b09b2..00944a9 100644 --- a/tests/case5/kod_gen.go +++ b/tests/case5/kod_gen.go @@ -37,7 +37,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command. diff --git a/tests/graphcase/kod_gen.go b/tests/graphcase/kod_gen.go index 3f87f7a..3127e76 100644 --- a/tests/graphcase/kod_gen.go +++ b/tests/graphcase/kod_gen.go @@ -96,7 +96,7 @@ func init() { // CodeGen version check. var _ kod.CodeGenLatestVersion = kod.CodeGenVersion[[0][1]struct{}](` -ERROR: You generated this file with 'kod generate' (devel) (codegen +ERROR: You generated this file with 'kod generate' (codegen version v0.1.0). The generated code is incompatible with the version of the github.com/go-kod/kod module that you're using. The kod module version can be found in your go.mod file or by running the following command.