Skip to content

Commit

Permalink
feat: improve test coverage (#265)
Browse files Browse the repository at this point in the history
  • Loading branch information
sysulq authored Dec 26, 2024
1 parent e2bb24d commit c14a196
Show file tree
Hide file tree
Showing 14 changed files with 233 additions and 18 deletions.
1 change: 0 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
69 changes: 69 additions & 0 deletions cmd/kod/internal/format_test.go
Original file line number Diff line number Diff line change
@@ -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))
})
}
}
4 changes: 2 additions & 2 deletions cmd/kod/internal/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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
}

Expand Down
6 changes: 3 additions & 3 deletions cmd/kod/internal/generate_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
65 changes: 60 additions & 5 deletions cmd/kod/internal/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}
75 changes: 75 additions & 0 deletions cmd/kod/internal/watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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)
})
}
2 changes: 1 addition & 1 deletion examples/helloworld/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions internal/version/version_test.go
Original file line number Diff line number Diff line change
@@ -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())
})
}
2 changes: 1 addition & 1 deletion tests/case1/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/case2/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/case3/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/case4/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/case5/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/graphcase/kod_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c14a196

Please sign in to comment.