Skip to content

Commit 635ed43

Browse files
authored
Add unit tests for workunitbase and wrap fsnotify library calls (#866)
1 parent 215c103 commit 635ed43

File tree

10 files changed

+541
-36
lines changed

10 files changed

+541
-36
lines changed

pkg/workceptor/command.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ func (cw *commandUnit) runCommand(cmd *exec.Cmd) error {
219219
})
220220
}()
221221
go cmdWaiter(cmd, doneChan)
222-
go cw.monitorLocalStatus()
222+
go cw.MonitorLocalStatus()
223223

224224
return nil
225225
}
@@ -263,7 +263,7 @@ func (cw *commandUnit) Restart() error {
263263
// Job never started - mark it failed
264264
cw.UpdateBasicStatus(WorkStateFailed, "Pending at restart", stdoutSize(cw.UnitDir()))
265265
}
266-
go cw.monitorLocalStatus()
266+
go cw.MonitorLocalStatus()
267267

268268
return nil
269269
}
@@ -331,7 +331,7 @@ func (cfg CommandWorkerCfg) NewWorker(w *Workceptor, unitID string, workType str
331331
baseParams: cfg.Params,
332332
allowRuntimeParams: cfg.AllowRuntimeParams,
333333
}
334-
cw.BaseWorkUnit.Init(w, unitID, workType)
334+
cw.BaseWorkUnit.Init(w, unitID, workType, FileSystem{}, nil)
335335

336336
return cw
337337
}

pkg/workceptor/json_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func newCommandWorker(w *Workceptor, unitID string, workType string) WorkUnit {
2222
baseParams: "foo",
2323
allowRuntimeParams: true,
2424
}
25-
cw.BaseWorkUnit.Init(w, unitID, workType)
25+
cw.BaseWorkUnit.Init(w, unitID, workType, FileSystem{}, nil)
2626

2727
return cw
2828
}

pkg/workceptor/kubernetes.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,7 @@ func (kw *kubeUnit) startOrRestart() error {
12721272
} else {
12731273
go kw.runWorkUsingLogger()
12741274
}
1275-
go kw.monitorLocalStatus()
1275+
go kw.MonitorLocalStatus()
12761276

12771277
return nil
12781278
}
@@ -1388,7 +1388,7 @@ func (cfg KubeWorkerCfg) NewWorker(w *Workceptor, unitID string, workType string
13881388
deletePodOnRestart: cfg.DeletePodOnRestart,
13891389
namePrefix: fmt.Sprintf("%s-", strings.ToLower(cfg.WorkType)),
13901390
}
1391-
ku.BaseWorkUnit.Init(w, unitID, workType)
1391+
ku.BaseWorkUnit.Init(w, unitID, workType, FileSystem{}, nil)
13921392

13931393
return ku
13941394
}

pkg/workceptor/mock_workceptor/stdio_utils.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/workceptor/mock_workceptor/workunitbase.go

Lines changed: 76 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/workceptor/python.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (cfg workPythonCfg) NewWorker(w *Workceptor, unitID string, workType string
6363
function: cfg.Function,
6464
config: cfg.Config,
6565
}
66-
cw.BaseWorkUnit.Init(w, unitID, workType)
66+
cw.BaseWorkUnit.Init(w, unitID, workType, FileSystem{}, nil)
6767

6868
return cw
6969
}

pkg/workceptor/remote_work.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ func (rw *remoteUnit) Release(force bool) error {
680680

681681
func newRemoteWorker(w *Workceptor, unitID, workType string) WorkUnit {
682682
rw := &remoteUnit{logger: w.nc.GetLogger()}
683-
rw.BaseWorkUnit.Init(w, unitID, workType)
683+
rw.BaseWorkUnit.Init(w, unitID, workType, FileSystem{}, nil)
684684
red := &remoteExtraData{}
685685
red.RemoteParams = make(map[string]string)
686686
rw.status.ExtraData = red

pkg/workceptor/stdio_utils.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type FileSystemer interface {
1616
OpenFile(name string, flag int, perm os.FileMode) (*os.File, error)
1717
Stat(name string) (os.FileInfo, error)
1818
Open(name string) (*os.File, error)
19+
RemoveAll(path string) error
1920
}
2021

2122
// FileSystem represents the real filesystem.
@@ -36,6 +37,11 @@ func (FileSystem) Open(name string) (*os.File, error) {
3637
return os.Open(name)
3738
}
3839

40+
// RemoveAll removes path and any children it contains.
41+
func (FileSystem) RemoveAll(path string) error {
42+
return os.RemoveAll(path)
43+
}
44+
3945
// FileWriteCloser wraps io.WriteCloser.
4046
type FileWriteCloser interface {
4147
io.WriteCloser

pkg/workceptor/workunitbase.go

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ const (
3232
WorkStateCanceled = 4
3333
)
3434

35+
// WatcherWrapper is wrapping the fsnofity Watcher struct and exposing the Event chan within.
36+
type WatcherWrapper interface {
37+
Add(name string) error
38+
Close() error
39+
EventChannel() chan fsnotify.Event
40+
}
41+
42+
type RealWatcher struct {
43+
watcher *fsnotify.Watcher
44+
}
45+
46+
func (rw *RealWatcher) Add(name string) error {
47+
return rw.watcher.Add(name)
48+
}
49+
50+
func (rw *RealWatcher) Close() error {
51+
return rw.watcher.Close()
52+
}
53+
54+
func (rw *RealWatcher) EventChannel() chan fsnotify.Event {
55+
return rw.watcher.Events
56+
}
57+
3558
// IsComplete returns true if a given WorkState indicates the job is finished.
3659
func IsComplete(workState int) bool {
3760
return workState == WorkStateSucceeded || workState == WorkStateFailed
@@ -74,10 +97,12 @@ type BaseWorkUnit struct {
7497
lastUpdateErrorLock *sync.RWMutex
7598
ctx context.Context
7699
cancel context.CancelFunc
100+
fs FileSystemer
101+
watcher WatcherWrapper
77102
}
78103

79104
// Init initializes the basic work unit data, in memory only.
80-
func (bwu *BaseWorkUnit) Init(w *Workceptor, unitID string, workType string) {
105+
func (bwu *BaseWorkUnit) Init(w *Workceptor, unitID string, workType string, fs FileSystemer, watcher WatcherWrapper) {
81106
bwu.w = w
82107
bwu.status.State = WorkStatePending
83108
bwu.status.Detail = "Unit Created"
@@ -90,6 +115,17 @@ func (bwu *BaseWorkUnit) Init(w *Workceptor, unitID string, workType string) {
90115
bwu.statusLock = &sync.RWMutex{}
91116
bwu.lastUpdateErrorLock = &sync.RWMutex{}
92117
bwu.ctx, bwu.cancel = context.WithCancel(w.ctx)
118+
bwu.fs = fs
119+
if watcher != nil {
120+
bwu.watcher = watcher
121+
} else {
122+
watcher, err := fsnotify.NewWatcher()
123+
if err == nil {
124+
bwu.watcher = &RealWatcher{watcher: watcher}
125+
} else {
126+
bwu.watcher = nil
127+
}
128+
}
93129
}
94130

95131
// Error logs message with unitID prepended.
@@ -340,33 +376,29 @@ func (bwu *BaseWorkUnit) LastUpdateError() error {
340376
return bwu.lastUpdateError
341377
}
342378

343-
// monitorLocalStatus watches a unit dir and keeps the in-memory workUnit up to date with status changes.
344-
func (bwu *BaseWorkUnit) monitorLocalStatus() {
379+
// MonitorLocalStatus watches a unit dir and keeps the in-memory workUnit up to date with status changes.
380+
func (bwu *BaseWorkUnit) MonitorLocalStatus() {
345381
statusFile := path.Join(bwu.UnitDir(), "status")
346-
watcher, err := fsnotify.NewWatcher()
347-
if err == nil {
348-
err = watcher.Add(statusFile)
382+
var watcherEvents chan fsnotify.Event
383+
watcherEvents = make(chan fsnotify.Event)
384+
385+
if bwu.watcher != nil {
386+
err := bwu.watcher.Add(statusFile)
349387
if err == nil {
350388
defer func() {
351-
_ = watcher.Close()
389+
_ = bwu.watcher.Close()
352390
}()
391+
watcherEvents = bwu.watcher.EventChannel()
353392
} else {
354-
_ = watcher.Close()
355-
watcher = nil
393+
_ = bwu.watcher.Close()
394+
bwu.watcher = nil
356395
}
357-
} else {
358-
watcher = nil
359396
}
360-
fi, err := os.Stat(statusFile)
397+
fi, err := bwu.fs.Stat(statusFile)
361398
if err != nil {
362399
fi = nil
363400
}
364-
var watcherEvents chan fsnotify.Event
365-
if watcher == nil {
366-
watcherEvents = make(chan fsnotify.Event)
367-
} else {
368-
watcherEvents = watcher.Events
369-
}
401+
370402
loop:
371403
for {
372404
select {
@@ -380,14 +412,12 @@ loop:
380412
}
381413
}
382414
case <-time.After(time.Second):
383-
newFi, err := os.Stat(statusFile)
384-
if err == nil {
385-
if fi == nil || fi.ModTime() != newFi.ModTime() {
386-
fi = newFi
387-
err = bwu.Load()
388-
if err != nil {
389-
bwu.w.nc.GetLogger().Error("Error reading %s: %s", statusFile, err)
390-
}
415+
newFi, err := bwu.fs.Stat(statusFile)
416+
if err == nil && (fi == nil || fi.ModTime() != newFi.ModTime()) {
417+
fi = newFi
418+
err = bwu.Load()
419+
if err != nil {
420+
bwu.w.nc.GetLogger().Error("Error reading %s: %s", statusFile, err)
391421
}
392422
}
393423
}
@@ -425,7 +455,7 @@ func (bwu *BaseWorkUnit) Release(force bool) error {
425455
defer bwu.statusLock.Unlock()
426456
attemptsLeft := 3
427457
for {
428-
err := os.RemoveAll(bwu.UnitDir())
458+
err := bwu.fs.RemoveAll(bwu.UnitDir())
429459
if force {
430460
break
431461
} else if err != nil {
@@ -451,11 +481,15 @@ func (bwu *BaseWorkUnit) Release(force bool) error {
451481
return nil
452482
}
453483

484+
func (bwu *BaseWorkUnit) CancelContext() {
485+
bwu.cancel()
486+
}
487+
454488
// =============================================================================================== //
455489

456490
func newUnknownWorker(w *Workceptor, unitID string, workType string) WorkUnit {
457491
uu := &unknownUnit{}
458-
uu.BaseWorkUnit.Init(w, unitID, workType)
492+
uu.BaseWorkUnit.Init(w, unitID, workType, FileSystem{}, nil)
459493

460494
return uu
461495
}

0 commit comments

Comments
 (0)