@@ -13,6 +13,12 @@ import (
13
13
"time"
14
14
15
15
"github.com/golang/snappy"
16
+ "github.com/kr/pretty"
17
+ "github.com/shoenig/test"
18
+ "github.com/shoenig/test/must"
19
+ "github.com/stretchr/testify/assert"
20
+ "github.com/stretchr/testify/require"
21
+
16
22
"github.com/hashicorp/nomad/ci"
17
23
"github.com/hashicorp/nomad/client/allocdir"
18
24
"github.com/hashicorp/nomad/client/allocrunner/interfaces"
@@ -38,9 +44,6 @@ import (
38
44
"github.com/hashicorp/nomad/plugins/device"
39
45
"github.com/hashicorp/nomad/plugins/drivers"
40
46
"github.com/hashicorp/nomad/testutil"
41
- "github.com/kr/pretty"
42
- "github.com/stretchr/testify/assert"
43
- "github.com/stretchr/testify/require"
44
47
)
45
48
46
49
type MockTaskStateUpdater struct {
@@ -658,6 +661,61 @@ func TestTaskRunner_Restore_System(t *testing.T) {
658
661
})
659
662
}
660
663
664
+ // TestTaskRunner_MarkFailedKill asserts that MarkFailedKill marks the task as failed
665
+ // and cancels the killCtx so a subsequent Run() will do any necessary task cleanup.
666
+ func TestTaskRunner_MarkFailedKill (t * testing.T ) {
667
+ ci .Parallel (t )
668
+
669
+ // set up some taskrunner
670
+ alloc := mock .MinAlloc ()
671
+ task := alloc .Job .TaskGroups [0 ].Tasks [0 ]
672
+ conf , cleanup := testTaskRunnerConfig (t , alloc , task .Name )
673
+ t .Cleanup (cleanup )
674
+ tr , err := NewTaskRunner (conf )
675
+ must .NoError (t , err )
676
+
677
+ // side quest: set this lifecycle coordination channel,
678
+ // so early in tr MAIN, it doesn't randomly follow that route.
679
+ // test config creates this already closed, but not so in real life.
680
+ startCh := make (chan struct {})
681
+ t .Cleanup (func () { close (startCh ) })
682
+ tr .startConditionMetCh = startCh
683
+
684
+ // function under test: should mark the task as failed and cancel kill context
685
+ reason := "because i said so"
686
+ tr .MarkFailedKill (reason )
687
+
688
+ // explicitly check kill context.
689
+ select {
690
+ case <- tr .killCtx .Done ():
691
+ default :
692
+ t .Fatal ("kill context should be done" )
693
+ }
694
+
695
+ // Run() should now follow the kill path.
696
+ go tr .Run ()
697
+
698
+ select { // it should finish up very quickly
699
+ case <- tr .WaitCh ():
700
+ case <- time .After (time .Second ):
701
+ t .Error ("task not killed (or not as fast as expected)" )
702
+ }
703
+
704
+ // check state for expected values and events
705
+ state := tr .TaskState ()
706
+
707
+ // this gets set directly by MarkFailedKill()
708
+ test .True (t , state .Failed , test .Sprint ("task should have failed" ))
709
+ // this is set in Run()
710
+ test .Eq (t , structs .TaskStateDead , state .State , test .Sprint ("task should be dead" ))
711
+ // reason "because i said so" should be a task event message
712
+ foundMessages := make (map [string ]bool )
713
+ for _ , event := range state .Events {
714
+ foundMessages [event .DisplayMessage ] = true
715
+ }
716
+ test .True (t , foundMessages [reason ], test .Sprintf ("expected '%s' in events: %#v" , reason , foundMessages ))
717
+ }
718
+
661
719
// TestTaskRunner_TaskEnv_Interpolated asserts driver configurations are
662
720
// interpolated.
663
721
func TestTaskRunner_TaskEnv_Interpolated (t * testing.T ) {
0 commit comments