github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/runsc/specutils/specutils_test.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package specutils
    16  
    17  import (
    18  	"fmt"
    19  	"os/exec"
    20  	"strings"
    21  	"testing"
    22  	"time"
    23  
    24  	specs "github.com/opencontainers/runtime-spec/specs-go"
    25  )
    26  
    27  func TestWaitForReadyHappy(t *testing.T) {
    28  	cmd := exec.Command("/bin/sleep", "1000")
    29  	if err := cmd.Start(); err != nil {
    30  		t.Fatalf("cmd.Start() failed, err: %v", err)
    31  	}
    32  	defer cmd.Wait()
    33  
    34  	var count int
    35  	err := WaitForReady(cmd.Process.Pid, 5*time.Second, func() (bool, error) {
    36  		if count < 3 {
    37  			count++
    38  			return false, nil
    39  		}
    40  		return true, nil
    41  	})
    42  	if err != nil {
    43  		t.Errorf("ProcessWaitReady got: %v, expected: nil", err)
    44  	}
    45  	cmd.Process.Kill()
    46  }
    47  
    48  func TestWaitForReadyFail(t *testing.T) {
    49  	cmd := exec.Command("/bin/sleep", "1000")
    50  	if err := cmd.Start(); err != nil {
    51  		t.Fatalf("cmd.Start() failed, err: %v", err)
    52  	}
    53  	defer cmd.Wait()
    54  
    55  	var count int
    56  	err := WaitForReady(cmd.Process.Pid, 5*time.Second, func() (bool, error) {
    57  		if count < 3 {
    58  			count++
    59  			return false, nil
    60  		}
    61  		return false, fmt.Errorf("Fake error")
    62  	})
    63  	if err == nil {
    64  		t.Errorf("ProcessWaitReady got: nil, expected: error")
    65  	}
    66  	cmd.Process.Kill()
    67  }
    68  
    69  func TestWaitForReadyNotRunning(t *testing.T) {
    70  	cmd := exec.Command("/bin/true")
    71  	if err := cmd.Start(); err != nil {
    72  		t.Fatalf("cmd.Start() failed, err: %v", err)
    73  	}
    74  	defer cmd.Wait()
    75  
    76  	err := WaitForReady(cmd.Process.Pid, 5*time.Second, func() (bool, error) {
    77  		return false, nil
    78  	})
    79  	if err != nil && !strings.Contains(err.Error(), "terminated") {
    80  		t.Errorf("ProcessWaitReady got: %v, expected: process terminated", err)
    81  	}
    82  	if err == nil {
    83  		t.Errorf("ProcessWaitReady incorrectly succeeded")
    84  	}
    85  }
    86  
    87  func TestWaitForReadyTimeout(t *testing.T) {
    88  	cmd := exec.Command("/bin/sleep", "1000")
    89  	if err := cmd.Start(); err != nil {
    90  		t.Fatalf("cmd.Start() failed, err: %v", err)
    91  	}
    92  	defer cmd.Wait()
    93  
    94  	err := WaitForReady(cmd.Process.Pid, 50*time.Millisecond, func() (bool, error) {
    95  		return false, nil
    96  	})
    97  	if !strings.Contains(err.Error(), "not running yet") {
    98  		t.Errorf("ProcessWaitReady got: %v, expected: not running yet", err)
    99  	}
   100  	cmd.Process.Kill()
   101  }
   102  
   103  func TestSpecInvalid(t *testing.T) {
   104  	for _, test := range []struct {
   105  		name  string
   106  		spec  specs.Spec
   107  		error string
   108  	}{
   109  		{
   110  			name: "valid",
   111  			spec: specs.Spec{
   112  				Root: &specs.Root{Path: "/"},
   113  				Process: &specs.Process{
   114  					Args: []string{"/bin/true"},
   115  				},
   116  				Mounts: []specs.Mount{
   117  					{
   118  						Source:      "src",
   119  						Destination: "/dst",
   120  					},
   121  				},
   122  			},
   123  			error: "",
   124  		},
   125  		{
   126  			name: "valid+warning",
   127  			spec: specs.Spec{
   128  				Root: &specs.Root{Path: "/"},
   129  				Process: &specs.Process{
   130  					Args: []string{"/bin/true"},
   131  					// This is normally set by docker and will just cause warnings to be logged.
   132  					ApparmorProfile: "someprofile",
   133  				},
   134  				// This is normally set by docker and will just cause warnings to be logged.
   135  				Linux: &specs.Linux{Seccomp: &specs.LinuxSeccomp{}},
   136  			},
   137  			error: "",
   138  		},
   139  		{
   140  			name: "no root",
   141  			spec: specs.Spec{
   142  				Process: &specs.Process{
   143  					Args: []string{"/bin/true"},
   144  				},
   145  			},
   146  			error: "must be defined",
   147  		},
   148  		{
   149  			name: "empty root",
   150  			spec: specs.Spec{
   151  				Root: &specs.Root{},
   152  				Process: &specs.Process{
   153  					Args: []string{"/bin/true"},
   154  				},
   155  			},
   156  			error: "must be defined",
   157  		},
   158  		{
   159  			name: "no process",
   160  			spec: specs.Spec{
   161  				Root: &specs.Root{Path: "/"},
   162  			},
   163  			error: "must be defined",
   164  		},
   165  		{
   166  			name: "empty args",
   167  			spec: specs.Spec{
   168  				Root:    &specs.Root{Path: "/"},
   169  				Process: &specs.Process{},
   170  			},
   171  			error: "must be defined",
   172  		},
   173  		{
   174  			name: "selinux",
   175  			spec: specs.Spec{
   176  				Root: &specs.Root{Path: "/"},
   177  				Process: &specs.Process{
   178  					Args:         []string{"/bin/true"},
   179  					SelinuxLabel: "somelabel",
   180  				},
   181  			},
   182  			error: "is not supported",
   183  		},
   184  		{
   185  			name: "solaris",
   186  			spec: specs.Spec{
   187  				Root: &specs.Root{Path: "/"},
   188  				Process: &specs.Process{
   189  					Args: []string{"/bin/true"},
   190  				},
   191  				Solaris: &specs.Solaris{},
   192  			},
   193  			error: "is not supported",
   194  		},
   195  		{
   196  			name: "windows",
   197  			spec: specs.Spec{
   198  				Root: &specs.Root{Path: "/"},
   199  				Process: &specs.Process{
   200  					Args: []string{"/bin/true"},
   201  				},
   202  				Windows: &specs.Windows{},
   203  			},
   204  			error: "is not supported",
   205  		},
   206  		{
   207  			name: "relative mount destination",
   208  			spec: specs.Spec{
   209  				Root: &specs.Root{Path: "/"},
   210  				Process: &specs.Process{
   211  					Args: []string{"/bin/true"},
   212  				},
   213  				Mounts: []specs.Mount{
   214  					{
   215  						Source:      "src",
   216  						Destination: "dst",
   217  					},
   218  				},
   219  			},
   220  			error: "must be an absolute path",
   221  		},
   222  		{
   223  			name: "invalid mount option",
   224  			spec: specs.Spec{
   225  				Root: &specs.Root{Path: "/"},
   226  				Process: &specs.Process{
   227  					Args: []string{"/bin/true"},
   228  				},
   229  				Mounts: []specs.Mount{
   230  					{
   231  						Source:      "/src",
   232  						Destination: "/dst",
   233  						Type:        "bind",
   234  						Options:     []string{"shared"},
   235  					},
   236  				},
   237  			},
   238  			error: "is not supported",
   239  		},
   240  		{
   241  			name: "invalid rootfs propagation",
   242  			spec: specs.Spec{
   243  				Root: &specs.Root{Path: "/"},
   244  				Process: &specs.Process{
   245  					Args: []string{"/bin/true"},
   246  				},
   247  				Linux: &specs.Linux{
   248  					RootfsPropagation: "foo",
   249  				},
   250  			},
   251  			error: "root mount propagation option must specify private or slave",
   252  		},
   253  	} {
   254  		err := ValidateSpec(&test.spec)
   255  		if len(test.error) == 0 {
   256  			if err != nil {
   257  				t.Errorf("ValidateSpec(%q) failed, err: %v", test.name, err)
   258  			}
   259  		} else {
   260  			if err == nil || !strings.Contains(err.Error(), test.error) {
   261  				t.Errorf("ValidateSpec(%q) wrong error, got: %v, want: .*%s.*", test.name, err, test.error)
   262  			}
   263  		}
   264  	}
   265  }