@@ -1081,37 +1081,95 @@ func TestCaptureFifoToFile_leak(t *testing.T) {
1081
1081
assert .Contains (t , loggerBuffer .String (), `file already closed` , "log" )
1082
1082
}
1083
1083
1084
- func TestWaitWithKill (t * testing.T ) {
1084
+ // Replace filesystem-unsafe characters (such as /) which are often seen in Go's test names
1085
+ var fsSafeTestName = strings .NewReplacer ("/" , "_" )
1086
+
1087
+ func TestWait (t * testing.T ) {
1085
1088
fctesting .RequiresRoot (t )
1086
- ctx := context .Background ()
1087
1089
1088
- socketPath := filepath .Join (testDataPath , t .Name ())
1089
- defer os .Remove (socketPath )
1090
+ cases := []struct {
1091
+ name string
1092
+ stop func (m * Machine , cancel context.CancelFunc )
1093
+ }{
1094
+ {
1095
+ name : "StopVMM" ,
1096
+ stop : func (m * Machine , _ context.CancelFunc ) {
1097
+ err := m .StopVMM ()
1098
+ require .NoError (t , err )
1099
+ },
1100
+ },
1101
+ {
1102
+ name : "Kill" ,
1103
+ stop : func (m * Machine , cancel context.CancelFunc ) {
1104
+ pid , err := m .PID ()
1105
+ require .NoError (t , err )
1106
+
1107
+ process , err := os .FindProcess (pid )
1108
+ err = process .Kill ()
1109
+ require .NoError (t , err )
1110
+ },
1111
+ },
1112
+ {
1113
+ name : "Context Cancel" ,
1114
+ stop : func (m * Machine , cancel context.CancelFunc ) {
1115
+ cancel ()
1116
+ },
1117
+ },
1118
+ {
1119
+ name : "StopVMM + Context Cancel" ,
1120
+ stop : func (m * Machine , cancel context.CancelFunc ) {
1121
+ m .StopVMM ()
1122
+ time .Sleep (1 * time .Second )
1123
+ cancel ()
1124
+ },
1125
+ },
1126
+ }
1090
1127
1091
- cfg := createValidConfig (t , socketPath )
1092
- cmd := VMCommandBuilder {}.
1093
- WithSocketPath (cfg .SocketPath ).
1094
- WithBin (getFirecrackerBinaryPath ()).
1095
- Build (ctx )
1096
- m , err := NewMachine (ctx , cfg , WithProcessRunner (cmd ))
1097
- require .NoError (t , err )
1128
+ for _ , c := range cases {
1129
+ t .Run (c .name , func (t * testing.T ) {
1130
+ ctx := context .Background ()
1131
+ vmContext , vmCancel := context .WithCancel (context .Background ())
1098
1132
1099
- err = m . Start ( ctx )
1100
- require . NoError ( t , err )
1133
+ socketPath := filepath . Join ( testDataPath , fsSafeTestName . Replace ( t . Name ()) )
1134
+ defer os . Remove ( socketPath )
1101
1135
1102
- go func () {
1103
- pid , err := m .PID ()
1104
- require .NoError (t , err )
1136
+ cfg := createValidConfig (t , socketPath )
1137
+ m , err := NewMachine (ctx , cfg , func (m * Machine ) {
1138
+ // Rewriting m.cmd partially wouldn't work since Cmd has
1139
+ // some unexported members
1140
+ args := m .cmd .Args [1 :]
1141
+ m .cmd = exec .Command (getFirecrackerBinaryPath (), args ... )
1142
+ })
1143
+ require .NoError (t , err )
1105
1144
1106
- process , err := os . FindProcess ( pid )
1107
- require .NoError (t , err )
1145
+ err = m . Start ( vmContext )
1146
+ require .NoError (t , err )
1108
1147
1109
- err = process .Kill ()
1110
- require .NoError (t , err )
1111
- }()
1148
+ pid , err := m .PID ()
1149
+ require .NoError (t , err )
1112
1150
1113
- err = m .Wait (ctx )
1114
- require .Error (t , err , "Firecracker was killed and it must be reported" )
1151
+ var wg sync.WaitGroup
1152
+ wg .Add (1 )
1153
+ go func () {
1154
+ defer wg .Done ()
1155
+ c .stop (m , vmCancel )
1156
+ }()
1157
+
1158
+ err = m .Wait (ctx )
1159
+ require .Error (t , err , "Firecracker was killed and it must be reported" )
1160
+ t .Logf ("err = %v" , err )
1161
+
1162
+ proc , err := os .FindProcess (pid )
1163
+ // Having an error here doesn't mean the process is not there.
1164
+ // In fact it won't be non-nil on Unix systems
1165
+ require .NoError (t , err )
1166
+
1167
+ err = proc .Signal (syscall .Signal (0 ))
1168
+ require .Equal (t , "os: process already finished" , err .Error ())
1169
+
1170
+ wg .Wait ()
1171
+ })
1172
+ }
1115
1173
}
1116
1174
1117
1175
func TestWaitWithInvalidBinary (t * testing.T ) {
0 commit comments