bc37c036 |
package main
import ( |
321874f3 |
"encoding/json" |
e2aa8f0c |
"fmt" |
6f75dd85 |
"io/ioutil" |
321874f3 |
"log" |
5daa9260 |
"net/http" |
ea3afdad |
"os" |
e2aa8f0c |
"os/exec" |
321874f3 |
"strings" |
6e4c6da8 |
"time" |
dc944ea7 |
"github.com/go-check/check" |
bc37c036 |
)
|
6b3c9281 |
type testCondition func() bool |
bc37c036 |
|
6b3c9281 |
type testRequirement struct {
Condition testCondition |
bc37c036 |
SkipMessage string
}
// List test requirements
var ( |
321874f3 |
daemonExecDriver string
|
cd18e7bb |
DaemonIsWindows = testRequirement{
func() bool { return daemonPlatform == "windows" },
"Test requires a Windows daemon",
}
DaemonIsLinux = testRequirement{
func() bool { return daemonPlatform == "linux" },
"Test requires a Linux daemon",
} |
6b3c9281 |
SameHostDaemon = testRequirement{ |
bc37c036 |
func() bool { return isLocalDaemon },
"Test requires docker daemon to runs on the same machine as CLI",
} |
6b3c9281 |
UnixCli = testRequirement{ |
492a58f0 |
func() bool { return isUnixCli },
"Test requires posix utilities or functionality to run.",
} |
6b3c9281 |
ExecSupport = testRequirement{ |
102e0611 |
func() bool { return supportsExec },
"Test requires 'docker exec' capabilities on the tested daemon.",
} |
6b3c9281 |
Network = testRequirement{ |
5daa9260 |
func() bool { |
6e4c6da8 |
// Set a timeout on the GET at 15s
var timeout = time.Duration(15 * time.Second)
var url = "https://hub.docker.com"
client := http.Client{
Timeout: timeout,
}
resp, err := client.Get(url)
if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
panic(fmt.Sprintf("Timeout for GET request on %s", url))
} |
5daa9260 |
if resp != nil {
resp.Body.Close()
}
return err == nil
},
"Test requires network availability, environment variable set to none to run in a non-network enabled mode.",
} |
6b3c9281 |
Apparmor = testRequirement{ |
6f75dd85 |
func() bool {
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
return err == nil && len(buf) > 1 && buf[0] == 'Y'
},
"Test requires apparmor is enabled.",
} |
6b3c9281 |
RegistryHosting = testRequirement{ |
e2aa8f0c |
func() bool {
// for now registry binary is built only if we're running inside
// container through `make test`. Figure that out by testing if
// registry binary is in PATH.
_, err := exec.LookPath(v2binary)
return err == nil
},
fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary),
} |
58a1de9b |
NotaryHosting = testRequirement{
func() bool {
// for now notary binary is built only if we're running inside
// container through `make test`. Figure that out by testing if
// notary-server binary is in PATH.
_, err := exec.LookPath(notaryBinary)
return err == nil
},
fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryBinary),
} |
6b3c9281 |
NativeExecDriver = testRequirement{ |
321874f3 |
func() bool {
if daemonExecDriver == "" {
// get daemon info |
c7845e27 |
status, body, err := sockRequest("GET", "/info", nil)
if err != nil || status != http.StatusOK { |
321874f3 |
log.Fatalf("sockRequest failed for /info: %v", err)
}
type infoJSON struct {
ExecutionDriver string
}
var info infoJSON
if err = json.Unmarshal(body, &info); err != nil {
log.Fatalf("unable to unmarshal body: %v", err)
}
daemonExecDriver = info.ExecutionDriver
}
return strings.HasPrefix(daemonExecDriver, "native")
},
"Test requires the native (libcontainer) exec driver.",
} |
6b3c9281 |
NotOverlay = testRequirement{ |
9057ca25 |
func() bool {
cmd := exec.Command("grep", "^overlay / overlay", "/proc/mounts")
if err := cmd.Run(); err != nil {
return true
}
return false
},
"Test requires underlying root filesystem not be backed by overlay.",
} |
6b3c9281 |
IPv6 = testRequirement{ |
2dfb7f3b |
func() bool {
cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
if err := cmd.Run(); err != nil {
return true
}
return false
},
"Test requires support for IPv6",
} |
2c53643b |
NotGCCGO = testRequirement{
func() bool {
out, err := exec.Command("go", "version").Output()
if err != nil && strings.Contains(string(out), "gccgo") {
return true
}
return false
},
"Test requires native Golang compiler instead of GCCGO",
} |
ea3afdad |
NotUserNamespace = testRequirement{
func() bool {
root := os.Getenv("DOCKER_REMAP_ROOT")
if root != "" { |
930b27a8 |
return false |
ea3afdad |
} |
930b27a8 |
return true |
ea3afdad |
},
"Test cannot be run when remapping root",
} |
bc37c036 |
)
// testRequires checks if the environment satisfies the requirements
// for the test to run or skips the tests. |
6b3c9281 |
func testRequires(c *check.C, requirements ...testRequirement) { |
bc37c036 |
for _, r := range requirements {
if !r.Condition() { |
dc944ea7 |
c.Skip(r.SkipMessage) |
bc37c036 |
}
}
} |