github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/runconfig/hostconfig_test.go (about) 1 // +build !windows 2 3 package runconfig // import "github.com/docker/docker/runconfig" 4 5 import ( 6 "bytes" 7 "fmt" 8 "io/ioutil" 9 "testing" 10 11 "github.com/docker/docker/api/types/container" 12 "github.com/docker/docker/pkg/sysinfo" 13 "gotest.tools/v3/assert" 14 is "gotest.tools/v3/assert/cmp" 15 ) 16 17 func TestCgroupnsModeTest(t *testing.T) { 18 cgroupNsModes := map[container.CgroupnsMode][]bool{ 19 // private, host, empty, valid 20 "": {false, false, true, true}, 21 "something:weird": {false, false, false, false}, 22 "host": {false, true, false, true}, 23 "host:name": {false, false, false, false}, 24 "private": {true, false, false, true}, 25 "private:name": {false, false, false, false}, 26 } 27 for cgroupNsMode, state := range cgroupNsModes { 28 if cgroupNsMode.IsPrivate() != state[0] { 29 t.Fatalf("CgroupnsMode.IsPrivate for %v should have been %v but was %v", cgroupNsMode, state[0], cgroupNsMode.IsPrivate()) 30 } 31 if cgroupNsMode.IsHost() != state[1] { 32 t.Fatalf("CgroupnsMode.IsHost for %v should have been %v but was %v", cgroupNsMode, state[1], cgroupNsMode.IsHost()) 33 } 34 if cgroupNsMode.IsEmpty() != state[2] { 35 t.Fatalf("CgroupnsMode.Valid for %v should have been %v but was %v", cgroupNsMode, state[2], cgroupNsMode.Valid()) 36 } 37 if cgroupNsMode.Valid() != state[3] { 38 t.Fatalf("CgroupnsMode.Valid for %v should have been %v but was %v", cgroupNsMode, state[2], cgroupNsMode.Valid()) 39 } 40 } 41 } 42 43 // TODO Windows: This will need addressing for a Windows daemon. 44 func TestNetworkModeTest(t *testing.T) { 45 networkModes := map[container.NetworkMode][]bool{ 46 // private, bridge, host, container, none, default 47 "": {true, false, false, false, false, false}, 48 "something:weird": {true, false, false, false, false, false}, 49 "bridge": {true, true, false, false, false, false}, 50 DefaultDaemonNetworkMode(): {true, true, false, false, false, false}, 51 "host": {false, false, true, false, false, false}, 52 "container:name": {false, false, false, true, false, false}, 53 "none": {true, false, false, false, true, false}, 54 "default": {true, false, false, false, false, true}, 55 } 56 networkModeNames := map[container.NetworkMode]string{ 57 "": "", 58 "something:weird": "something:weird", 59 "bridge": "bridge", 60 DefaultDaemonNetworkMode(): "bridge", 61 "host": "host", 62 "container:name": "container", 63 "none": "none", 64 "default": "default", 65 } 66 for networkMode, state := range networkModes { 67 if networkMode.IsPrivate() != state[0] { 68 t.Fatalf("NetworkMode.IsPrivate for %v should have been %v but was %v", networkMode, state[0], networkMode.IsPrivate()) 69 } 70 if networkMode.IsBridge() != state[1] { 71 t.Fatalf("NetworkMode.IsBridge for %v should have been %v but was %v", networkMode, state[1], networkMode.IsBridge()) 72 } 73 if networkMode.IsHost() != state[2] { 74 t.Fatalf("NetworkMode.IsHost for %v should have been %v but was %v", networkMode, state[2], networkMode.IsHost()) 75 } 76 if networkMode.IsContainer() != state[3] { 77 t.Fatalf("NetworkMode.IsContainer for %v should have been %v but was %v", networkMode, state[3], networkMode.IsContainer()) 78 } 79 if networkMode.IsNone() != state[4] { 80 t.Fatalf("NetworkMode.IsNone for %v should have been %v but was %v", networkMode, state[4], networkMode.IsNone()) 81 } 82 if networkMode.IsDefault() != state[5] { 83 t.Fatalf("NetworkMode.IsDefault for %v should have been %v but was %v", networkMode, state[5], networkMode.IsDefault()) 84 } 85 if networkMode.NetworkName() != networkModeNames[networkMode] { 86 t.Fatalf("Expected name %v, got %v", networkModeNames[networkMode], networkMode.NetworkName()) 87 } 88 } 89 } 90 91 func TestIpcModeTest(t *testing.T) { 92 ipcModes := map[container.IpcMode]struct { 93 private bool 94 host bool 95 container bool 96 shareable bool 97 valid bool 98 ctrName string 99 }{ 100 "": {valid: true}, 101 "private": {private: true, valid: true}, 102 "something:weird": {}, 103 ":weird": {}, 104 "host": {host: true, valid: true}, 105 "container": {}, 106 "container:": {container: true, valid: true, ctrName: ""}, 107 "container:name": {container: true, valid: true, ctrName: "name"}, 108 "container:name1:name2": {container: true, valid: true, ctrName: "name1:name2"}, 109 "shareable": {shareable: true, valid: true}, 110 } 111 112 for ipcMode, state := range ipcModes { 113 assert.Check(t, is.Equal(state.private, ipcMode.IsPrivate()), "IpcMode.IsPrivate() parsing failed for %q", ipcMode) 114 assert.Check(t, is.Equal(state.host, ipcMode.IsHost()), "IpcMode.IsHost() parsing failed for %q", ipcMode) 115 assert.Check(t, is.Equal(state.container, ipcMode.IsContainer()), "IpcMode.IsContainer() parsing failed for %q", ipcMode) 116 assert.Check(t, is.Equal(state.shareable, ipcMode.IsShareable()), "IpcMode.IsShareable() parsing failed for %q", ipcMode) 117 assert.Check(t, is.Equal(state.valid, ipcMode.Valid()), "IpcMode.Valid() parsing failed for %q", ipcMode) 118 assert.Check(t, is.Equal(state.ctrName, ipcMode.Container()), "IpcMode.Container() parsing failed for %q", ipcMode) 119 } 120 } 121 122 func TestUTSModeTest(t *testing.T) { 123 utsModes := map[container.UTSMode][]bool{ 124 // private, host, valid 125 "": {true, false, true}, 126 "something:weird": {true, false, false}, 127 "host": {false, true, true}, 128 "host:name": {true, false, true}, 129 } 130 for utsMode, state := range utsModes { 131 if utsMode.IsPrivate() != state[0] { 132 t.Fatalf("UtsMode.IsPrivate for %v should have been %v but was %v", utsMode, state[0], utsMode.IsPrivate()) 133 } 134 if utsMode.IsHost() != state[1] { 135 t.Fatalf("UtsMode.IsHost for %v should have been %v but was %v", utsMode, state[1], utsMode.IsHost()) 136 } 137 if utsMode.Valid() != state[2] { 138 t.Fatalf("UtsMode.Valid for %v should have been %v but was %v", utsMode, state[2], utsMode.Valid()) 139 } 140 } 141 } 142 143 func TestUsernsModeTest(t *testing.T) { 144 usrensMode := map[container.UsernsMode][]bool{ 145 // private, host, valid 146 "": {true, false, true}, 147 "something:weird": {true, false, false}, 148 "host": {false, true, true}, 149 "host:name": {true, false, true}, 150 } 151 for usernsMode, state := range usrensMode { 152 if usernsMode.IsPrivate() != state[0] { 153 t.Fatalf("UsernsMode.IsPrivate for %v should have been %v but was %v", usernsMode, state[0], usernsMode.IsPrivate()) 154 } 155 if usernsMode.IsHost() != state[1] { 156 t.Fatalf("UsernsMode.IsHost for %v should have been %v but was %v", usernsMode, state[1], usernsMode.IsHost()) 157 } 158 if usernsMode.Valid() != state[2] { 159 t.Fatalf("UsernsMode.Valid for %v should have been %v but was %v", usernsMode, state[2], usernsMode.Valid()) 160 } 161 } 162 } 163 164 func TestPidModeTest(t *testing.T) { 165 pidModes := map[container.PidMode][]bool{ 166 // private, host, valid 167 "": {true, false, true}, 168 "something:weird": {true, false, false}, 169 "host": {false, true, true}, 170 "host:name": {true, false, true}, 171 } 172 for pidMode, state := range pidModes { 173 if pidMode.IsPrivate() != state[0] { 174 t.Fatalf("PidMode.IsPrivate for %v should have been %v but was %v", pidMode, state[0], pidMode.IsPrivate()) 175 } 176 if pidMode.IsHost() != state[1] { 177 t.Fatalf("PidMode.IsHost for %v should have been %v but was %v", pidMode, state[1], pidMode.IsHost()) 178 } 179 if pidMode.Valid() != state[2] { 180 t.Fatalf("PidMode.Valid for %v should have been %v but was %v", pidMode, state[2], pidMode.Valid()) 181 } 182 } 183 } 184 185 func TestRestartPolicy(t *testing.T) { 186 restartPolicies := map[container.RestartPolicy][]bool{ 187 // none, always, failure 188 {}: {true, false, false}, 189 {Name: "something", MaximumRetryCount: 0}: {false, false, false}, 190 {Name: "no", MaximumRetryCount: 0}: {true, false, false}, 191 {Name: "always", MaximumRetryCount: 0}: {false, true, false}, 192 {Name: "on-failure", MaximumRetryCount: 0}: {false, false, true}, 193 } 194 for restartPolicy, state := range restartPolicies { 195 if restartPolicy.IsNone() != state[0] { 196 t.Fatalf("RestartPolicy.IsNone for %v should have been %v but was %v", restartPolicy, state[0], restartPolicy.IsNone()) 197 } 198 if restartPolicy.IsAlways() != state[1] { 199 t.Fatalf("RestartPolicy.IsAlways for %v should have been %v but was %v", restartPolicy, state[1], restartPolicy.IsAlways()) 200 } 201 if restartPolicy.IsOnFailure() != state[2] { 202 t.Fatalf("RestartPolicy.IsOnFailure for %v should have been %v but was %v", restartPolicy, state[2], restartPolicy.IsOnFailure()) 203 } 204 } 205 } 206 func TestDecodeHostConfig(t *testing.T) { 207 fixtures := []struct { 208 file string 209 }{ 210 {"fixtures/unix/container_hostconfig_1_14.json"}, 211 {"fixtures/unix/container_hostconfig_1_19.json"}, 212 } 213 214 for _, f := range fixtures { 215 b, err := ioutil.ReadFile(f.file) 216 if err != nil { 217 t.Fatal(err) 218 } 219 220 c, err := decodeHostConfig(bytes.NewReader(b)) 221 if err != nil { 222 t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err)) 223 } 224 225 assert.Check(t, !c.Privileged) 226 227 if l := len(c.Binds); l != 1 { 228 t.Fatalf("Expected 1 bind, found %d\n", l) 229 } 230 231 if len(c.CapAdd) != 1 && c.CapAdd[0] != "NET_ADMIN" { 232 t.Fatalf("Expected CapAdd NET_ADMIN, got %v", c.CapAdd) 233 } 234 235 if len(c.CapDrop) != 1 && c.CapDrop[0] != "NET_ADMIN" { 236 t.Fatalf("Expected CapDrop NET_ADMIN, got %v", c.CapDrop) 237 } 238 } 239 } 240 241 func TestValidateResources(t *testing.T) { 242 type resourceTest struct { 243 ConfigCPURealtimePeriod int64 244 ConfigCPURealtimeRuntime int64 245 SysInfoCPURealtimePeriod bool 246 SysInfoCPURealtimeRuntime bool 247 ErrorExpected bool 248 FailureMsg string 249 } 250 251 tests := []resourceTest{ 252 { 253 ConfigCPURealtimePeriod: 1000, 254 ConfigCPURealtimeRuntime: 1000, 255 SysInfoCPURealtimePeriod: true, 256 SysInfoCPURealtimeRuntime: true, 257 ErrorExpected: false, 258 FailureMsg: "Expected valid configuration", 259 }, 260 { 261 ConfigCPURealtimePeriod: 5000, 262 ConfigCPURealtimeRuntime: 5000, 263 SysInfoCPURealtimePeriod: false, 264 SysInfoCPURealtimeRuntime: true, 265 ErrorExpected: true, 266 FailureMsg: "Expected failure when cpu-rt-period is set but kernel doesn't support it", 267 }, 268 { 269 ConfigCPURealtimePeriod: 5000, 270 ConfigCPURealtimeRuntime: 5000, 271 SysInfoCPURealtimePeriod: true, 272 SysInfoCPURealtimeRuntime: false, 273 ErrorExpected: true, 274 FailureMsg: "Expected failure when cpu-rt-runtime is set but kernel doesn't support it", 275 }, 276 { 277 ConfigCPURealtimePeriod: 5000, 278 ConfigCPURealtimeRuntime: 10000, 279 SysInfoCPURealtimePeriod: true, 280 SysInfoCPURealtimeRuntime: false, 281 ErrorExpected: true, 282 FailureMsg: "Expected failure when cpu-rt-runtime is greater than cpu-rt-period", 283 }, 284 } 285 286 for _, rt := range tests { 287 var hc container.HostConfig 288 hc.Resources.CPURealtimePeriod = rt.ConfigCPURealtimePeriod 289 hc.Resources.CPURealtimeRuntime = rt.ConfigCPURealtimeRuntime 290 291 var si sysinfo.SysInfo 292 si.CPURealtimePeriod = rt.SysInfoCPURealtimePeriod 293 si.CPURealtimeRuntime = rt.SysInfoCPURealtimeRuntime 294 295 if err := validateResources(&hc, &si); (err != nil) != rt.ErrorExpected { 296 t.Fatal(rt.FailureMsg, err) 297 } 298 } 299 }