add tests for main method

This commit is contained in:
Dominic Breuker
2018-03-16 09:33:22 +01:00
parent 9b43b8fe9d
commit f412c74160
4 changed files with 125 additions and 14 deletions

View File

@@ -7,6 +7,7 @@ import (
"os/signal" "os/signal"
"strings" "strings"
"syscall" "syscall"
"time"
"github.com/dominicbreuker/pspy/internal/config" "github.com/dominicbreuker/pspy/internal/config"
"github.com/dominicbreuker/pspy/internal/fswatcher" "github.com/dominicbreuker/pspy/internal/fswatcher"
@@ -69,10 +70,12 @@ func root(cmd *cobra.Command, args []string) {
logger := logging.NewLogger() logger := logging.NewLogger()
cfg := &config.Config{ cfg := &config.Config{
RDirs: rDirs, RDirs: rDirs,
Dirs: dirs, Dirs: dirs,
LogPS: logPS, LogPS: logPS,
LogFS: logFS, LogFS: logFS,
DrainFor: 1 * time.Second,
TriggerEvery: 100 * time.Millisecond,
} }
fsw := fswatcher.NewFSWatcher() fsw := fswatcher.NewFSWatcher()
defer fsw.Close() defer fsw.Close()

View File

@@ -1,12 +1,17 @@
package config package config
import "fmt" import (
"fmt"
"time"
)
type Config struct { type Config struct {
RDirs []string RDirs []string
Dirs []string Dirs []string
LogFS bool LogFS bool
LogPS bool LogPS bool
DrainFor time.Duration
TriggerEvery time.Duration
} }
func (c Config) String() string { func (c Config) String() string {

View File

@@ -30,10 +30,10 @@ type PSScanner interface {
} }
func Start(cfg *config.Config, b *Bindings, sigCh chan os.Signal) chan struct{} { func Start(cfg *config.Config, b *Bindings, sigCh chan os.Signal) chan struct{} {
b.Logger.Infof("Config: %+v\n", cfg) b.Logger.Infof("Config: %+v", cfg)
initFSW(b.FSW, cfg.RDirs, cfg.Dirs, b.Logger) initFSW(b.FSW, cfg.RDirs, cfg.Dirs, b.Logger)
triggerCh, fsEventCh := startFSW(b.FSW, b.Logger, 1*time.Second) triggerCh, fsEventCh := startFSW(b.FSW, b.Logger, cfg.DrainFor)
psEventCh := startPSS(b.PSS, b.Logger, triggerCh) psEventCh := startPSS(b.PSS, b.Logger, triggerCh)

View File

@@ -3,8 +3,12 @@ package pspy
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"testing" "testing"
"time" "time"
"github.com/dominicbreuker/pspy/internal/config"
"github.com/dominicbreuker/pspy/internal/logging"
) )
func TestInitFSW(t *testing.T) { func TestInitFSW(t *testing.T) {
@@ -50,6 +54,67 @@ func TestStartFSW(t *testing.T) {
expectMessage(t, fsEventCh, "event sent after draining") expectMessage(t, fsEventCh, "event sent after draining")
} }
func TestStartPSS(t *testing.T) {
pss := newMockPSScanner()
l := newMockLogger()
triggerCh := make(chan struct{})
go func() {
pss.runErrCh <- errors.New("error during refresh")
}()
startPSS(pss, l, triggerCh)
expectMessage(t, l.Error, "ERROR: error during refresh")
}
func TestStart(t *testing.T) {
drainFor := 10 * time.Millisecond
triggerEvery := 999 * time.Second
l := newMockLogger()
fsw := newMockFSWatcher()
pss := newMockPSScanner()
b := &Bindings{
Logger: l,
FSW: fsw,
PSS: pss,
}
cfg := &config.Config{
RDirs: []string{"rdir1", "rdir2"},
Dirs: []string{"dir1", "dir2"},
LogFS: true,
LogPS: true,
DrainFor: drainFor,
TriggerEvery: triggerEvery,
}
sigCh := make(chan os.Signal)
go func() {
close(fsw.initDoneCh)
<-time.After(2 * drainFor)
fsw.runTriggerCh <- struct{}{}
pss.runEventCh <- "pss event"
pss.runErrCh <- errors.New("pss error")
fsw.runEventCh <- "fsw event"
fsw.runErrCh <- errors.New("fsw error")
sigCh <- os.Interrupt
}()
exitCh := Start(cfg, b, sigCh)
expectMessage(t, l.Info, "Config: Printing events: processes=true | file-system-events=true ||| Watching directories: [rdir1 rdir2] (recursive) | [dir1 dir2] (non-recursive)")
expectMessage(t, l.Info, "Draining file system events due to startup...")
<-time.After(2 * drainFor)
expectMessage(t, l.Info, "done")
expectTrigger(t, pss.runTriggerCh) // pss receives triggers from fsw
expectMessage(t, l.Event, fmt.Sprintf("%d CMD: pss event", logging.ColorRed))
expectMessage(t, l.Error, "ERROR: pss error")
expectMessage(t, l.Event, fmt.Sprintf("%d FS: fsw event", logging.ColorGreen))
expectMessage(t, l.Error, "ERROR: fsw error")
expectMessage(t, l.Info, "Exiting program... (interrupt)")
expectExit(t, exitCh)
}
// #### Helpers #### // #### Helpers ####
var timeout = 100 * time.Millisecond var timeout = 100 * time.Millisecond
@@ -59,7 +124,7 @@ func expectMessage(t *testing.T, ch chan string, expected string) {
select { select {
case actual := <-ch: case actual := <-ch:
if actual != expected { if actual != expected {
t.Fatalf("Wrong message: got '%s' but wanted %s", actual, expected) t.Fatalf("Wrong message: got '%s' but wanted '%s'", actual, expected)
} }
case <-time.After(timeout): case <-time.After(timeout):
t.Fatalf("Did not get message in time: %s", expected) t.Fatalf("Did not get message in time: %s", expected)
@@ -67,11 +132,23 @@ func expectMessage(t *testing.T, ch chan string, expected string) {
} }
func expectTrigger(t *testing.T, ch chan struct{}) { func expectTrigger(t *testing.T, ch chan struct{}) {
if err := expectChanMsg(ch); err != nil {
t.Fatalf("triggering: %v", err)
}
}
func expectExit(t *testing.T, ch chan struct{}) {
if err := expectChanMsg(ch); err != nil {
t.Fatalf("exiting: %v", err)
}
}
func expectChanMsg(ch chan struct{}) error {
select { select {
case <-ch: case <-ch:
return return nil
case <-time.After(timeout): case <-time.After(timeout):
t.Fatalf("Did not get trigger in time") return fmt.Errorf("did not get message in time")
} }
} }
@@ -150,3 +227,29 @@ func (fsw *mockFSWatcher) Init(rdirs, dirs []string) (chan error, chan struct{})
func (fsw *mockFSWatcher) Run() (chan struct{}, chan string, chan error) { func (fsw *mockFSWatcher) Run() (chan struct{}, chan string, chan error) {
return fsw.runTriggerCh, fsw.runEventCh, fsw.runErrCh return fsw.runTriggerCh, fsw.runEventCh, fsw.runErrCh
} }
// PSScanner
type mockPSScanner struct {
runTriggerCh chan struct{}
runEventCh chan string
runErrCh chan error
numRefreshes int
}
func newMockPSScanner() *mockPSScanner {
return &mockPSScanner{}
}
func (pss *mockPSScanner) Run(triggerCh chan struct{}) (chan string, chan error) {
pss.runTriggerCh = triggerCh
pss.runEventCh = make(chan string)
pss.runErrCh = make(chan error)
go func() {
<-pss.runTriggerCh
pss.numRefreshes++ // count number of times we refreshed
}()
return pss.runEventCh, pss.runErrCh
}