Files
kata-containers/src/runtime/pkg/katatestutils/constraints_api.go
Peng Tao a02a8bda66 runtime: move all code to src/runtime
To prepare for merging into kata-containers repository.

Signed-off-by: Peng Tao <bergwolf@hyper.sh>
2020-04-27 19:39:25 -07:00

310 lines
8.5 KiB
Go

// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
// This file contains the public API for the test constraints facility.
package katatestutils
import (
"os"
"strings"
)
// Operator represents an operator to apply to a test constraint value.
type Operator int
const (
eqOperator Operator = iota
geOperator Operator = iota
gtOperator Operator = iota
leOperator Operator = iota
ltOperator Operator = iota
neOperator Operator = iota
)
// Constraints encapsulates all information about a test constraint.
type Constraints struct {
Issue string
UID int
// Not ideal: set when UID needs to be checked. This allows
// a test for UID 0 to be detected.
UIDSet bool
// DistroName is the name of a distro in all lower-case letters.
DistroName string
// DistroVersion is the version of the particular distro in string
// format. It may contain periods and dashes.
DistroVersion string
// KernelVersion is the version of a particular kernel.
KernelVersion string
// Operator is the operator to apply to one of the constraints.
Operator Operator
}
// Constraint is a function that operates on a Constraints object to set
// particular values.
type Constraint func(c *Constraints)
// TestConstraint records details about test constraints.
type TestConstraint struct {
Debug bool
// Effective user ID of running test
ActualEUID int
DistroName string
DistroVersion string
KernelVersion string
// Used to record all passed and failed constraints in
// human-readable form.
Passed []Result
Failed []Result
// Optionally used to record an issue number that relates to the
// constraint.
Issue string
}
// NewKataTest creates a new TestConstraint object and is the main interface
// to the test constraints feature.
func NewTestConstraint(debug bool) TestConstraint {
distroName, distroVersion, err := getDistroDetails()
if err != nil {
panic(err)
}
kernelVersion, err := getKernelVersion()
if err != nil {
panic(err)
}
return TestConstraint{
Debug: debug,
ActualEUID: os.Geteuid(),
DistroName: distroName,
DistroVersion: distroVersion,
KernelVersion: kernelVersion,
}
}
// NotValid checks if the specified list of constraints are all valid,
// returning true if any _fail_.
//
// Notes:
//
// - Constraints are applied in the order specified.
// - A constraint type (user, distro) can only be specified once.
// - If the function fails to determine whether it can check the constraints,
// it will panic. Since this is facility is used for testing, this seems like
// the best approach as it unburdens the caller from checking for an error
// (which should never be ignored).
func (tc *TestConstraint) NotValid(constraints ...Constraint) bool {
if len(constraints) == 0 {
panic("need atleast one constraint")
}
// Reset in case of a previous call
tc.Passed = nil
tc.Failed = nil
tc.Issue = ""
for _, c := range constraints {
valid := tc.constraintValid(c)
if !valid {
return true
}
}
return false
}
// NeedUID skips the test unless running as a user with the specified user ID.
func NeedUID(uid int, op Operator) Constraint {
return func(c *Constraints) {
c.Operator = op
c.UID = uid
c.UIDSet = true
}
}
// NeedNonRoot skips the test unless running as root.
func NeedRoot() Constraint {
return NeedUID(0, eqOperator)
}
// NeedNonRoot skips the test if running as the root user.
func NeedNonRoot() Constraint {
return NeedUID(0, neOperator)
}
// NeedDistroWithOp skips the test unless the distro constraint specified by
// the arguments is true.
func NeedDistroWithOp(distro string, op Operator) Constraint {
return func(c *Constraints) {
c.DistroName = strings.ToLower(distro)
c.Operator = op
}
}
// NeedDistroEquals will skip the test unless running on the specified distro.
func NeedDistroEquals(distro string) Constraint {
return NeedDistroWithOp(distro, eqOperator)
}
// NeedDistroNotEquals will skip the test unless run a distro that does not
// match the specified name.
func NeedDistroNotEquals(distro string) Constraint {
return NeedDistroWithOp(distro, neOperator)
}
// NeedDistro will skip the test unless running on the specified distro.
func NeedDistro(distro string) Constraint {
return NeedDistroEquals(distro)
}
// NeedDistroVersionWithOp skips the test unless the distro version constraint
// specified by the arguments is true.
//
// Note: distro versions vary in format.
func NeedDistroVersionWithOp(version string, op Operator) Constraint {
return func(c *Constraints) {
c.DistroVersion = version
c.Operator = op
}
}
// NeedDistroVersionEquals will skip the test unless the distro version is the
// same as the specified version.
//
// Note: distro versions vary in format.
func NeedDistroVersionEquals(version string) Constraint {
return NeedDistroVersionWithOp(version, eqOperator)
}
// NeedDistroVersionNotEquals will skip the test unless the distro version is
// different to the specified version.
//
// Note: distro versions vary in format.
func NeedDistroVersionNotEquals(version string) Constraint {
return NeedDistroVersionWithOp(version, neOperator)
}
// NeedDistroVersionLE will skip the test unless the distro version is older
// than or the same as the specified version.
//
// Note: distro versions vary in format.
func NeedDistroVersionLE(version string) Constraint {
return NeedDistroVersionWithOp(version, leOperator)
}
// NeedDistroVersionLT will skip the test unless the distro version is older
// than the specified version.
//
// Note: distro versions vary in format.
func NeedDistroVersionLT(version string) Constraint {
return NeedDistroVersionWithOp(version, ltOperator)
}
// NeedDistroVersionGE will skip the test unless the distro version is newer
// than or the same as the specified version.
//
// Note: distro versions vary in format.
func NeedDistroVersionGE(version string) Constraint {
return NeedDistroVersionWithOp(version, geOperator)
}
// NeedDistroVersionGT will skip the test unless the distro version is newer
// than the specified version.
//
// Note: distro versions vary in format.
func NeedDistroVersionGT(version string) Constraint {
return NeedDistroVersionWithOp(version, gtOperator)
}
// NeedDistroVersion will skip the test unless running on the specified
// (exact) version of some distro.
//
// Note: distro versions vary in format.
func NeedDistroVersion(version string) Constraint {
return NeedDistroVersionEquals(version)
}
// NeedKernelVersionWithOp skips the test unless the distro version constraint
// specified by the arguments is true.
func NeedKernelVersionWithOp(version string, op Operator) Constraint {
return func(c *Constraints) {
c.KernelVersion = version
c.Operator = op
}
}
// NeedKernelVersionLT will skip the test unless the distro version is older
// than the specified version.
func NeedKernelVersionEquals(version string) Constraint {
return NeedKernelVersionWithOp(version, eqOperator)
}
// NeedKernelVersionNotEquals will skip the test unless the distro version is
// different to the specified version.
func NeedKernelVersionNotEquals(version string) Constraint {
return NeedKernelVersionWithOp(version, neOperator)
}
// NeedKernelVersionLT will skip the test unless the distro version is older
// than the specified version.
//
// Note: distro versions vary in format.
func NeedKernelVersionLT(version string) Constraint {
return NeedKernelVersionWithOp(version, ltOperator)
}
// NeedKernelVersionLE will skip the test unless the distro version is older
// than or the same as the specified version.
//
// Note: distro versions vary in format.
func NeedKernelVersionLE(version string) Constraint {
return NeedKernelVersionWithOp(version, leOperator)
}
// NeedKernelVersionGT will skip the test unless the distro version is newer
// than the specified version.
//
// Note: distro versions vary in format.
func NeedKernelVersionGT(version string) Constraint {
return NeedKernelVersionWithOp(version, gtOperator)
}
// NeedKernelVersionGE will skip the test unless the distro version is newer
// than or the same as the specified version.
//
// Note: distro versions vary in format.
func NeedKernelVersionGE(version string) Constraint {
return NeedKernelVersionWithOp(version, geOperator)
}
// NeedKernelVersion will skip the test unless running on the specified
// (exact) version of some distro.
//
// Note: distro versions vary in format.
func NeedKernelVersion(version string) Constraint {
return NeedKernelVersionEquals(version)
}
// WithIssue allows the specification of an issue URL.
//
// Note that the issue is not checked for validity.
func WithIssue(issue string) Constraint {
return func(c *Constraints) {
c.Issue = issue
}
}