mirror of
https://github.com/DominicBreuker/pspy.git
synced 2025-12-21 03:34:50 +00:00
experiment with some tests
This commit is contained in:
committed by
Dominic Breuker
parent
cb48cc1b37
commit
f5ca2dad75
22
cmd/root.go
22
cmd/root.go
@@ -4,10 +4,14 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/dominicbreuker/pspy/internal/config"
|
||||
"github.com/dominicbreuker/pspy/internal/logger"
|
||||
"github.com/dominicbreuker/pspy/internal/inotify"
|
||||
"github.com/dominicbreuker/pspy/internal/logging"
|
||||
"github.com/dominicbreuker/pspy/internal/process"
|
||||
"github.com/dominicbreuker/pspy/internal/pspy"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -71,9 +75,19 @@ func root(cmd *cobra.Command, args []string) {
|
||||
LogPS: logPS,
|
||||
LogFS: logFS,
|
||||
}
|
||||
logger := logger.NewLogger()
|
||||
pspy.Start(cfg, logger)
|
||||
// pspy.Watch(rDirs, dirs, logPS, logFS)
|
||||
logger := logging.NewLogger()
|
||||
iw := inotify.NewInotifyWatcher()
|
||||
pscan := process.NewProcfsScanner()
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
||||
exit, err := pspy.Start(cfg, logger, iw, pscan, sigCh)
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
<-exit
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
|
||||
@@ -6,6 +6,18 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type InotifyWatcher struct{}
|
||||
|
||||
func NewInotifyWatcher() *InotifyWatcher {
|
||||
return &InotifyWatcher{}
|
||||
}
|
||||
|
||||
func (i *InotifyWatcher) Setup(rdirs, dirs []string) (chan struct{}, chan string, error) {
|
||||
triggerCh := make(chan struct{})
|
||||
fsEventCh := make(chan string)
|
||||
return triggerCh, fsEventCh, nil
|
||||
}
|
||||
|
||||
type Inotify struct {
|
||||
fd int
|
||||
watchers map[int]*watcher
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
package logger
|
||||
package logging
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logger is the logger used to print to the command line
|
||||
type Logger struct {
|
||||
infoLogger *log.Logger
|
||||
errorLogger *log.Logger
|
||||
eventLogger *log.Logger
|
||||
}
|
||||
|
||||
// NewLogger creates a new logger instance
|
||||
func NewLogger() *Logger {
|
||||
return &Logger{
|
||||
infoLogger: log.New(os.Stdout, "", 0),
|
||||
@@ -1,4 +1,4 @@
|
||||
package logger
|
||||
package logging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -6,8 +6,20 @@ import (
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ProcfsScanner struct{}
|
||||
|
||||
func NewProcfsScanner() *ProcfsScanner {
|
||||
return &ProcfsScanner{}
|
||||
}
|
||||
|
||||
func (p *ProcfsScanner) Setup(triggerCh chan struct{}, interval time.Duration) (chan string, error) {
|
||||
psEventCh := make(chan string)
|
||||
return psEventCh, nil
|
||||
}
|
||||
|
||||
type ProcList map[int]string
|
||||
|
||||
func NewProcList() *ProcList {
|
||||
|
||||
@@ -1,61 +1,66 @@
|
||||
package pspy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/dominicbreuker/pspy/internal/config"
|
||||
"github.com/dominicbreuker/pspy/internal/inotify"
|
||||
"github.com/dominicbreuker/pspy/internal/logger"
|
||||
"github.com/dominicbreuker/pspy/internal/process"
|
||||
"github.com/dominicbreuker/pspy/internal/walker"
|
||||
)
|
||||
|
||||
func Start(cfg config.Config, logger *logger.Logger) {
|
||||
fmt.Printf("Config: %+v\n", cfg)
|
||||
type Logger interface {
|
||||
Infof(format string, v ...interface{})
|
||||
Errorf(format string, v ...interface{})
|
||||
Eventf(format string, v ...interface{})
|
||||
}
|
||||
|
||||
triggerCh, fsEventCh, err := setupInotify(cfg.RDirs, cfg.Dirs)
|
||||
type InotifyWatcher interface {
|
||||
Setup(rdirs, dirs []string) (chan struct{}, chan string, error)
|
||||
}
|
||||
|
||||
type ProcfsScanner interface {
|
||||
Setup(triggerCh chan struct{}, interval time.Duration) (chan string, error)
|
||||
}
|
||||
|
||||
func Start(cfg config.Config, logger Logger, inotify InotifyWatcher, pscan ProcfsScanner, sigCh chan os.Signal) (chan struct{}, error) {
|
||||
logger.Infof("Config: %+v\n", cfg)
|
||||
|
||||
triggerCh, fsEventCh, err := inotify.Setup(cfg.RDirs, cfg.Dirs)
|
||||
if err != nil {
|
||||
logger.Errorf("Can't set up inotify watchers: %v\n", err)
|
||||
return nil, errors.New("inotify error")
|
||||
}
|
||||
psEventCh, err := setupProcfsScanner(triggerCh, 100*time.Millisecond)
|
||||
psEventCh, err := pscan.Setup(triggerCh, 100*time.Millisecond)
|
||||
if err != nil {
|
||||
logger.Errorf("Can't set up procfs scanner: %+v\n", err)
|
||||
return nil, errors.New("procfs scanner error")
|
||||
}
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
exit := make(chan struct{})
|
||||
|
||||
for {
|
||||
select {
|
||||
case se := <-sigCh:
|
||||
logger.Infof("Exiting program... (%s)\n", se)
|
||||
os.Exit(0)
|
||||
case fe := <-fsEventCh:
|
||||
if cfg.LogFS {
|
||||
logger.Eventf("FS: %+v\n", fe)
|
||||
}
|
||||
case pe := <-psEventCh:
|
||||
if cfg.LogPS {
|
||||
logger.Eventf("CMD: %+v\n", pe)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case se := <-sigCh:
|
||||
logger.Infof("Exiting program... (%s)\n", se)
|
||||
exit <- struct{}{}
|
||||
case fe := <-fsEventCh:
|
||||
if cfg.LogFS {
|
||||
logger.Eventf("FS: %+v\n", fe)
|
||||
}
|
||||
case pe := <-psEventCh:
|
||||
if cfg.LogPS {
|
||||
logger.Eventf("CMD: %+v\n", pe)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setupInotify(rdirs, dirs []string) (chan struct{}, chan string, error) {
|
||||
triggerCh := make(chan struct{})
|
||||
fsEventCh := make(chan string)
|
||||
return triggerCh, fsEventCh, nil
|
||||
}
|
||||
|
||||
func setupProcfsScanner(triggerCh chan struct{}, interval time.Duration) (chan string, error) {
|
||||
psEventCh := make(chan string)
|
||||
return psEventCh, nil
|
||||
}()
|
||||
return exit, nil
|
||||
}
|
||||
|
||||
const MaxInt = int(^uint(0) >> 1)
|
||||
|
||||
133
internal/pspy/pspy_test.go
Normal file
133
internal/pspy/pspy_test.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package pspy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/dominicbreuker/pspy/internal/config"
|
||||
)
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
cfg := config.Config{
|
||||
RDirs: []string{"rdir"},
|
||||
Dirs: []string{"dir"},
|
||||
LogFS: true,
|
||||
LogPS: true,
|
||||
}
|
||||
mockLogger := newMockLogger()
|
||||
mockIW := newMockInotifyWatcher(nil)
|
||||
mockPS := newMockProcfsScanner(nil)
|
||||
sigCh := make(chan os.Signal)
|
||||
|
||||
exit, err := Start(cfg, mockLogger, mockIW, mockPS, sigCh)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpcted error: %v", err)
|
||||
}
|
||||
mockIW.fsEventCh <- "some fs event"
|
||||
expectMsg(t, mockLogger.Event, "FS: some fs event\n")
|
||||
|
||||
mockPS.psEventCh <- "some ps event"
|
||||
expectMsg(t, mockLogger.Event, "CMD: some ps event\n")
|
||||
|
||||
sigCh <- syscall.SIGINT
|
||||
expectExit(t, exit)
|
||||
}
|
||||
|
||||
func expectMsg(t *testing.T, ch chan string, msg string) {
|
||||
select {
|
||||
case received := <-ch:
|
||||
if received != msg {
|
||||
t.Fatalf("Wanted to receive %s but got %s", msg, received)
|
||||
}
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
t.Fatalf("Did not receive message in time. Wanted: %s", msg)
|
||||
}
|
||||
}
|
||||
|
||||
func expectExit(t *testing.T, ch chan struct{}) {
|
||||
select {
|
||||
case <-ch:
|
||||
return
|
||||
case <-time.After(500 * time.Millisecond):
|
||||
t.Fatalf("Did not receive exit signal in time")
|
||||
}
|
||||
}
|
||||
|
||||
// ##### Mocks #####
|
||||
|
||||
// Logger
|
||||
|
||||
type mockLogger struct {
|
||||
Info chan string
|
||||
Error chan string
|
||||
Event chan string
|
||||
}
|
||||
|
||||
func newMockLogger() *mockLogger {
|
||||
return &mockLogger{
|
||||
Info: make(chan string, 10),
|
||||
Error: make(chan string, 10),
|
||||
Event: make(chan string, 10),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *mockLogger) Infof(format string, v ...interface{}) {
|
||||
l.Info <- fmt.Sprintf(format, v...)
|
||||
}
|
||||
|
||||
func (l *mockLogger) Errorf(format string, v ...interface{}) {
|
||||
l.Error <- fmt.Sprintf(format, v...)
|
||||
}
|
||||
|
||||
func (l *mockLogger) Eventf(format string, v ...interface{}) {
|
||||
l.Event <- fmt.Sprintf(format, v...)
|
||||
}
|
||||
|
||||
// InotfiyWatcher
|
||||
|
||||
type mockInotifyWatcher struct {
|
||||
triggerCh chan struct{}
|
||||
fsEventCh chan string
|
||||
setupErr error
|
||||
}
|
||||
|
||||
func newMockInotifyWatcher(setupErr error) *mockInotifyWatcher {
|
||||
return &mockInotifyWatcher{
|
||||
triggerCh: make(chan struct{}),
|
||||
fsEventCh: make(chan string),
|
||||
setupErr: setupErr,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *mockInotifyWatcher) Setup(rdirs, dirs []string) (chan struct{}, chan string, error) {
|
||||
if i.setupErr != nil {
|
||||
return nil, nil, i.setupErr
|
||||
}
|
||||
return i.triggerCh, i.fsEventCh, nil
|
||||
}
|
||||
|
||||
// ProcfsScanner
|
||||
|
||||
type mockProcfsScanner struct {
|
||||
triggerCh chan struct{}
|
||||
interval time.Duration
|
||||
psEventCh chan string
|
||||
setupErr error
|
||||
}
|
||||
|
||||
func newMockProcfsScanner(setupErr error) *mockProcfsScanner {
|
||||
return &mockProcfsScanner{
|
||||
psEventCh: make(chan string),
|
||||
setupErr: setupErr,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *mockProcfsScanner) Setup(triggerCh chan struct{}, interval time.Duration) (chan string, error) {
|
||||
if p.setupErr != nil {
|
||||
return nil, p.setupErr
|
||||
}
|
||||
return p.psEventCh, nil
|
||||
}
|
||||
Reference in New Issue
Block a user