github.com/demonoid81/containerd@v1.3.4/container_test.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package containerd
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"io"
    23  	"io/ioutil"
    24  	"os"
    25  	"os/exec"
    26  	"runtime"
    27  	"strings"
    28  	"syscall"
    29  	"testing"
    30  	"time"
    31  
    32  	// Register the typeurl
    33  	"github.com/containerd/containerd/cio"
    34  	"github.com/containerd/containerd/containers"
    35  	"github.com/containerd/containerd/namespaces"
    36  	"github.com/containerd/containerd/oci"
    37  	"github.com/containerd/containerd/platforms"
    38  	_ "github.com/containerd/containerd/runtime"
    39  	"github.com/containerd/typeurl"
    40  	specs "github.com/opencontainers/runtime-spec/specs-go"
    41  
    42  	"github.com/containerd/containerd/errdefs"
    43  	gogotypes "github.com/gogo/protobuf/types"
    44  )
    45  
    46  func empty() cio.Creator {
    47  	// TODO (@mlaventure) windows searches for pipes
    48  	// when none are provided
    49  	if runtime.GOOS == "windows" {
    50  		return cio.NewCreator(cio.WithStdio)
    51  	}
    52  	return cio.NullIO
    53  }
    54  
    55  func TestContainerList(t *testing.T) {
    56  	client, err := newClient(t, address)
    57  	if err != nil {
    58  		t.Fatal(err)
    59  	}
    60  	defer client.Close()
    61  
    62  	ctx, cancel := testContext(t)
    63  	defer cancel()
    64  
    65  	containers, err := client.Containers(ctx)
    66  	if err != nil {
    67  		t.Fatalf("container list returned error %v", err)
    68  	}
    69  	if len(containers) != 0 {
    70  		t.Errorf("expected 0 containers but received %d", len(containers))
    71  	}
    72  }
    73  
    74  func TestNewContainer(t *testing.T) {
    75  	t.Parallel()
    76  
    77  	id := t.Name()
    78  	client, err := newClient(t, address)
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	defer client.Close()
    83  
    84  	ctx, cancel := testContext(t)
    85  	defer cancel()
    86  
    87  	container, err := client.NewContainer(ctx, id, WithNewSpec())
    88  	if err != nil {
    89  		t.Fatal(err)
    90  	}
    91  	defer container.Delete(ctx)
    92  	if container.ID() != id {
    93  		t.Errorf("expected container id %q but received %q", id, container.ID())
    94  	}
    95  	if _, err = container.Spec(ctx); err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	if err := container.Delete(ctx); err != nil {
    99  		t.Fatal(err)
   100  	}
   101  }
   102  
   103  func TestContainerStart(t *testing.T) {
   104  	t.Parallel()
   105  
   106  	client, err := newClient(t, address)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	defer client.Close()
   111  
   112  	var (
   113  		image       Image
   114  		ctx, cancel = testContext(t)
   115  		id          = t.Name()
   116  	)
   117  	defer cancel()
   118  
   119  	image, err = client.GetImage(ctx, testImage)
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)))
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	defer container.Delete(ctx, WithSnapshotCleanup)
   128  
   129  	task, err := container.NewTask(ctx, empty())
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	defer task.Delete(ctx)
   134  
   135  	statusC, err := task.Wait(ctx)
   136  	if err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	if pid := task.Pid(); pid < 1 {
   141  		t.Errorf("invalid task pid %d", pid)
   142  	}
   143  	if err := task.Start(ctx); err != nil {
   144  		t.Error(err)
   145  		task.Delete(ctx)
   146  		return
   147  	}
   148  	status := <-statusC
   149  	code, _, err := status.Result()
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  	if code != 7 {
   154  		t.Errorf("expected status 7 from wait but received %d", code)
   155  	}
   156  
   157  	deleteStatus, err := task.Delete(ctx)
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	if ec := deleteStatus.ExitCode(); ec != 7 {
   162  		t.Errorf("expected status 7 from delete but received %d", ec)
   163  	}
   164  }
   165  
   166  func TestContainerOutput(t *testing.T) {
   167  	t.Parallel()
   168  
   169  	client, err := newClient(t, address)
   170  	if err != nil {
   171  		t.Fatal(err)
   172  	}
   173  	defer client.Close()
   174  
   175  	var (
   176  		image       Image
   177  		ctx, cancel = testContext(t)
   178  		id          = t.Name()
   179  		expected    = "kingkoye"
   180  	)
   181  	defer cancel()
   182  
   183  	image, err = client.GetImage(ctx, testImage)
   184  	if err != nil {
   185  		t.Fatal(err)
   186  	}
   187  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("echo", expected)))
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  	defer container.Delete(ctx, WithSnapshotCleanup)
   192  
   193  	stdout := bytes.NewBuffer(nil)
   194  	task, err := container.NewTask(ctx, cio.NewCreator(withByteBuffers(stdout)))
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  	defer task.Delete(ctx)
   199  
   200  	statusC, err := task.Wait(ctx)
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  
   205  	if err := task.Start(ctx); err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	status := <-statusC
   210  	code, _, err := status.Result()
   211  	if code != 0 {
   212  		t.Errorf("expected status 0 but received %d: %v", code, err)
   213  	}
   214  	if _, err := task.Delete(ctx); err != nil {
   215  		t.Fatal(err)
   216  	}
   217  
   218  	actual := stdout.String()
   219  	// echo adds a new line
   220  	expected = expected + newLine
   221  	if actual != expected {
   222  		t.Errorf("expected output %q but received %q", expected, actual)
   223  	}
   224  }
   225  
   226  func withByteBuffers(stdout io.Writer) cio.Opt {
   227  	// TODO: could this use ioutil.Discard?
   228  	return func(streams *cio.Streams) {
   229  		streams.Stdin = new(bytes.Buffer)
   230  		streams.Stdout = stdout
   231  		streams.Stderr = new(bytes.Buffer)
   232  	}
   233  }
   234  
   235  func TestContainerExec(t *testing.T) {
   236  	t.Parallel()
   237  
   238  	client, err := newClient(t, address)
   239  	if err != nil {
   240  		t.Fatal(err)
   241  	}
   242  	defer client.Close()
   243  
   244  	var (
   245  		image       Image
   246  		ctx, cancel = testContext(t)
   247  		id          = t.Name()
   248  	)
   249  	defer cancel()
   250  
   251  	image, err = client.GetImage(ctx, testImage)
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  
   256  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  	defer container.Delete(ctx, WithSnapshotCleanup)
   261  
   262  	task, err := container.NewTask(ctx, empty())
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  	defer task.Delete(ctx)
   267  
   268  	finishedC, err := task.Wait(ctx)
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  
   273  	if err := task.Start(ctx); err != nil {
   274  		t.Fatal(err)
   275  	}
   276  	spec, err := container.Spec(ctx)
   277  	if err != nil {
   278  		t.Fatal(err)
   279  	}
   280  
   281  	// start an exec process without running the original container process info
   282  	processSpec := spec.Process
   283  	withExecExitStatus(processSpec, 6)
   284  	execID := t.Name() + "_exec"
   285  	process, err := task.Exec(ctx, execID, processSpec, empty())
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  	processStatusC, err := process.Wait(ctx)
   290  	if err != nil {
   291  		t.Fatal(err)
   292  	}
   293  
   294  	if err := process.Start(ctx); err != nil {
   295  		t.Fatal(err)
   296  	}
   297  
   298  	// wait for the exec to return
   299  	status := <-processStatusC
   300  	code, _, err := status.Result()
   301  	if err != nil {
   302  		t.Fatal(err)
   303  	}
   304  
   305  	if code != 6 {
   306  		t.Errorf("expected exec exit code 6 but received %d", code)
   307  	}
   308  	deleteStatus, err := process.Delete(ctx)
   309  	if err != nil {
   310  		t.Fatal(err)
   311  	}
   312  	if ec := deleteStatus.ExitCode(); ec != 6 {
   313  		t.Errorf("expected delete exit code 6 but received %d", ec)
   314  	}
   315  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   316  		t.Error(err)
   317  	}
   318  	<-finishedC
   319  }
   320  func TestContainerLargeExecArgs(t *testing.T) {
   321  	t.Parallel()
   322  
   323  	client, err := newClient(t, address)
   324  	if err != nil {
   325  		t.Fatal(err)
   326  	}
   327  	defer client.Close()
   328  
   329  	var (
   330  		image       Image
   331  		ctx, cancel = testContext(t)
   332  		id          = t.Name()
   333  	)
   334  	defer cancel()
   335  
   336  	image, err = client.GetImage(ctx, testImage)
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  
   341  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   342  	if err != nil {
   343  		t.Fatal(err)
   344  	}
   345  	defer container.Delete(ctx, WithSnapshotCleanup)
   346  
   347  	task, err := container.NewTask(ctx, empty())
   348  	if err != nil {
   349  		t.Fatal(err)
   350  	}
   351  	defer task.Delete(ctx)
   352  
   353  	finishedC, err := task.Wait(ctx)
   354  	if err != nil {
   355  		t.Fatal(err)
   356  	}
   357  
   358  	if err := task.Start(ctx); err != nil {
   359  		t.Fatal(err)
   360  	}
   361  	spec, err := container.Spec(ctx)
   362  	if err != nil {
   363  		t.Fatal(err)
   364  	}
   365  
   366  	processSpec := spec.Process
   367  	withExecArgs(processSpec, "echo", strings.Repeat("a", 20000))
   368  	execID := t.Name() + "_exec"
   369  	process, err := task.Exec(ctx, execID, processSpec, empty())
   370  	if err != nil {
   371  		t.Fatal(err)
   372  	}
   373  	processStatusC, err := process.Wait(ctx)
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	if err := process.Start(ctx); err != nil {
   379  		t.Fatal(err)
   380  	}
   381  
   382  	// wait for the exec to return
   383  	status := <-processStatusC
   384  	if _, _, err := status.Result(); err != nil {
   385  		t.Fatal(err)
   386  	}
   387  	if _, err := process.Delete(ctx); err != nil {
   388  		t.Fatal(err)
   389  	}
   390  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   391  		t.Error(err)
   392  	}
   393  	<-finishedC
   394  }
   395  
   396  func TestContainerPids(t *testing.T) {
   397  	t.Parallel()
   398  
   399  	client, err := newClient(t, address)
   400  	if err != nil {
   401  		t.Fatal(err)
   402  	}
   403  	defer client.Close()
   404  
   405  	var (
   406  		image       Image
   407  		ctx, cancel = testContext(t)
   408  		id          = t.Name()
   409  	)
   410  	defer cancel()
   411  
   412  	image, err = client.GetImage(ctx, testImage)
   413  	if err != nil {
   414  		t.Fatal(err)
   415  	}
   416  
   417  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   418  	if err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	defer container.Delete(ctx, WithSnapshotCleanup)
   422  
   423  	task, err := container.NewTask(ctx, empty())
   424  	if err != nil {
   425  		t.Fatal(err)
   426  	}
   427  	defer task.Delete(ctx)
   428  
   429  	statusC, err := task.Wait(ctx)
   430  	if err != nil {
   431  		t.Fatal(err)
   432  	}
   433  
   434  	if err := task.Start(ctx); err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	pid := task.Pid()
   439  	if pid < 1 {
   440  		t.Errorf("invalid task pid %d", pid)
   441  	}
   442  	processes, err := task.Pids(ctx)
   443  	switch runtime.GOOS {
   444  	case "windows":
   445  		// TODO: This is currently not implemented on windows
   446  	default:
   447  		if err != nil {
   448  			t.Fatal(err)
   449  		}
   450  		if l := len(processes); l != 1 {
   451  			t.Errorf("expected 1 process but received %d", l)
   452  		}
   453  		if len(processes) > 0 {
   454  			actual := processes[0].Pid
   455  			if pid != actual {
   456  				t.Errorf("expected pid %d but received %d", pid, actual)
   457  			}
   458  		}
   459  	}
   460  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   461  		t.Error(err)
   462  	}
   463  	<-statusC
   464  }
   465  
   466  func TestContainerCloseIO(t *testing.T) {
   467  	t.Parallel()
   468  
   469  	client, err := newClient(t, address)
   470  	if err != nil {
   471  		t.Fatal(err)
   472  	}
   473  	defer client.Close()
   474  
   475  	var (
   476  		image       Image
   477  		ctx, cancel = testContext(t)
   478  		id          = t.Name()
   479  	)
   480  	defer cancel()
   481  
   482  	image, err = client.GetImage(ctx, testImage)
   483  	if err != nil {
   484  		t.Fatal(err)
   485  	}
   486  
   487  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withCat()))
   488  	if err != nil {
   489  		t.Fatal(err)
   490  	}
   491  	defer container.Delete(ctx, WithSnapshotCleanup)
   492  
   493  	stdout := bytes.NewBuffer(nil)
   494  
   495  	r, w, err := os.Pipe()
   496  	if err != nil {
   497  		t.Fatal(err)
   498  	}
   499  
   500  	task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStreams(r, stdout, ioutil.Discard)))
   501  	if err != nil {
   502  		t.Fatal(err)
   503  	}
   504  	defer task.Delete(ctx)
   505  
   506  	statusC, err := task.Wait(ctx)
   507  	if err != nil {
   508  		t.Fatal(err)
   509  	}
   510  
   511  	if err := task.Start(ctx); err != nil {
   512  		t.Fatal(err)
   513  	}
   514  	w.Close()
   515  	if err := task.CloseIO(ctx, WithStdinCloser); err != nil {
   516  		t.Error(err)
   517  	}
   518  
   519  	<-statusC
   520  }
   521  
   522  func TestDeleteRunningContainer(t *testing.T) {
   523  	t.Parallel()
   524  
   525  	client, err := newClient(t, address)
   526  	if err != nil {
   527  		t.Fatal(err)
   528  	}
   529  	defer client.Close()
   530  
   531  	var (
   532  		image       Image
   533  		ctx, cancel = testContext(t)
   534  		id          = t.Name()
   535  	)
   536  	defer cancel()
   537  
   538  	image, err = client.GetImage(ctx, testImage)
   539  	if err != nil {
   540  		t.Fatal(err)
   541  	}
   542  
   543  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   544  	if err != nil {
   545  		t.Fatal(err)
   546  	}
   547  	defer container.Delete(ctx, WithSnapshotCleanup)
   548  
   549  	task, err := container.NewTask(ctx, empty())
   550  	if err != nil {
   551  		t.Fatal(err)
   552  	}
   553  	defer task.Delete(ctx)
   554  
   555  	statusC, err := task.Wait(ctx)
   556  	if err != nil {
   557  		t.Fatal(err)
   558  	}
   559  
   560  	if err := task.Start(ctx); err != nil {
   561  		t.Fatal(err)
   562  	}
   563  
   564  	err = container.Delete(ctx, WithSnapshotCleanup)
   565  	if err == nil {
   566  		t.Error("delete did not error with running task")
   567  	}
   568  	if !errdefs.IsFailedPrecondition(err) {
   569  		t.Errorf("expected error %q but received %q", errdefs.ErrFailedPrecondition, err)
   570  	}
   571  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   572  		t.Fatal(err)
   573  	}
   574  	<-statusC
   575  }
   576  
   577  func TestContainerKill(t *testing.T) {
   578  	t.Parallel()
   579  
   580  	client, err := newClient(t, address)
   581  	if err != nil {
   582  		t.Fatal(err)
   583  	}
   584  	defer client.Close()
   585  
   586  	var (
   587  		image       Image
   588  		ctx, cancel = testContext(t)
   589  		id          = t.Name()
   590  	)
   591  	defer cancel()
   592  
   593  	image, err = client.GetImage(ctx, testImage)
   594  	if err != nil {
   595  		t.Fatal(err)
   596  	}
   597  
   598  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "10")))
   599  	if err != nil {
   600  		t.Fatal(err)
   601  	}
   602  	defer container.Delete(ctx)
   603  
   604  	task, err := container.NewTask(ctx, empty())
   605  	if err != nil {
   606  		t.Fatal(err)
   607  	}
   608  	defer task.Delete(ctx)
   609  
   610  	statusC, err := task.Wait(ctx)
   611  	if err != nil {
   612  		t.Fatal(err)
   613  	}
   614  
   615  	if err := task.Start(ctx); err != nil {
   616  		t.Fatal(err)
   617  	}
   618  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   619  		t.Fatal(err)
   620  	}
   621  	<-statusC
   622  
   623  	err = task.Kill(ctx, syscall.SIGTERM)
   624  	if err == nil {
   625  		t.Fatal("second call to kill should return an error")
   626  	}
   627  	if !errdefs.IsNotFound(err) {
   628  		t.Errorf("expected error %q but received %q", errdefs.ErrNotFound, err)
   629  	}
   630  }
   631  
   632  func TestContainerNoBinaryExists(t *testing.T) {
   633  	t.Parallel()
   634  
   635  	client, err := newClient(t, address)
   636  	if err != nil {
   637  		t.Fatal(err)
   638  	}
   639  	defer client.Close()
   640  
   641  	var (
   642  		image       Image
   643  		ctx, cancel = testContext(t)
   644  		id          = t.Name()
   645  	)
   646  	defer cancel()
   647  
   648  	image, err = client.GetImage(ctx, testImage)
   649  	if err != nil {
   650  		t.Fatal(err)
   651  	}
   652  
   653  	container, err := client.NewContainer(ctx, id,
   654  		WithNewSnapshot(id, image),
   655  		WithNewSpec(oci.WithImageConfig(image), oci.WithProcessArgs("nothing")))
   656  	if err != nil {
   657  		t.Fatal(err)
   658  	}
   659  	defer container.Delete(ctx, WithSnapshotCleanup)
   660  
   661  	task, err := container.NewTask(ctx, empty())
   662  	switch runtime.GOOS {
   663  	case "windows":
   664  		if err != nil {
   665  			t.Fatalf("failed to create task %v", err)
   666  		}
   667  		defer task.Delete(ctx, WithProcessKill)
   668  		if err := task.Start(ctx); err == nil {
   669  			t.Error("task.Start() should return an error when binary does not exist")
   670  		}
   671  	default:
   672  		if err == nil {
   673  			t.Error("NewTask should return an error when binary does not exist")
   674  			task.Delete(ctx)
   675  		}
   676  	}
   677  }
   678  
   679  func TestContainerExecNoBinaryExists(t *testing.T) {
   680  	t.Parallel()
   681  
   682  	client, err := newClient(t, address)
   683  	if err != nil {
   684  		t.Fatal(err)
   685  	}
   686  	defer client.Close()
   687  
   688  	var (
   689  		image       Image
   690  		ctx, cancel = testContext(t)
   691  		id          = t.Name()
   692  	)
   693  	defer cancel()
   694  
   695  	image, err = client.GetImage(ctx, testImage)
   696  	if err != nil {
   697  		t.Fatal(err)
   698  	}
   699  
   700  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   701  	if err != nil {
   702  		t.Fatal(err)
   703  	}
   704  	defer container.Delete(ctx, WithSnapshotCleanup)
   705  
   706  	task, err := container.NewTask(ctx, empty())
   707  	if err != nil {
   708  		t.Fatal(err)
   709  	}
   710  	defer task.Delete(ctx)
   711  
   712  	finishedC, err := task.Wait(ctx)
   713  	if err != nil {
   714  		t.Error(err)
   715  	}
   716  	if err := task.Start(ctx); err != nil {
   717  		t.Fatal(err)
   718  	}
   719  	spec, err := container.Spec(ctx)
   720  	if err != nil {
   721  		t.Fatal(err)
   722  	}
   723  
   724  	// start an exec process without running the original container process
   725  	processSpec := spec.Process
   726  	processSpec.Args = []string{
   727  		"none",
   728  	}
   729  	execID := t.Name() + "_exec"
   730  	process, err := task.Exec(ctx, execID, processSpec, empty())
   731  	if err != nil {
   732  		t.Fatal(err)
   733  	}
   734  	defer process.Delete(ctx)
   735  	if err := process.Start(ctx); err == nil {
   736  		t.Error("Process.Start should fail when process does not exist")
   737  	}
   738  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   739  		t.Error(err)
   740  	}
   741  	<-finishedC
   742  }
   743  
   744  func TestWaitStoppedTask(t *testing.T) {
   745  	t.Parallel()
   746  
   747  	client, err := newClient(t, address)
   748  	if err != nil {
   749  		t.Fatal(err)
   750  	}
   751  	defer client.Close()
   752  
   753  	var (
   754  		image       Image
   755  		ctx, cancel = testContext(t)
   756  		id          = t.Name()
   757  	)
   758  	defer cancel()
   759  
   760  	image, err = client.GetImage(ctx, testImage)
   761  	if err != nil {
   762  		t.Fatal(err)
   763  	}
   764  
   765  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)))
   766  	if err != nil {
   767  		t.Fatal(err)
   768  	}
   769  	defer container.Delete(ctx, WithSnapshotCleanup)
   770  
   771  	task, err := container.NewTask(ctx, empty())
   772  	if err != nil {
   773  		t.Fatal(err)
   774  	}
   775  	defer task.Delete(ctx)
   776  
   777  	statusC, err := task.Wait(ctx)
   778  	if err != nil {
   779  		t.Fatal(err)
   780  	}
   781  
   782  	if pid := task.Pid(); pid < 1 {
   783  		t.Errorf("invalid task pid %d", pid)
   784  	}
   785  	if err := task.Start(ctx); err != nil {
   786  		t.Error(err)
   787  		task.Delete(ctx)
   788  		return
   789  	}
   790  
   791  	// wait for the task to stop then call wait again
   792  	<-statusC
   793  	statusC, err = task.Wait(ctx)
   794  	if err != nil {
   795  		t.Fatal(err)
   796  	}
   797  	status := <-statusC
   798  	code, _, err := status.Result()
   799  	if err != nil {
   800  		t.Fatal(err)
   801  	}
   802  	if code != 7 {
   803  		t.Errorf("exit status from stopped task should be 7 but received %d", code)
   804  	}
   805  }
   806  
   807  func TestWaitStoppedProcess(t *testing.T) {
   808  	t.Parallel()
   809  
   810  	client, err := newClient(t, address)
   811  	if err != nil {
   812  		t.Fatal(err)
   813  	}
   814  	defer client.Close()
   815  
   816  	var (
   817  		image       Image
   818  		ctx, cancel = testContext(t)
   819  		id          = t.Name()
   820  	)
   821  	defer cancel()
   822  
   823  	image, err = client.GetImage(ctx, testImage)
   824  	if err != nil {
   825  		t.Fatal(err)
   826  	}
   827  
   828  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   829  	if err != nil {
   830  		t.Fatal(err)
   831  	}
   832  	defer container.Delete(ctx, WithSnapshotCleanup)
   833  
   834  	task, err := container.NewTask(ctx, empty())
   835  	if err != nil {
   836  		t.Fatal(err)
   837  	}
   838  	defer task.Delete(ctx)
   839  
   840  	finishedC, err := task.Wait(ctx)
   841  	if err != nil {
   842  		t.Error(err)
   843  	}
   844  
   845  	if err := task.Start(ctx); err != nil {
   846  		t.Fatal(err)
   847  	}
   848  	spec, err := container.Spec(ctx)
   849  	if err != nil {
   850  		t.Fatal(err)
   851  	}
   852  
   853  	// start an exec process without running the original container process info
   854  	processSpec := spec.Process
   855  	withExecExitStatus(processSpec, 6)
   856  	execID := t.Name() + "_exec"
   857  	process, err := task.Exec(ctx, execID, processSpec, empty())
   858  	if err != nil {
   859  		t.Fatal(err)
   860  	}
   861  	defer process.Delete(ctx)
   862  
   863  	statusC, err := process.Wait(ctx)
   864  	if err != nil {
   865  		t.Fatal(err)
   866  	}
   867  
   868  	if err := process.Start(ctx); err != nil {
   869  		t.Fatal(err)
   870  	}
   871  
   872  	// wait for the exec to return
   873  	<-statusC
   874  
   875  	// try to wait on the process after it has stopped
   876  	statusC, err = process.Wait(ctx)
   877  	if err != nil {
   878  		t.Fatal(err)
   879  	}
   880  	status := <-statusC
   881  	code, _, err := status.Result()
   882  	if err != nil {
   883  		t.Fatal(err)
   884  	}
   885  	if code != 6 {
   886  		t.Errorf("exit status from stopped process should be 6 but received %d", code)
   887  	}
   888  
   889  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   890  		t.Error(err)
   891  	}
   892  	<-finishedC
   893  }
   894  
   895  func TestTaskForceDelete(t *testing.T) {
   896  	t.Parallel()
   897  
   898  	client, err := newClient(t, address)
   899  	if err != nil {
   900  		t.Fatal(err)
   901  	}
   902  	defer client.Close()
   903  
   904  	var (
   905  		image       Image
   906  		ctx, cancel = testContext(t)
   907  		id          = t.Name()
   908  	)
   909  	defer cancel()
   910  
   911  	image, err = client.GetImage(ctx, testImage)
   912  	if err != nil {
   913  		t.Fatal(err)
   914  	}
   915  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
   916  	if err != nil {
   917  		t.Fatal(err)
   918  	}
   919  	defer container.Delete(ctx, WithSnapshotCleanup)
   920  
   921  	task, err := container.NewTask(ctx, empty())
   922  	if err != nil {
   923  		t.Fatal(err)
   924  	}
   925  	if err := task.Start(ctx); err != nil {
   926  		t.Fatal(err)
   927  	}
   928  	if _, err := task.Delete(ctx); err == nil {
   929  		t.Error("task.Delete of a running task should create an error")
   930  	}
   931  	if _, err := task.Delete(ctx, WithProcessKill); err != nil {
   932  		t.Fatal(err)
   933  	}
   934  }
   935  
   936  func TestProcessForceDelete(t *testing.T) {
   937  	t.Parallel()
   938  
   939  	client, err := newClient(t, address)
   940  	if err != nil {
   941  		t.Fatal(err)
   942  	}
   943  	defer client.Close()
   944  
   945  	var (
   946  		image       Image
   947  		ctx, cancel = testContext(t)
   948  		id          = t.Name()
   949  	)
   950  	defer cancel()
   951  
   952  	image, err = client.GetImage(ctx, testImage)
   953  	if err != nil {
   954  		t.Fatal(err)
   955  	}
   956  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
   957  	if err != nil {
   958  		t.Fatal(err)
   959  	}
   960  	defer container.Delete(ctx, WithSnapshotCleanup)
   961  
   962  	task, err := container.NewTask(ctx, empty())
   963  	if err != nil {
   964  		t.Fatal(err)
   965  	}
   966  	defer task.Delete(ctx)
   967  
   968  	statusC, err := task.Wait(ctx)
   969  	if err != nil {
   970  		t.Fatal(err)
   971  	}
   972  
   973  	// task must be started on windows
   974  	if err := task.Start(ctx); err != nil {
   975  		t.Fatal(err)
   976  	}
   977  	spec, err := container.Spec(ctx)
   978  	if err != nil {
   979  		t.Fatal(err)
   980  	}
   981  
   982  	processSpec := spec.Process
   983  	withExecArgs(processSpec, "sleep", "20")
   984  	execID := t.Name() + "_exec"
   985  	process, err := task.Exec(ctx, execID, processSpec, empty())
   986  	if err != nil {
   987  		t.Fatal(err)
   988  	}
   989  	if err := process.Start(ctx); err != nil {
   990  		t.Fatal(err)
   991  	}
   992  	if _, err := process.Delete(ctx); err == nil {
   993  		t.Error("process.Delete should return an error when process is running")
   994  	}
   995  	if _, err := process.Delete(ctx, WithProcessKill); err != nil {
   996  		t.Error(err)
   997  	}
   998  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   999  		t.Fatal(err)
  1000  	}
  1001  	<-statusC
  1002  }
  1003  
  1004  func TestContainerHostname(t *testing.T) {
  1005  	t.Parallel()
  1006  
  1007  	client, err := newClient(t, address)
  1008  	if err != nil {
  1009  		t.Fatal(err)
  1010  	}
  1011  	defer client.Close()
  1012  
  1013  	var (
  1014  		image       Image
  1015  		ctx, cancel = testContext(t)
  1016  		id          = t.Name()
  1017  		expected    = "myhostname"
  1018  	)
  1019  	defer cancel()
  1020  
  1021  	image, err = client.GetImage(ctx, testImage)
  1022  	if err != nil {
  1023  		t.Fatal(err)
  1024  	}
  1025  
  1026  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image),
  1027  		withProcessArgs("hostname"),
  1028  		oci.WithHostname(expected),
  1029  	))
  1030  	if err != nil {
  1031  		t.Fatal(err)
  1032  	}
  1033  	defer container.Delete(ctx, WithSnapshotCleanup)
  1034  
  1035  	stdout := bytes.NewBuffer(nil)
  1036  	task, err := container.NewTask(ctx, cio.NewCreator(withByteBuffers(stdout)))
  1037  	if err != nil {
  1038  		t.Fatal(err)
  1039  	}
  1040  	defer task.Delete(ctx)
  1041  
  1042  	statusC, err := task.Wait(ctx)
  1043  	if err != nil {
  1044  		t.Fatal(err)
  1045  	}
  1046  
  1047  	if err := task.Start(ctx); err != nil {
  1048  		t.Fatal(err)
  1049  	}
  1050  
  1051  	status := <-statusC
  1052  	code, _, err := status.Result()
  1053  	if err != nil {
  1054  		t.Fatal(err)
  1055  	}
  1056  	if code != 0 {
  1057  		t.Errorf("expected status 0 but received %d", code)
  1058  	}
  1059  	if _, err := task.Delete(ctx); err != nil {
  1060  		t.Fatal(err)
  1061  	}
  1062  	cutset := "\n"
  1063  	if runtime.GOOS == "windows" {
  1064  		cutset = "\r\n"
  1065  	}
  1066  
  1067  	actual := strings.TrimSuffix(stdout.String(), cutset)
  1068  	if actual != expected {
  1069  		t.Errorf("expected output %q but received %q", expected, actual)
  1070  	}
  1071  }
  1072  
  1073  func TestContainerExitedAtSet(t *testing.T) {
  1074  	t.Parallel()
  1075  
  1076  	client, err := newClient(t, address)
  1077  	if err != nil {
  1078  		t.Fatal(err)
  1079  	}
  1080  	defer client.Close()
  1081  
  1082  	var (
  1083  		image       Image
  1084  		ctx, cancel = testContext(t)
  1085  		id          = t.Name()
  1086  	)
  1087  	defer cancel()
  1088  
  1089  	image, err = client.GetImage(ctx, testImage)
  1090  	if err != nil {
  1091  		t.Fatal(err)
  1092  	}
  1093  
  1094  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withTrue()))
  1095  	if err != nil {
  1096  		t.Fatal(err)
  1097  	}
  1098  	defer container.Delete(ctx, WithSnapshotCleanup)
  1099  
  1100  	task, err := container.NewTask(ctx, empty())
  1101  	if err != nil {
  1102  		t.Fatal(err)
  1103  	}
  1104  	defer task.Delete(ctx)
  1105  
  1106  	statusC, err := task.Wait(ctx)
  1107  	if err != nil {
  1108  		t.Error(err)
  1109  	}
  1110  
  1111  	startTime := time.Now()
  1112  	if err := task.Start(ctx); err != nil {
  1113  		t.Fatal(err)
  1114  	}
  1115  
  1116  	status := <-statusC
  1117  	code, _, err := status.Result()
  1118  	if code != 0 {
  1119  		t.Errorf("expected status 0 but received %d (err: %v)", code, err)
  1120  	}
  1121  
  1122  	if s, err := task.Status(ctx); err != nil {
  1123  		t.Errorf("failed to retrieve status: %v", err)
  1124  	} else if s.ExitTime.After(startTime) == false {
  1125  		t.Errorf("exit time is not after start time: %v <= %v", startTime, s.ExitTime)
  1126  	}
  1127  
  1128  	if _, err := task.Delete(ctx); err != nil {
  1129  		t.Fatal(err)
  1130  	}
  1131  }
  1132  
  1133  func TestDeleteContainerExecCreated(t *testing.T) {
  1134  	t.Parallel()
  1135  
  1136  	client, err := newClient(t, address)
  1137  	if err != nil {
  1138  		t.Fatal(err)
  1139  	}
  1140  	defer client.Close()
  1141  
  1142  	var (
  1143  		image       Image
  1144  		ctx, cancel = testContext(t)
  1145  		id          = t.Name()
  1146  	)
  1147  	defer cancel()
  1148  
  1149  	image, err = client.GetImage(ctx, testImage)
  1150  	if err != nil {
  1151  		t.Fatal(err)
  1152  	}
  1153  
  1154  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
  1155  	if err != nil {
  1156  		t.Fatal(err)
  1157  	}
  1158  	defer container.Delete(ctx, WithSnapshotCleanup)
  1159  
  1160  	task, err := container.NewTask(ctx, empty())
  1161  	if err != nil {
  1162  		t.Fatal(err)
  1163  	}
  1164  	defer task.Delete(ctx)
  1165  
  1166  	finished, err := task.Wait(ctx)
  1167  	if err != nil {
  1168  		t.Error(err)
  1169  	}
  1170  
  1171  	if err := task.Start(ctx); err != nil {
  1172  		t.Fatal(err)
  1173  	}
  1174  	spec, err := container.Spec(ctx)
  1175  	if err != nil {
  1176  		t.Fatal(err)
  1177  	}
  1178  
  1179  	// start an exec process without running the original container process info
  1180  	processSpec := spec.Process
  1181  	withExecExitStatus(processSpec, 6)
  1182  	execID := t.Name() + "_exec"
  1183  	process, err := task.Exec(ctx, execID, processSpec, empty())
  1184  	if err != nil {
  1185  		t.Fatal(err)
  1186  	}
  1187  	deleteStatus, err := process.Delete(ctx)
  1188  	if err != nil {
  1189  		t.Fatal(err)
  1190  	}
  1191  	if ec := deleteStatus.ExitCode(); ec != 0 {
  1192  		t.Errorf("expected delete exit code 0 but received %d", ec)
  1193  	}
  1194  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
  1195  		t.Error(err)
  1196  	}
  1197  	<-finished
  1198  }
  1199  
  1200  func TestContainerMetrics(t *testing.T) {
  1201  	if runtime.GOOS == "windows" {
  1202  		t.Skip("metrics are currently not supported on windows")
  1203  	}
  1204  	t.Parallel()
  1205  
  1206  	client, err := newClient(t, address)
  1207  	if err != nil {
  1208  		t.Fatal(err)
  1209  	}
  1210  	defer client.Close()
  1211  
  1212  	var (
  1213  		image       Image
  1214  		ctx, cancel = testContext(t)
  1215  		id          = t.Name()
  1216  	)
  1217  	defer cancel()
  1218  
  1219  	image, err = client.GetImage(ctx, testImage)
  1220  	if err != nil {
  1221  		t.Fatal(err)
  1222  	}
  1223  	container, err := client.NewContainer(ctx, id,
  1224  		WithNewSnapshot(id, image),
  1225  		WithNewSpec(oci.WithImageConfig(image), oci.WithProcessArgs("sleep", "30")))
  1226  	if err != nil {
  1227  		t.Fatal(err)
  1228  	}
  1229  	defer container.Delete(ctx, WithSnapshotCleanup)
  1230  
  1231  	task, err := container.NewTask(ctx, empty())
  1232  	if err != nil {
  1233  		t.Fatal(err)
  1234  	}
  1235  	defer task.Delete(ctx, WithProcessKill)
  1236  
  1237  	statusC, err := task.Wait(ctx)
  1238  	if err != nil {
  1239  		t.Fatal(err)
  1240  	}
  1241  
  1242  	metric, err := task.Metrics(ctx)
  1243  	if err != nil {
  1244  		t.Error(err)
  1245  		return
  1246  	}
  1247  	if metric.ID != id {
  1248  		t.Errorf("expected metric id %q but received %q", id, metric.ID)
  1249  	}
  1250  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
  1251  		t.Fatal(err)
  1252  	}
  1253  
  1254  	<-statusC
  1255  }
  1256  
  1257  func TestDeletedContainerMetrics(t *testing.T) {
  1258  	if runtime.GOOS == "windows" {
  1259  		t.Skip("metrics are currently not supported on windows")
  1260  	}
  1261  	t.Parallel()
  1262  
  1263  	client, err := newClient(t, address)
  1264  	if err != nil {
  1265  		t.Fatal(err)
  1266  	}
  1267  	defer client.Close()
  1268  
  1269  	var (
  1270  		image       Image
  1271  		ctx, cancel = testContext(t)
  1272  		id          = t.Name()
  1273  	)
  1274  	defer cancel()
  1275  
  1276  	image, err = client.GetImage(ctx, testImage)
  1277  	if err != nil {
  1278  		t.Fatal(err)
  1279  	}
  1280  	container, err := client.NewContainer(ctx, id,
  1281  		WithNewSnapshot(id, image),
  1282  		WithNewSpec(oci.WithImageConfig(image), withExitStatus(0)))
  1283  	if err != nil {
  1284  		t.Fatal(err)
  1285  	}
  1286  	defer container.Delete(ctx, WithSnapshotCleanup)
  1287  
  1288  	task, err := container.NewTask(ctx, empty())
  1289  	if err != nil {
  1290  		t.Fatal(err)
  1291  	}
  1292  	defer task.Delete(ctx)
  1293  
  1294  	if err := task.Start(ctx); err != nil {
  1295  		t.Fatal(err)
  1296  	}
  1297  
  1298  	statusC, err := task.Wait(ctx)
  1299  	if err != nil {
  1300  		t.Fatal(err)
  1301  	}
  1302  	<-statusC
  1303  
  1304  	if _, err := task.Delete(ctx); err != nil {
  1305  		t.Fatal(err)
  1306  	}
  1307  
  1308  	if _, err := task.Metrics(ctx); err == nil {
  1309  		t.Errorf("Getting metrics of deleted task should have failed")
  1310  	}
  1311  }
  1312  
  1313  func TestContainerExtensions(t *testing.T) {
  1314  	t.Parallel()
  1315  
  1316  	ctx, cancel := testContext(t)
  1317  	defer cancel()
  1318  	id := t.Name()
  1319  
  1320  	client, err := newClient(t, address)
  1321  	if err != nil {
  1322  		t.Fatal(err)
  1323  	}
  1324  	defer client.Close()
  1325  
  1326  	ext := gogotypes.Any{TypeUrl: "test.ext.url", Value: []byte("hello")}
  1327  	container, err := client.NewContainer(ctx, id, WithNewSpec(), WithContainerExtension("hello", &ext))
  1328  	if err != nil {
  1329  		t.Fatal(err)
  1330  	}
  1331  	defer container.Delete(ctx)
  1332  
  1333  	checkExt := func(container Container) {
  1334  		cExts, err := container.Extensions(ctx)
  1335  		if err != nil {
  1336  			t.Fatal(err)
  1337  		}
  1338  		if len(cExts) != 1 {
  1339  			t.Errorf("expected 1 container extension")
  1340  		}
  1341  		if cExts["hello"].TypeUrl != ext.TypeUrl {
  1342  			t.Errorf("got unexpected type url for extension: %s", cExts["hello"].TypeUrl)
  1343  		}
  1344  		if !bytes.Equal(cExts["hello"].Value, ext.Value) {
  1345  			t.Errorf("expected extension value %q, got: %q", ext.Value, cExts["hello"].Value)
  1346  		}
  1347  	}
  1348  
  1349  	checkExt(container)
  1350  
  1351  	container, err = client.LoadContainer(ctx, container.ID())
  1352  	if err != nil {
  1353  		t.Fatal(err)
  1354  	}
  1355  	checkExt(container)
  1356  }
  1357  
  1358  func TestContainerUpdate(t *testing.T) {
  1359  	t.Parallel()
  1360  
  1361  	ctx, cancel := testContext(t)
  1362  	defer cancel()
  1363  	id := t.Name()
  1364  
  1365  	client, err := newClient(t, address)
  1366  	if err != nil {
  1367  		t.Fatal(err)
  1368  	}
  1369  	defer client.Close()
  1370  
  1371  	container, err := client.NewContainer(ctx, id, WithNewSpec())
  1372  	if err != nil {
  1373  		t.Fatal(err)
  1374  	}
  1375  	defer container.Delete(ctx)
  1376  
  1377  	spec, err := container.Spec(ctx)
  1378  	if err != nil {
  1379  		t.Fatal(err)
  1380  	}
  1381  
  1382  	const hostname = "updated-hostname"
  1383  	spec.Hostname = hostname
  1384  
  1385  	if err := container.Update(ctx, func(ctx context.Context, client *Client, c *containers.Container) error {
  1386  		a, err := typeurl.MarshalAny(spec)
  1387  		if err != nil {
  1388  			return err
  1389  		}
  1390  		c.Spec = a
  1391  		return nil
  1392  	}); err != nil {
  1393  		t.Fatal(err)
  1394  	}
  1395  	if spec, err = container.Spec(ctx); err != nil {
  1396  		t.Fatal(err)
  1397  	}
  1398  	if spec.Hostname != hostname {
  1399  		t.Errorf("hostname %q != %q", spec.Hostname, hostname)
  1400  	}
  1401  }
  1402  
  1403  func TestContainerInfo(t *testing.T) {
  1404  	t.Parallel()
  1405  
  1406  	ctx, cancel := testContext(t)
  1407  	defer cancel()
  1408  	id := t.Name()
  1409  
  1410  	client, err := newClient(t, address)
  1411  	if err != nil {
  1412  		t.Fatal(err)
  1413  	}
  1414  	defer client.Close()
  1415  
  1416  	container, err := client.NewContainer(ctx, id, WithNewSpec())
  1417  	if err != nil {
  1418  		t.Fatal(err)
  1419  	}
  1420  	defer container.Delete(ctx)
  1421  
  1422  	info, err := container.Info(ctx)
  1423  	if err != nil {
  1424  		t.Fatal(err)
  1425  	}
  1426  	if info.ID != container.ID() {
  1427  		t.Fatalf("info.ID=%s != container.ID()=%s", info.ID, container.ID())
  1428  	}
  1429  }
  1430  
  1431  func TestContainerLabels(t *testing.T) {
  1432  	t.Parallel()
  1433  
  1434  	ctx, cancel := testContext(t)
  1435  	defer cancel()
  1436  	id := t.Name()
  1437  
  1438  	client, err := newClient(t, address)
  1439  	if err != nil {
  1440  		t.Fatal(err)
  1441  	}
  1442  	defer client.Close()
  1443  
  1444  	container, err := client.NewContainer(ctx, id, WithNewSpec(), WithContainerLabels(map[string]string{
  1445  		"test": "yes",
  1446  	}))
  1447  	if err != nil {
  1448  		t.Fatal(err)
  1449  	}
  1450  	defer container.Delete(ctx)
  1451  
  1452  	labels, err := container.Labels(ctx)
  1453  	if err != nil {
  1454  		t.Fatal(err)
  1455  	}
  1456  	if labels["test"] != "yes" {
  1457  		t.Fatalf("expected label \"test\" to be \"yes\"")
  1458  	}
  1459  	labels["test"] = "no"
  1460  	if labels, err = container.SetLabels(ctx, labels); err != nil {
  1461  		t.Fatal(err)
  1462  	}
  1463  	if labels["test"] != "no" {
  1464  		t.Fatalf("expected label \"test\" to be \"no\"")
  1465  	}
  1466  }
  1467  
  1468  func TestContainerHook(t *testing.T) {
  1469  	t.Parallel()
  1470  
  1471  	client, err := newClient(t, address)
  1472  	if err != nil {
  1473  		t.Fatal(err)
  1474  	}
  1475  	defer client.Close()
  1476  
  1477  	var (
  1478  		image       Image
  1479  		ctx, cancel = testContext(t)
  1480  		id          = t.Name()
  1481  	)
  1482  	defer cancel()
  1483  
  1484  	image, err = client.GetImage(ctx, testImage)
  1485  	if err != nil {
  1486  		t.Fatal(err)
  1487  	}
  1488  	hook := func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
  1489  		if s.Hooks == nil {
  1490  			s.Hooks = &specs.Hooks{}
  1491  		}
  1492  		path, err := exec.LookPath("containerd")
  1493  		if err != nil {
  1494  			return err
  1495  		}
  1496  		psPath, err := exec.LookPath("ps")
  1497  		if err != nil {
  1498  			return err
  1499  		}
  1500  		s.Hooks.Prestart = []specs.Hook{
  1501  			{
  1502  				Path: path,
  1503  				Args: []string{
  1504  					"containerd",
  1505  					"oci-hook", "--",
  1506  					psPath, "--pid", "{{pid}}",
  1507  				},
  1508  				Env: os.Environ(),
  1509  			},
  1510  		}
  1511  		return nil
  1512  	}
  1513  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), hook))
  1514  	if err != nil {
  1515  		t.Fatal(err)
  1516  	}
  1517  	defer container.Delete(ctx, WithSnapshotCleanup)
  1518  
  1519  	task, err := container.NewTask(ctx, empty())
  1520  	if err != nil {
  1521  		t.Fatal(err)
  1522  	}
  1523  	defer task.Delete(ctx, WithProcessKill)
  1524  }
  1525  
  1526  func TestShimSockLength(t *testing.T) {
  1527  	t.Parallel()
  1528  
  1529  	// Max length of namespace should be 76
  1530  	namespace := strings.Repeat("n", 76)
  1531  
  1532  	ctx, cancel := context.WithCancel(context.Background())
  1533  	defer cancel()
  1534  
  1535  	ctx = namespaces.WithNamespace(ctx, namespace)
  1536  
  1537  	client, err := newClient(t, address)
  1538  	if err != nil {
  1539  		t.Fatal(err)
  1540  	}
  1541  	defer client.Close()
  1542  
  1543  	image, err := client.Pull(ctx, testImage,
  1544  		WithPlatformMatcher(platforms.Default()),
  1545  		WithPullUnpack,
  1546  	)
  1547  	if err != nil {
  1548  		t.Fatal(err)
  1549  	}
  1550  
  1551  	id := strings.Repeat("c", 64)
  1552  
  1553  	// We don't have limitation with length of container name,
  1554  	// but 64 bytes of sha256 is the common case
  1555  	container, err := client.NewContainer(ctx, id,
  1556  		WithNewSnapshot(id, image),
  1557  		WithNewSpec(oci.WithImageConfig(image), withExitStatus(0)),
  1558  	)
  1559  	if err != nil {
  1560  		t.Fatal(err)
  1561  	}
  1562  	defer container.Delete(ctx, WithSnapshotCleanup)
  1563  
  1564  	task, err := container.NewTask(ctx, empty())
  1565  	if err != nil {
  1566  		t.Fatal(err)
  1567  	}
  1568  	defer task.Delete(ctx)
  1569  
  1570  	statusC, err := task.Wait(ctx)
  1571  	if err != nil {
  1572  		t.Fatal(err)
  1573  	}
  1574  
  1575  	if err := task.Start(ctx); err != nil {
  1576  		t.Fatal(err)
  1577  	}
  1578  
  1579  	<-statusC
  1580  }
  1581  
  1582  func TestContainerExecLargeOutputWithTTY(t *testing.T) {
  1583  	t.Parallel()
  1584  
  1585  	client, err := newClient(t, address)
  1586  	if err != nil {
  1587  		t.Fatal(err)
  1588  	}
  1589  	defer client.Close()
  1590  
  1591  	var (
  1592  		image       Image
  1593  		ctx, cancel = testContext(t)
  1594  		id          = t.Name()
  1595  	)
  1596  	defer cancel()
  1597  
  1598  	image, err = client.GetImage(ctx, testImage)
  1599  	if err != nil {
  1600  		t.Fatal(err)
  1601  	}
  1602  
  1603  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "999")))
  1604  	if err != nil {
  1605  		t.Fatal(err)
  1606  	}
  1607  	defer container.Delete(ctx, WithSnapshotCleanup)
  1608  
  1609  	task, err := container.NewTask(ctx, empty())
  1610  	if err != nil {
  1611  		t.Fatal(err)
  1612  	}
  1613  	defer task.Delete(ctx)
  1614  
  1615  	finishedC, err := task.Wait(ctx)
  1616  	if err != nil {
  1617  		t.Fatal(err)
  1618  	}
  1619  
  1620  	if err := task.Start(ctx); err != nil {
  1621  		t.Fatal(err)
  1622  	}
  1623  
  1624  	for i := 0; i < 100; i++ {
  1625  		spec, err := container.Spec(ctx)
  1626  		if err != nil {
  1627  			t.Fatal(err)
  1628  		}
  1629  
  1630  		// start an exec process without running the original container process info
  1631  		processSpec := spec.Process
  1632  		withExecArgs(processSpec, "sh", "-c", `seq -s " " 1000000`)
  1633  
  1634  		stdout := bytes.NewBuffer(nil)
  1635  
  1636  		execID := t.Name() + "_exec"
  1637  		process, err := task.Exec(ctx, execID, processSpec, cio.NewCreator(withByteBuffers(stdout), withProcessTTY()))
  1638  		if err != nil {
  1639  			t.Fatal(err)
  1640  		}
  1641  		processStatusC, err := process.Wait(ctx)
  1642  		if err != nil {
  1643  			t.Fatal(err)
  1644  		}
  1645  
  1646  		if err := process.Start(ctx); err != nil {
  1647  			t.Fatal(err)
  1648  		}
  1649  
  1650  		// wait for the exec to return
  1651  		status := <-processStatusC
  1652  		code, _, err := status.Result()
  1653  		if err != nil {
  1654  			t.Fatal(err)
  1655  		}
  1656  
  1657  		if code != 0 {
  1658  			t.Errorf("expected exec exit code 0 but received %d", code)
  1659  		}
  1660  		if _, err := process.Delete(ctx); err != nil {
  1661  			t.Fatal(err)
  1662  		}
  1663  
  1664  		const expectedSuffix = "999999 1000000"
  1665  		stdoutString := stdout.String()
  1666  		if !strings.Contains(stdoutString, expectedSuffix) {
  1667  			t.Fatalf("process output does not end with %q at iteration %d, here are the last 20 characters of the output:\n\n %q", expectedSuffix, i, stdoutString[len(stdoutString)-20:])
  1668  		}
  1669  
  1670  	}
  1671  
  1672  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
  1673  		t.Error(err)
  1674  	}
  1675  	<-finishedC
  1676  }
  1677  
  1678  func TestShortRunningTaskPid(t *testing.T) {
  1679  	t.Parallel()
  1680  
  1681  	client, err := newClient(t, address)
  1682  	if err != nil {
  1683  		t.Fatal(err)
  1684  	}
  1685  	defer client.Close()
  1686  
  1687  	var (
  1688  		image       Image
  1689  		ctx, cancel = testContext(t)
  1690  		id          = t.Name()
  1691  	)
  1692  	defer cancel()
  1693  
  1694  	image, err = client.GetImage(ctx, testImage)
  1695  	if err != nil {
  1696  		t.Fatal(err)
  1697  	}
  1698  
  1699  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("true")))
  1700  	if err != nil {
  1701  		t.Fatal(err)
  1702  	}
  1703  	defer container.Delete(ctx, WithSnapshotCleanup)
  1704  
  1705  	task, err := container.NewTask(ctx, empty())
  1706  	if err != nil {
  1707  		t.Fatal(err)
  1708  	}
  1709  	defer task.Delete(ctx)
  1710  
  1711  	finishedC, err := task.Wait(ctx)
  1712  	if err != nil {
  1713  		t.Fatal(err)
  1714  	}
  1715  
  1716  	if err := task.Start(ctx); err != nil {
  1717  		t.Fatal(err)
  1718  	}
  1719  
  1720  	int32PID := int32(task.Pid())
  1721  	if int32PID <= 0 {
  1722  		t.Errorf("Unexpected task pid %d", int32PID)
  1723  	}
  1724  	<-finishedC
  1725  }
  1726  
  1727  func withProcessTTY() cio.Opt {
  1728  	return func(opt *cio.Streams) {
  1729  		cio.WithTerminal(opt)
  1730  	}
  1731  }