@@ -23,6 +23,7 @@ import (
2323 "io"
2424 "os"
2525 "path"
26+ "path/filepath"
2627 "runtime"
2728 "strings"
2829 "syscall"
@@ -42,6 +43,7 @@ import (
4243 "github.com/containerd/containerd/plugin"
4344 _ "github.com/containerd/containerd/runtime"
4445 "github.com/containerd/containerd/runtime/v2/runc/options"
46+ "github.com/containerd/continuity/fs"
4547 "github.com/containerd/go-runc"
4648 "github.com/containerd/typeurl"
4749 gogotypes "github.com/gogo/protobuf/types"
@@ -173,6 +175,130 @@ func TestContainerStart(t *testing.T) {
173175 }
174176}
175177
178+ func readShimPath (taskID string ) (string , error ) {
179+ runtime := fmt .Sprintf ("%s.%s" , plugin .RuntimePluginV2 , "task" )
180+ shimBinaryNamePath := filepath .Join (defaultState , runtime , testNamespace , taskID , "shim-binary-path" )
181+
182+ shimPath , err := os .ReadFile (shimBinaryNamePath )
183+ if err != nil {
184+ return "" , err
185+ }
186+ return string (shimPath ), nil
187+ }
188+
189+ func copyShim (shimPath string ) (string , error ) {
190+ tempPath := filepath .Join (os .TempDir (), filepath .Base (shimPath ))
191+ if err := fs .CopyFile (tempPath , shimPath ); err != nil {
192+ return "" , err
193+ }
194+
195+ fi , err := os .Stat (shimPath )
196+ if err != nil {
197+ return "" , err
198+ }
199+ if err := os .Chmod (tempPath , fi .Mode ().Perm ()); err != nil {
200+ return "" , err
201+ }
202+
203+ return tempPath , nil
204+ }
205+
206+ func TestContainerStartWithAbsRuntimePath (t * testing.T ) {
207+ t .Parallel ()
208+
209+ client , err := newClient (t , address )
210+ if err != nil {
211+ t .Fatal (err )
212+ }
213+ defer client .Close ()
214+
215+ var (
216+ image Image
217+ ctx , cancel = testContext (t )
218+ id = t .Name ()
219+ )
220+ defer cancel ()
221+
222+ image , err = client .GetImage (ctx , testImage )
223+ if err != nil {
224+ t .Fatal (err )
225+ }
226+ container , err := client .NewContainer (ctx , id , WithNewSnapshot (id , image ), WithNewSpec (oci .WithImageConfig (image ), withExitStatus (7 )))
227+ if err != nil {
228+ t .Fatal (err )
229+ }
230+ defer container .Delete (ctx , WithSnapshotCleanup )
231+
232+ // create a temp task to read the default shim path
233+ task , err := container .NewTask (ctx , empty ())
234+ if err != nil {
235+ t .Fatal (err )
236+ }
237+
238+ defaultShimPath , err := readShimPath (task .ID ())
239+ if err != nil {
240+ t .Fatal (err )
241+ }
242+
243+ // remove the temp task
244+ if _ , err := task .Delete (ctx , WithProcessKill ); err != nil {
245+ t .Fatal (err )
246+ }
247+
248+ tempShimPath , err := copyShim (defaultShimPath )
249+ if err != nil {
250+ t .Fatal (err )
251+ }
252+ defer os .Remove (tempShimPath )
253+
254+ task , err = container .NewTask (ctx , empty (), WithRuntimePath (tempShimPath ))
255+ if err != nil {
256+ t .Fatal (err )
257+ }
258+
259+ shimPath , err := readShimPath (task .ID ())
260+ if err != nil {
261+ t .Fatal (err )
262+ }
263+ if shimPath != tempShimPath {
264+ t .Fatalf ("The task's shim path is %s, does not used the specified runtime path: %s" , shimPath , tempShimPath )
265+ }
266+
267+ statusC , err := task .Wait (ctx )
268+ if err != nil {
269+ t .Fatal (err )
270+ }
271+
272+ if runtime .GOOS != "windows" {
273+ // task.Pid not implemented on Windows
274+ if pid := task .Pid (); pid < 1 {
275+ t .Errorf ("invalid task pid %d" , pid )
276+ }
277+ }
278+
279+ if err := task .Start (ctx ); err != nil {
280+ t .Error (err )
281+ task .Delete (ctx )
282+ return
283+ }
284+ status := <- statusC
285+ code , _ , err := status .Result ()
286+ if err != nil {
287+ t .Fatal (err )
288+ }
289+ if code != 7 {
290+ t .Errorf ("expected status 7 from wait but received %d" , code )
291+ }
292+
293+ deleteStatus , err := task .Delete (ctx )
294+ if err != nil {
295+ t .Fatal (err )
296+ }
297+ if ec := deleteStatus .ExitCode (); ec != 7 {
298+ t .Errorf ("expected status 7 from delete but received %d" , ec )
299+ }
300+ }
301+
176302func TestContainerOutput (t * testing.T ) {
177303 t .Parallel ()
178304
0 commit comments