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 }