Skip to content

Commit

Permalink
ci: improve test coverage (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
sysulq authored Sep 10, 2024
1 parent 2ba3ef6 commit dbc9f26
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 31 deletions.
8 changes: 2 additions & 6 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@ tasks:

build:gowork:
run: once
sources:
- /ext
- /tests
generates:
- go.work
- go.work.sum
status:
- test -f ../go.work || test -f go.work
cmds:
- go work init
- go work use -r .
Expand Down
22 changes: 12 additions & 10 deletions cmd/kod/internal/generate.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"context"
"fmt"
"path/filepath"
"time"
Expand All @@ -19,23 +20,24 @@ var generate = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
{
if watch, _ := cmd.Flags().GetBool("watch"); watch {
// Create new watcher.
w := lo.Must(fsnotify.NewWatcher())
defer w.Close()

Watch(&watcher{w: w}, ".",
func(event fsnotify.Event) {
doGenerate(cmd, filepath.Dir(event.Name), args)
},
lo.Must(cmd.Flags().GetBool("verbose")),
)
startWatcher(cmd.Context(), cmd, args)
}

doGenerate(cmd, "./", args)
}
},
}

func startWatcher(ctx context.Context, cmd *cobra.Command, args []string) {
// Create new watcher.
w := lo.Must(fsnotify.NewWatcher())
defer w.Close()

Watch(&watcher{ctx: ctx, w: w}, ".",
func(event fsnotify.Event) { doGenerate(cmd, filepath.Dir(event.Name), args) }, lo.Must(cmd.Flags().GetBool("verbose")),
)
}

func doGenerate(cmd *cobra.Command, dir string, args []string) {
startTime := time.Now()

Expand Down
8 changes: 8 additions & 0 deletions cmd/kod/internal/generate_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package internal

import (
"context"
"testing"
"time"
)

func TestGenerate(t *testing.T) {
Expand All @@ -11,3 +13,9 @@ func TestGenerate(t *testing.T) {
func TestGenerateWithStruct2Interface(t *testing.T) {
execute(t, "generate -s github.com/go-kod/kod/tests/graphcase/...")
}

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/..."})
}
11 changes: 0 additions & 11 deletions cmd/kod/internal/generate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"sort"

"golang.org/x/tools/go/packages"
"golang.org/x/tools/go/types/typeutil"
)

const kodPackagePath = "github.com/go-kod/kod"
Expand All @@ -17,16 +16,6 @@ type typeSet struct {
imported []importPkg // imported packages
importedByPath map[string]importPkg // imported, indexed by path
importedByName map[string]importPkg // imported, indexed by name

// If checked[t] != nil, then checked[t] is the cached result of calling
// check(pkg, t, string[]{}). Otherwise, if checked[t] == nil, then t has
// not yet been checked for serializability. Read typeutil.Map's
// documentation for why checked shouldn't be a map[types.Type]bool.
// checked typeutil.Map

// If measurable[t] != nil, then measurable[t] == isMeasurableType(t).
//nolint
measurable typeutil.Map
}

// importPkg is a package imported by the generated code.
Expand Down
16 changes: 16 additions & 0 deletions cmd/kod/internal/mock_watcher_test.go

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

13 changes: 12 additions & 1 deletion cmd/kod/internal/watcher.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"context"
"fmt"
"log"
"os"
Expand All @@ -16,10 +17,12 @@ type Watcher interface {
Remove(string) error
Events() chan fsnotify.Event
Errors() chan error
Context() context.Context
}

type watcher struct {
w *fsnotify.Watcher
ctx context.Context
w *fsnotify.Watcher
}

func (w *watcher) Add(name string) error {
Expand All @@ -34,6 +37,10 @@ func (w *watcher) Errors() chan error {
return w.w.Errors
}

func (w *watcher) Context() context.Context {
return w.ctx
}

func (w *watcher) Remove(name string) error {
return w.w.Remove(name)
}
Expand All @@ -53,6 +60,7 @@ func Watch(watcher Watcher, dir string, callback func(fsnotify.Event), verbose b
go func() {
for {
select {

case event, ok := <-watcher.Events():
if !ok {
stop <- struct{}{}
Expand Down Expand Up @@ -93,6 +101,9 @@ func Watch(watcher Watcher, dir string, callback func(fsnotify.Event), verbose b
}
log.Println("error:", err)
stop <- struct{}{}
case <-watcher.Context().Done():
stop <- struct{}{}
return
}
}
}()
Expand Down
11 changes: 11 additions & 0 deletions cmd/kod/internal/watcher_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package internal

import (
"context"
"errors"
"testing"
"time"
Expand All @@ -25,6 +26,7 @@ func TestWatcherNormal(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -47,6 +49,7 @@ func TestWatcherNotExistFile(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -69,6 +72,7 @@ func TestWatcherAddDir(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -92,6 +96,7 @@ func TestWatcherRemoveDir(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -114,6 +119,7 @@ func TestWatcherNonGofile(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -136,6 +142,7 @@ func TestWatcherInvalidEvents(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -154,6 +161,7 @@ func TestWatcherErrors(t *testing.T) {
events <- fsnotify.ErrEventOverflow
w.EXPECT().Events().Return(nil).AnyTimes()
w.EXPECT().Errors().Return(events).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

Watch(w, ".", func(fsnotify.Event) {}, true)
}
Expand All @@ -168,6 +176,7 @@ func TestWatcherAddFail(t *testing.T) {
events <- fsnotify.ErrEventOverflow
w.EXPECT().Events().Return(nil).AnyTimes()
w.EXPECT().Errors().Return(events).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

Watch(w, ".", func(fsnotify.Event) {}, true)
}
Expand All @@ -181,6 +190,7 @@ func TestWatcherErrorsClose(t *testing.T) {
events := make(chan error, 2)
w.EXPECT().Events().Return(nil).AnyTimes()
w.EXPECT().Errors().Return(events).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand All @@ -203,6 +213,7 @@ func TestWatcherFilterGenPath(t *testing.T) {

w.EXPECT().Events().Return(events).AnyTimes()
w.EXPECT().Errors().Return(nil).AnyTimes()
w.EXPECT().Context().Return(context.Background()).AnyTimes()

time.AfterFunc(time.Second, func() {
close(events)
Expand Down
11 changes: 8 additions & 3 deletions internal/singleton/singleton.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
// Singleton[T any] provides a common structure for components,
type Singleton[T any] struct {
instances map[string]*T
mu sync.Mutex
mu sync.RWMutex
}

// NewSingleton creates a new Singleton[T].
Expand All @@ -19,15 +19,20 @@ func NewSingleton[T any]() *Singleton[T] {

// Get returns the instance of the component with the given name.
func (s *Singleton[T]) Get(name string, initFn func() *T) *T {
s.mu.Lock()
defer s.mu.Unlock()
s.mu.RLock()

if instance, exists := s.instances[name]; exists {
s.mu.RUnlock()
return instance
}

s.mu.RUnlock()

instance := initFn()

s.mu.Lock()
s.instances[name] = instance
s.mu.Unlock()

return instance
}

0 comments on commit dbc9f26

Please sign in to comment.