gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/kata_shim_test.go (about) 1 // Copyright (c) 2017 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 package virtcontainers 7 8 import ( 9 "fmt" 10 "io" 11 "io/ioutil" 12 "os" 13 "path/filepath" 14 "strings" 15 "syscall" 16 "testing" 17 "time" 18 "unsafe" 19 20 . "github.com/kata-containers/runtime/virtcontainers/pkg/mock" 21 "github.com/kata-containers/runtime/virtcontainers/utils" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 const ( 26 testContainer = "testContainer" 27 ) 28 29 var ( 30 testKataShimPath = "/usr/bin/virtcontainers/bin/test/kata-shim" 31 testKataShimProxyURL = "foo:///foo/kata-containers/proxy.sock" 32 testWrongConsolePath = "/foo/wrong-console" 33 ) 34 35 func getMockKataShimBinPath() string { 36 if DefaultMockKataShimBinPath == "" { 37 return testKataShimPath 38 } 39 40 return DefaultMockKataShimBinPath 41 } 42 43 func testKataShimStart(t *testing.T, sandbox *Sandbox, params ShimParams, expectFail bool) { 44 s := &kataShim{} 45 assert := assert.New(t) 46 47 pid, err := s.start(sandbox, params) 48 if expectFail { 49 assert.Error(err) 50 assert.Equal(pid, -1) 51 } else { 52 assert.NoError(err) 53 assert.NotEqual(pid, -1) 54 } 55 } 56 57 func TestKataShimStartNilSandboxConfigFailure(t *testing.T) { 58 testKataShimStart(t, &Sandbox{}, ShimParams{}, true) 59 } 60 61 func TestKataShimStartNilShimConfigFailure(t *testing.T) { 62 sandbox := &Sandbox{ 63 config: &SandboxConfig{}, 64 } 65 66 testKataShimStart(t, sandbox, ShimParams{}, true) 67 } 68 69 func TestKataShimStartShimPathEmptyFailure(t *testing.T) { 70 sandbox := &Sandbox{ 71 config: &SandboxConfig{ 72 ShimType: KataShimType, 73 ShimConfig: ShimConfig{}, 74 }, 75 } 76 77 testKataShimStart(t, sandbox, ShimParams{}, true) 78 } 79 80 func TestKataShimStartShimTypeInvalid(t *testing.T) { 81 sandbox := &Sandbox{ 82 config: &SandboxConfig{ 83 ShimType: "foo", 84 ShimConfig: ShimConfig{}, 85 }, 86 } 87 88 testKataShimStart(t, sandbox, ShimParams{}, true) 89 } 90 91 func TestKataShimStartParamsTokenEmptyFailure(t *testing.T) { 92 sandbox := &Sandbox{ 93 config: &SandboxConfig{ 94 ShimType: KataShimType, 95 ShimConfig: ShimConfig{ 96 Path: getMockKataShimBinPath(), 97 }, 98 }, 99 } 100 101 testKataShimStart(t, sandbox, ShimParams{}, true) 102 } 103 104 func TestKataShimStartParamsURLEmptyFailure(t *testing.T) { 105 sandbox := &Sandbox{ 106 config: &SandboxConfig{ 107 ShimType: KataShimType, 108 ShimConfig: ShimConfig{ 109 Path: getMockKataShimBinPath(), 110 }, 111 }, 112 } 113 114 params := ShimParams{ 115 Token: "testToken", 116 } 117 118 testKataShimStart(t, sandbox, params, true) 119 } 120 121 func TestKataShimStartParamsContainerEmptyFailure(t *testing.T) { 122 sandbox := &Sandbox{ 123 config: &SandboxConfig{ 124 ShimType: KataShimType, 125 ShimConfig: ShimConfig{ 126 Path: getMockKataShimBinPath(), 127 }, 128 }, 129 } 130 131 params := ShimParams{ 132 Token: "testToken", 133 URL: "unix://is/awesome", 134 } 135 136 testKataShimStart(t, sandbox, params, true) 137 } 138 139 func TestKataShimStartParamsInvalidCommand(t *testing.T) { 140 dir, err := ioutil.TempDir("", "") 141 assert.NoError(t, err) 142 defer os.RemoveAll(dir) 143 144 cmd := filepath.Join(dir, "does-not-exist") 145 146 sandbox := &Sandbox{ 147 config: &SandboxConfig{ 148 ShimType: KataShimType, 149 ShimConfig: ShimConfig{ 150 Path: cmd, 151 }, 152 }, 153 } 154 155 params := ShimParams{ 156 Token: "testToken", 157 URL: "http://foo", 158 } 159 160 testKataShimStart(t, sandbox, params, true) 161 } 162 163 func startKataShimStartWithoutConsoleSuccessful(t *testing.T, detach bool) (*os.File, *os.File, *os.File, *Sandbox, ShimParams, error) { 164 saveStdout := os.Stdout 165 rStdout, wStdout, err := os.Pipe() 166 if err != nil { 167 return nil, nil, nil, &Sandbox{}, ShimParams{}, err 168 } 169 170 os.Stdout = wStdout 171 172 sandbox := &Sandbox{ 173 config: &SandboxConfig{ 174 ShimType: KataShimType, 175 ShimConfig: ShimConfig{ 176 Path: getMockKataShimBinPath(), 177 }, 178 }, 179 } 180 181 params := ShimParams{ 182 Container: testContainer, 183 Token: "testToken", 184 URL: testKataShimProxyURL, 185 Detach: detach, 186 } 187 188 return rStdout, wStdout, saveStdout, sandbox, params, nil 189 } 190 191 func TestKataShimStartSuccessful(t *testing.T) { 192 rStdout, wStdout, saveStdout, sandbox, params, err := startKataShimStartWithoutConsoleSuccessful(t, false) 193 assert := assert.New(t) 194 assert.NoError(err) 195 196 defer func() { 197 os.Stdout = saveStdout 198 rStdout.Close() 199 wStdout.Close() 200 }() 201 202 testKataShimStart(t, sandbox, params, false) 203 204 bufStdout := make([]byte, 1024) 205 _, err = rStdout.Read(bufStdout) 206 assert.NoError(err) 207 assert.True(strings.Contains(string(bufStdout), ShimStdoutOutput)) 208 } 209 210 func TestKataShimStartDetachSuccessful(t *testing.T) { 211 rStdout, wStdout, saveStdout, sandbox, params, err := startKataShimStartWithoutConsoleSuccessful(t, true) 212 assert.NoError(t, err) 213 214 defer func() { 215 os.Stdout = saveStdout 216 wStdout.Close() 217 rStdout.Close() 218 }() 219 220 testKataShimStart(t, sandbox, params, false) 221 222 readCh := make(chan error, 1) 223 go func() { 224 defer close(readCh) 225 bufStdout := make([]byte, 1024) 226 n, err := rStdout.Read(bufStdout) 227 if err != nil && err != io.EOF { 228 readCh <- err 229 return 230 } 231 232 if n > 0 { 233 readCh <- fmt.Errorf("Not expecting to read anything, Got %q", string(bufStdout)) 234 return 235 } 236 237 readCh <- nil 238 }() 239 240 select { 241 case err := <-readCh: 242 assert.NoError(t, err) 243 case <-time.After(time.Duration(20) * time.Millisecond): 244 return 245 } 246 } 247 248 func TestKataShimStartWithConsoleNonExistingFailure(t *testing.T) { 249 sandbox := &Sandbox{ 250 config: &SandboxConfig{ 251 ShimType: KataShimType, 252 ShimConfig: ShimConfig{ 253 Path: getMockKataShimBinPath(), 254 }, 255 }, 256 } 257 258 params := ShimParams{ 259 Token: "testToken", 260 URL: testKataShimProxyURL, 261 Console: testWrongConsolePath, 262 } 263 264 testKataShimStart(t, sandbox, params, true) 265 } 266 267 // unlockpt unlocks the slave pseudoterminal device corresponding to the master pseudoterminal referred to by f. 268 func unlockpt(f *os.File) error { 269 var u int32 270 271 return utils.Ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) 272 } 273 274 // ptsname retrieves the name of the first available pts for the given master. 275 func ptsname(f *os.File) (string, error) { 276 var n int32 277 278 if err := utils.Ioctl(f.Fd(), syscall.TIOCGPTN, uintptr(unsafe.Pointer(&n))); err != nil { 279 return "", err 280 } 281 282 return fmt.Sprintf("/dev/pts/%d", n), nil 283 } 284 285 func newConsole() (*os.File, string, error) { 286 master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0) 287 if err != nil { 288 return nil, "", err 289 } 290 291 console, err := ptsname(master) 292 if err != nil { 293 return nil, "", err 294 } 295 296 if err := unlockpt(master); err != nil { 297 return nil, "", err 298 } 299 300 if err := os.Chmod(console, 0600); err != nil { 301 return nil, "", err 302 } 303 304 return master, console, nil 305 } 306 307 func TestKataShimStartWithConsoleSuccessful(t *testing.T) { 308 defer cleanUp() 309 310 master, console, err := newConsole() 311 t.Logf("Console created for tests:%s\n", console) 312 assert.NoError(t, err) 313 314 sandbox := &Sandbox{ 315 config: &SandboxConfig{ 316 ShimType: KataShimType, 317 ShimConfig: ShimConfig{ 318 Path: getMockKataShimBinPath(), 319 }, 320 }, 321 } 322 323 params := ShimParams{ 324 Container: testContainer, 325 Token: "testToken", 326 URL: testKataShimProxyURL, 327 Console: console, 328 } 329 330 testKataShimStart(t, sandbox, params, false) 331 master.Close() 332 }