mirror of
https://github.com/aljazceru/kata-containers.git
synced 2025-12-18 14:54:19 +01:00
Change io/ioutil to io/os packages because io/ioutil package is deprecated from 1.16: Discard => io.Discard NopCloser => io.NopCloser ReadAll => io.ReadAll ReadDir => os.ReadDir ReadFile => os.ReadFile TempDir => os.MkdirTemp TempFile => os.CreateTemp WriteFile => os.WriteFile Details: https://go.dev/doc/go1.16#ioutil Fixes: #3265 Signed-off-by: bin <bin@hyper.sh>
1843 lines
42 KiB
Go
1843 lines
42 KiB
Go
// Copyright (c) 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package katatestutils
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
|
|
semver "github.com/blang/semver/v4"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
const (
|
|
invalidOperator = 1234
|
|
|
|
skipUnknownDistroName = "skipping test as cannot determine distro name"
|
|
)
|
|
|
|
// nolint: govet
|
|
type testDataUID struct {
|
|
uid int
|
|
op Operator
|
|
c Constraints
|
|
}
|
|
|
|
// nolint: govet
|
|
type testDataDistro struct {
|
|
distro string
|
|
op Operator
|
|
c Constraints
|
|
}
|
|
|
|
var distros = []string{
|
|
"centos",
|
|
"clear-linux-os",
|
|
"fedora",
|
|
"opensuse",
|
|
"rhel",
|
|
"sles",
|
|
"ubuntu",
|
|
}
|
|
|
|
var thisUID = os.Getuid()
|
|
var rootUID = 0
|
|
|
|
// name and version of current distro and kernel version of system tests are
|
|
// running on
|
|
var distroName string
|
|
var distroVersion string
|
|
var kernelVersion string
|
|
|
|
// error saved when attempting to determine distro name+version and kernel
|
|
// version.
|
|
var getDistroErr error
|
|
var getKernelErr error
|
|
|
|
// true if running as root
|
|
var root = thisUID == rootUID
|
|
|
|
var uidEqualsRootData = testDataUID{
|
|
uid: rootUID,
|
|
op: eqOperator,
|
|
c: Constraints{
|
|
Operator: eqOperator,
|
|
UID: rootUID,
|
|
UIDSet: true,
|
|
},
|
|
}
|
|
|
|
var uidNotEqualsRootData = testDataUID{
|
|
uid: rootUID,
|
|
op: neOperator,
|
|
c: Constraints{
|
|
Operator: neOperator,
|
|
UID: rootUID,
|
|
UIDSet: true,
|
|
},
|
|
}
|
|
|
|
var distroEqualsCurrentData testDataDistro
|
|
var distroNotEqualsCurrentData testDataDistro
|
|
|
|
func init() {
|
|
distroName, distroVersion, getDistroErr = testGetDistro()
|
|
kernelVersion, getKernelErr = testGetKernelVersion()
|
|
|
|
distroEqualsCurrentData = testDataDistro{
|
|
distro: distroName,
|
|
op: eqOperator,
|
|
c: Constraints{
|
|
DistroName: distroName,
|
|
Operator: eqOperator,
|
|
},
|
|
}
|
|
|
|
distroNotEqualsCurrentData = testDataDistro{
|
|
distro: distroName,
|
|
op: neOperator,
|
|
c: Constraints{
|
|
DistroName: distroName,
|
|
Operator: neOperator,
|
|
},
|
|
}
|
|
}
|
|
|
|
func fileExists(path string) bool {
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// getAnotherDistro returns a distro name not equal to the one specified.
|
|
func getAnotherDistro(distro string) string {
|
|
for _, d := range distros {
|
|
if d != distro {
|
|
return d
|
|
}
|
|
}
|
|
|
|
panic(fmt.Sprintf("failed to find a distro different to %s", distro))
|
|
}
|
|
|
|
func checkUIDConstraints(assert *assert.Assertions, a, b Constraints, desc string) {
|
|
msg := fmt.Sprintf("%s: a: %+v, b: %+v", desc, a, b)
|
|
|
|
assert.Equal(a.UID, b.UID, msg)
|
|
assert.Equal(a.Operator, b.Operator, msg)
|
|
assert.Equal(a.UIDSet, b.UIDSet, msg)
|
|
}
|
|
|
|
func checkDistroConstraints(assert *assert.Assertions, a, b Constraints, desc string) {
|
|
msg := fmt.Sprintf("%s: a: %+v, b: %+v", desc, a, b)
|
|
|
|
assert.Equal(a.DistroName, b.DistroName, msg)
|
|
assert.Equal(a.Operator, b.Operator, msg)
|
|
}
|
|
|
|
func checkKernelConstraint(assert *assert.Assertions, f Constraint, version string, op Operator, msg string) {
|
|
c := Constraints{}
|
|
|
|
f(&c)
|
|
|
|
assert.Equal(c.KernelVersion, version, msg)
|
|
assert.Equal(c.Operator, op, msg)
|
|
}
|
|
|
|
// runCommand runs a command and returns its output
|
|
func runCommand(args ...string) ([]string, error) {
|
|
cmd := exec.Command(args[0], args[1:]...)
|
|
bytes, err := cmd.Output()
|
|
if err != nil {
|
|
return []string{}, err
|
|
}
|
|
|
|
output := strings.Split(string(bytes), "\n")
|
|
|
|
return output, nil
|
|
}
|
|
|
|
// semverBumpVersion takes an existing semantic version and increments one or
|
|
// more parts of it, returning the new version number as a string.
|
|
func semverBumpVersion(ver semver.Version, bumpMajor, bumpMinor, bumpPatch bool) (string, error) {
|
|
if bumpMajor {
|
|
err := ver.IncrementMajor()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
if bumpMinor {
|
|
err := ver.IncrementMinor()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
if bumpPatch {
|
|
err := ver.IncrementPatch()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return ver.String(), nil
|
|
}
|
|
|
|
// changeVersion modifies the specified version and returns the
|
|
// string representation. If decrement is true the returned version is smaller
|
|
// than the specified version, else it is larger.
|
|
func changeVersion(version string, decrement bool) (string, error) {
|
|
operand := int64(1)
|
|
|
|
if decrement {
|
|
operand = -1
|
|
}
|
|
|
|
// Is it an integer?
|
|
intResult, err := strconv.ParseUint(version, 10, 0)
|
|
if err == nil {
|
|
if intResult == 0 && decrement {
|
|
return "", fmt.Errorf("cannot decrement integer version with value zero")
|
|
}
|
|
|
|
return fmt.Sprintf("%d", uint64(int64(intResult)+operand)), nil
|
|
}
|
|
|
|
// Is it a float?
|
|
floatResult, err := strconv.ParseFloat(version, 32)
|
|
if err == nil {
|
|
if int(floatResult) == 0 && decrement {
|
|
return "", fmt.Errorf("cannot decrement integer part of floating point version with value zero: %v", version)
|
|
}
|
|
|
|
return fmt.Sprintf("%f", floatResult+float64(operand)), nil
|
|
}
|
|
|
|
// Not an int nor a float, so it must be a semantic version
|
|
ver, err := semver.Make(version)
|
|
if err != nil {
|
|
// but if not, bail as we've run out of options
|
|
return "", err
|
|
}
|
|
|
|
if decrement {
|
|
// the semver package only provides increment operations, so
|
|
// handle decrement ourselves.
|
|
major := ver.Major
|
|
|
|
if major == 0 {
|
|
return "", fmt.Errorf("cannot decrement semver with zero major version: %+v", version)
|
|
}
|
|
|
|
major--
|
|
|
|
ver.Major = major
|
|
} else {
|
|
err = ver.IncrementMajor()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
return ver.String(), nil
|
|
}
|
|
|
|
func incrementVersion(version string) (string, error) {
|
|
return changeVersion(version, false)
|
|
}
|
|
|
|
func decrementVersion(version string) (string, error) {
|
|
return changeVersion(version, true)
|
|
}
|
|
|
|
// testGetDistro is an alternative implementation of getDistroDetails() used
|
|
// for testing.
|
|
func testGetDistro() (name, version string, err error) {
|
|
files := []string{"/etc/os-release", "/usr/lib/os-release"}
|
|
|
|
for _, file := range files {
|
|
if !fileExists(file) {
|
|
continue
|
|
}
|
|
|
|
output, err := runCommand("grep", "^ID=", file)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
line := output[0]
|
|
fields := strings.Split(line, "=")
|
|
if name == "" {
|
|
name = strings.Trim(fields[1], `"`)
|
|
name = strings.ToLower(name)
|
|
}
|
|
|
|
output, err = runCommand("grep", "^VERSION_ID=", file)
|
|
if err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
line = output[0]
|
|
fields = strings.Split(line, "=")
|
|
if version == "" {
|
|
version = strings.Trim(fields[1], `"`)
|
|
version = strings.ToLower(version)
|
|
}
|
|
}
|
|
|
|
if name != "" && version != "" {
|
|
return name, version, nil
|
|
}
|
|
|
|
if name == "" {
|
|
return "", "", errUnknownDistroName
|
|
}
|
|
|
|
if version == "" {
|
|
return "", "", errUnknownDistroVersion
|
|
}
|
|
|
|
return "", "", errors.New("BUG: something bad happened")
|
|
}
|
|
|
|
func testGetKernelVersion() (version string, err error) {
|
|
const file = "/proc/version"
|
|
|
|
bytes, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
line := string(bytes)
|
|
fields := strings.Fields(line)
|
|
|
|
const minFields = 3
|
|
|
|
count := len(fields)
|
|
|
|
if count < minFields {
|
|
return "", fmt.Errorf("expected atleast %d fields in file %q, got %d",
|
|
minFields, file, count)
|
|
}
|
|
|
|
version = fixKernelVersion(fields[2])
|
|
|
|
return version, nil
|
|
}
|
|
|
|
func TestOperatorString(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
op Operator
|
|
value string
|
|
}
|
|
|
|
data := []testData{
|
|
{eqOperator, "=="},
|
|
{neOperator, "!="},
|
|
}
|
|
|
|
for i, d := range data {
|
|
value := d.op.String()
|
|
|
|
assert.Equal(value, d.value, "test[%d]: %+v", i, d)
|
|
}
|
|
}
|
|
|
|
func TestNewTestConstraint(t *testing.T) {
|
|
if getDistroErr != nil {
|
|
t.Skipf("skipping as unable to determine distro name/version: %v",
|
|
getDistroErr)
|
|
}
|
|
|
|
if getKernelErr != nil {
|
|
t.Skipf("skipping as unable to determine kernel version: %v",
|
|
getKernelErr)
|
|
}
|
|
|
|
assert := assert.New(t)
|
|
|
|
for i, debug := range []bool{true, false} {
|
|
c := NewTestConstraint(debug)
|
|
|
|
msg := fmt.Sprintf("test[%d]: debug: %v, constraint: %+v", i, debug, c)
|
|
|
|
assert.Equal(debug, c.Debug, msg)
|
|
|
|
assert.Equal(distroName, c.DistroName, msg)
|
|
assert.Equal(distroVersion, c.DistroVersion, msg)
|
|
assert.Equal(kernelVersion, c.KernelVersion, msg)
|
|
assert.Equal(thisUID, c.ActualEUID)
|
|
|
|
toCheck := []string{
|
|
distroName,
|
|
distroVersion,
|
|
kernelVersion,
|
|
c.DistroName,
|
|
c.DistroVersion,
|
|
c.KernelVersion,
|
|
}
|
|
|
|
for _, str := range toCheck {
|
|
assert.NotNil(str, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetFileContents(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
type testData struct {
|
|
contents string
|
|
}
|
|
|
|
data := []testData{
|
|
{""},
|
|
{" "},
|
|
{"\n"},
|
|
{"\n\n"},
|
|
{"\n\n\n"},
|
|
{"foo"},
|
|
{"foo\nbar"},
|
|
}
|
|
|
|
dir, err := os.MkdirTemp("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(dir)
|
|
|
|
file := filepath.Join(dir, "foo")
|
|
|
|
// file doesn't exist
|
|
_, err = getFileContents(file)
|
|
assert.Error(err)
|
|
|
|
for _, d := range data {
|
|
// create the file
|
|
err = os.WriteFile(file, []byte(d.contents), testFileMode)
|
|
assert.NoError(err)
|
|
defer os.Remove(file)
|
|
|
|
contents, err := getFileContents(file)
|
|
assert.NoError(err)
|
|
assert.Equal(contents, d.contents)
|
|
}
|
|
}
|
|
|
|
func TestGetDistroDetails(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
if getDistroErr == errUnknownDistroName {
|
|
t.Skip(skipUnknownDistroName)
|
|
}
|
|
|
|
assert.NoError(getDistroErr)
|
|
assert.NotNil(distroName)
|
|
assert.NotNil(distroVersion)
|
|
|
|
name, version, err := getDistroDetails()
|
|
assert.NoError(err)
|
|
assert.NotNil(name)
|
|
assert.NotNil(version)
|
|
|
|
assert.Equal(name, distroName)
|
|
assert.Equal(version, distroVersion)
|
|
}
|
|
|
|
func TestGetKernelVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
assert.NoError(getKernelErr)
|
|
assert.NotNil(kernelVersion)
|
|
|
|
version, err := getKernelVersion()
|
|
assert.NoError(err)
|
|
assert.NotNil(version)
|
|
|
|
assert.Equal(version, kernelVersion)
|
|
}
|
|
|
|
func TestConstraintHandleDistroName(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
distro string
|
|
op Operator
|
|
result Result
|
|
expectError bool
|
|
}
|
|
|
|
distroName, _, err := testGetDistro()
|
|
if err != nil && err == errUnknownDistroName {
|
|
t.Skip(skipUnknownDistroName)
|
|
}
|
|
|
|
// Look for the first distro that is not the same as the distro this
|
|
// test is currently running on.
|
|
differentDistro := getAnotherDistro(distroName)
|
|
|
|
data := []testData{
|
|
{"", eqOperator, Result{}, true},
|
|
{"", neOperator, Result{}, true},
|
|
{"", invalidOperator, Result{}, true},
|
|
{distroName, invalidOperator, Result{}, true},
|
|
{distroName, invalidOperator, Result{}, true},
|
|
|
|
{
|
|
distroName,
|
|
eqOperator,
|
|
Result{
|
|
Description: distroName,
|
|
Success: true,
|
|
},
|
|
false,
|
|
},
|
|
{
|
|
distroName,
|
|
neOperator,
|
|
Result{
|
|
Description: distroName,
|
|
Success: false,
|
|
},
|
|
false,
|
|
},
|
|
{
|
|
differentDistro,
|
|
eqOperator,
|
|
Result{
|
|
Description: differentDistro,
|
|
Success: false,
|
|
},
|
|
false,
|
|
},
|
|
|
|
{
|
|
differentDistro,
|
|
neOperator,
|
|
Result{
|
|
Description: differentDistro,
|
|
Success: true,
|
|
},
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for i, d := range data {
|
|
result, err := tc.handleDistroName(d.distro, d.op)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
|
|
}
|
|
|
|
assert.NoError(err, msg)
|
|
assert.Equal(result.Success, d.result.Success, msg)
|
|
assert.NotNil(result.Description, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConstraintHandleDistroVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
assert.NotNil(distroVersion)
|
|
|
|
// Generate a new distro version for testing purposes. Since we don't
|
|
// know the format of this particular distros versioning scheme, we
|
|
// need to calculate it.
|
|
higherVersion, err := incrementVersion(distroVersion)
|
|
assert.NoError(err)
|
|
assert.NotEqual(distroVersion, higherVersion)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
version string
|
|
op Operator
|
|
result Result
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
{"", eqOperator, Result{}, true},
|
|
{"", geOperator, Result{}, true},
|
|
{"", gtOperator, Result{}, true},
|
|
{"", leOperator, Result{}, true},
|
|
{"", ltOperator, Result{}, true},
|
|
{"", neOperator, Result{}, true},
|
|
|
|
{distroVersion, eqOperator, Result{Success: true}, false},
|
|
{higherVersion, eqOperator, Result{Success: false}, false},
|
|
|
|
{distroVersion, gtOperator, Result{Success: false}, false},
|
|
{higherVersion, gtOperator, Result{Success: false}, false},
|
|
|
|
{distroVersion, geOperator, Result{Success: true}, false},
|
|
{higherVersion, geOperator, Result{Success: false}, false},
|
|
|
|
{distroVersion, ltOperator, Result{Success: false}, false},
|
|
{higherVersion, ltOperator, Result{Success: true}, false},
|
|
|
|
{distroVersion, leOperator, Result{Success: true}, false},
|
|
{higherVersion, leOperator, Result{Success: true}, false},
|
|
|
|
{distroVersion, neOperator, Result{Success: false}, false},
|
|
{higherVersion, neOperator, Result{Success: true}, false},
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for i, d := range data {
|
|
result, err := tc.handleDistroVersion(d.version, d.op)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
assert.Equal(d.result.Success, result.Success, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConstraintHandleVersionType(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
versionName string
|
|
currentVersion string
|
|
op Operator
|
|
newVersion string
|
|
result Result
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
//----------
|
|
|
|
{"", "", eqOperator, "", Result{}, true},
|
|
|
|
{"name", "foo", eqOperator, "", Result{}, true},
|
|
{"name", "", eqOperator, "foo", Result{}, true},
|
|
{"name", "1", eqOperator, "", Result{}, true},
|
|
{"name", "", eqOperator, "1", Result{}, true},
|
|
|
|
{"name", "1", eqOperator, "1", Result{Success: true}, false},
|
|
{"name", "1", eqOperator, "2", Result{Success: false}, false},
|
|
{"name", "2", eqOperator, "1", Result{Success: false}, false},
|
|
|
|
{"name", "3.141", eqOperator, "3.141", Result{Success: true}, false},
|
|
{"name", "4.141", eqOperator, "3.141", Result{Success: false}, false},
|
|
{"name", "3.141", eqOperator, "4.141", Result{Success: false}, false},
|
|
|
|
{"name", "3.1.4-1", eqOperator, "3.1.4-1", Result{Success: true}, false},
|
|
{"name", "3.1.4-1", eqOperator, "4.1.4-1", Result{Success: false}, false},
|
|
{"name", "4.1.4-1", eqOperator, "3.1.4-1", Result{Success: false}, false},
|
|
|
|
//----------
|
|
|
|
{"", "", ltOperator, "", Result{}, true},
|
|
|
|
{"name", "foo", ltOperator, "", Result{}, true},
|
|
{"name", "", ltOperator, "foo", Result{}, true},
|
|
{"name", "1", ltOperator, "", Result{}, true},
|
|
{"name", "", ltOperator, "1", Result{}, true},
|
|
|
|
{"name", "1", ltOperator, "2", Result{Success: true}, false},
|
|
{"name", "2", ltOperator, "1", Result{Success: false}, false},
|
|
{"name", "1", ltOperator, "1", Result{Success: false}, false},
|
|
|
|
{"name", "1.3", ltOperator, "2.3", Result{Success: true}, false},
|
|
{"name", "2.3", ltOperator, "1.3", Result{Success: false}, false},
|
|
{"name", "1.3", ltOperator, "1.3", Result{Success: false}, false},
|
|
|
|
{"name", "3.1.4", ltOperator, "3.1.5", Result{Success: true}, false},
|
|
{"name", "3.1.5", ltOperator, "3.1.4", Result{Success: false}, false},
|
|
{"name", "3.1.4", ltOperator, "3.1.4", Result{Success: false}, false},
|
|
|
|
//----------
|
|
|
|
{"", "", leOperator, "", Result{}, true},
|
|
|
|
{"name", "foo", leOperator, "", Result{}, true},
|
|
{"name", "", leOperator, "foo", Result{}, true},
|
|
{"name", "1", leOperator, "", Result{}, true},
|
|
{"name", "", leOperator, "1", Result{}, true},
|
|
|
|
{"name", "1", leOperator, "2", Result{Success: true}, false},
|
|
{"name", "2", leOperator, "1", Result{Success: false}, false},
|
|
{"name", "1", leOperator, "1", Result{Success: true}, false},
|
|
|
|
{"name", "1.3", leOperator, "2.3", Result{Success: true}, false},
|
|
{"name", "2.3", leOperator, "1.3", Result{Success: false}, false},
|
|
{"name", "1.3", leOperator, "1.3", Result{Success: true}, false},
|
|
|
|
{"name", "3.1.4", leOperator, "3.1.5", Result{Success: true}, false},
|
|
{"name", "3.1.5", leOperator, "3.1.4", Result{Success: false}, false},
|
|
{"name", "3.1.4", leOperator, "3.1.4", Result{Success: true}, false},
|
|
|
|
//----------
|
|
|
|
{"", "", gtOperator, "", Result{}, true},
|
|
|
|
{"name", "foo", gtOperator, "", Result{}, true},
|
|
{"name", "", gtOperator, "foo", Result{}, true},
|
|
{"name", "1", gtOperator, "", Result{}, true},
|
|
{"name", "", gtOperator, "1", Result{}, true},
|
|
|
|
{"name", "1", gtOperator, "2", Result{Success: false}, false},
|
|
{"name", "2", gtOperator, "1", Result{Success: true}, false},
|
|
{"name", "1", gtOperator, "1", Result{Success: false}, false},
|
|
|
|
{"name", "1.3", gtOperator, "2.3", Result{Success: false}, false},
|
|
{"name", "2.3", gtOperator, "1.3", Result{Success: true}, false},
|
|
{"name", "1.3", gtOperator, "1.3", Result{Success: false}, false},
|
|
|
|
{"name", "3.1.4", gtOperator, "3.1.5", Result{Success: false}, false},
|
|
{"name", "3.1.5", gtOperator, "3.1.4", Result{Success: true}, false},
|
|
{"name", "3.1.4", gtOperator, "3.1.4", Result{Success: false}, false},
|
|
|
|
//----------
|
|
|
|
{"", "", geOperator, "", Result{}, true},
|
|
|
|
{"name", "foo", geOperator, "", Result{}, true},
|
|
{"name", "", geOperator, "foo", Result{}, true},
|
|
{"name", "1", geOperator, "", Result{}, true},
|
|
{"name", "", geOperator, "1", Result{}, true},
|
|
|
|
{"name", "1", geOperator, "2", Result{Success: false}, false},
|
|
{"name", "2", geOperator, "1", Result{Success: true}, false},
|
|
{"name", "1", geOperator, "1", Result{Success: true}, false},
|
|
|
|
{"name", "1.3", geOperator, "2.3", Result{Success: false}, false},
|
|
{"name", "2.3", geOperator, "1.3", Result{Success: true}, false},
|
|
{"name", "1.3", geOperator, "1.3", Result{Success: true}, false},
|
|
|
|
{"name", "3.1.4", geOperator, "3.1.5", Result{Success: false}, false},
|
|
{"name", "3.1.5", geOperator, "3.1.4", Result{Success: true}, false},
|
|
{"name", "3.1.4", geOperator, "3.1.4", Result{Success: true}, false},
|
|
|
|
//----------
|
|
|
|
{"", "", neOperator, "", Result{}, true},
|
|
|
|
{"name", "foo", neOperator, "", Result{}, true},
|
|
{"name", "", neOperator, "foo", Result{}, true},
|
|
{"name", "1", neOperator, "", Result{}, true},
|
|
{"name", "", neOperator, "1", Result{}, true},
|
|
|
|
{"name", "1", neOperator, "2", Result{Success: true}, false},
|
|
{"name", "2", neOperator, "1", Result{Success: true}, false},
|
|
{"name", "1", neOperator, "1", Result{Success: false}, false},
|
|
|
|
{"name", "1.3", neOperator, "2.3", Result{Success: true}, false},
|
|
{"name", "2.3", neOperator, "1.3", Result{Success: true}, false},
|
|
{"name", "1.3", neOperator, "1.3", Result{Success: false}, false},
|
|
|
|
{"name", "3.1.4", neOperator, "3.1.5", Result{Success: true}, false},
|
|
{"name", "3.1.5", neOperator, "3.1.4", Result{Success: true}, false},
|
|
{"name", "3.1.4", neOperator, "3.1.4", Result{Success: false}, false},
|
|
|
|
//----------
|
|
}
|
|
|
|
for i, d := range data {
|
|
result, err := handleVersionType(d.versionName, d.currentVersion, d.op, d.newVersion)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
assert.Equal(d.result.Success, result.Success, msg)
|
|
}
|
|
}
|
|
|
|
func TestConstraintHandleKernelVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
ver, err := semver.Make(kernelVersion)
|
|
assert.NoError(err)
|
|
|
|
newerMajor, err := semverBumpVersion(ver, true, false, false)
|
|
assert.NoError(err)
|
|
|
|
newerMinor, err := semverBumpVersion(ver, false, true, false)
|
|
assert.NoError(err)
|
|
|
|
newerPatch, err := semverBumpVersion(ver, false, false, true)
|
|
assert.NoError(err)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
version string
|
|
op Operator
|
|
result Result
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
{"", eqOperator, Result{}, true},
|
|
{"", geOperator, Result{}, true},
|
|
{"", gtOperator, Result{}, true},
|
|
{"", leOperator, Result{}, true},
|
|
{"", ltOperator, Result{}, true},
|
|
{"", neOperator, Result{}, true},
|
|
|
|
{kernelVersion, eqOperator, Result{Success: true}, false},
|
|
{kernelVersion, neOperator, Result{Success: false}, false},
|
|
|
|
{newerMajor, eqOperator, Result{Success: false}, false},
|
|
{newerMajor, geOperator, Result{Success: false}, false},
|
|
{newerMajor, gtOperator, Result{Success: false}, false},
|
|
{newerMajor, ltOperator, Result{Success: true}, false},
|
|
{newerMajor, leOperator, Result{Success: true}, false},
|
|
{newerMajor, neOperator, Result{Success: true}, false},
|
|
|
|
{newerMinor, eqOperator, Result{Success: false}, false},
|
|
{newerMinor, geOperator, Result{Success: false}, false},
|
|
{newerMinor, gtOperator, Result{Success: false}, false},
|
|
{newerMinor, ltOperator, Result{Success: true}, false},
|
|
{newerMinor, leOperator, Result{Success: true}, false},
|
|
{newerMinor, neOperator, Result{Success: true}, false},
|
|
|
|
{newerPatch, eqOperator, Result{Success: false}, false},
|
|
{newerPatch, geOperator, Result{Success: false}, false},
|
|
{newerPatch, gtOperator, Result{Success: false}, false},
|
|
{newerPatch, ltOperator, Result{Success: true}, false},
|
|
{newerPatch, leOperator, Result{Success: true}, false},
|
|
{newerPatch, neOperator, Result{Success: true}, false},
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for i, d := range data {
|
|
result, err := tc.handleKernelVersion(d.version, d.op)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
assert.Equal(d.result.Success, result.Success, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConstraintHandleUID(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
uid int
|
|
op Operator
|
|
result Result
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
{-1, eqOperator, Result{}, true},
|
|
{-1, neOperator, Result{}, true},
|
|
{-2, eqOperator, Result{}, true},
|
|
{-2, neOperator, Result{}, true},
|
|
{rootUID, invalidOperator, Result{}, true},
|
|
{thisUID, invalidOperator, Result{}, true},
|
|
|
|
{rootUID, eqOperator, Result{Success: root}, false},
|
|
{rootUID, neOperator, Result{Success: !root}, false},
|
|
|
|
{thisUID, eqOperator, Result{Success: true}, false},
|
|
{thisUID, neOperator, Result{Success: false}, false},
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for i, d := range data {
|
|
result, err := tc.handleUID(d.uid, d.op)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
assert.NoError(err, msg)
|
|
assert.Equal(result.Success, d.result.Success, msg)
|
|
assert.NotNil(result.Description, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConstraintHandleResults(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
result Result
|
|
err error
|
|
}
|
|
|
|
data := []testData{
|
|
{Result{}, errors.New("foo")},
|
|
|
|
{Result{Success: true}, nil},
|
|
{Result{Success: false}, nil},
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for i, d := range data {
|
|
tc.Passed = nil
|
|
tc.Failed = nil
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v", i, d)
|
|
|
|
if d.err != nil {
|
|
assert.Panics(func() {
|
|
tc.handleResults(d.result, d.err)
|
|
}, msg)
|
|
continue
|
|
}
|
|
|
|
tc.handleResults(d.result, d.err)
|
|
|
|
passedLen := len(tc.Passed)
|
|
failedLen := len(tc.Failed)
|
|
|
|
var expectedPassedLen int
|
|
var expectedFailedLen int
|
|
|
|
if d.result.Success {
|
|
expectedPassedLen = 1
|
|
expectedFailedLen = 0
|
|
} else {
|
|
expectedPassedLen = 0
|
|
expectedFailedLen = 1
|
|
}
|
|
|
|
assert.Equal(passedLen, expectedPassedLen, msg)
|
|
assert.Equal(failedLen, expectedFailedLen, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNeedUID(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
data := []testDataUID{
|
|
uidEqualsRootData,
|
|
uidNotEqualsRootData,
|
|
{thisUID, eqOperator, Constraints{
|
|
Operator: eqOperator,
|
|
UID: thisUID,
|
|
UIDSet: true},
|
|
},
|
|
}
|
|
|
|
for i, d := range data {
|
|
c := Constraints{}
|
|
|
|
f := NeedUID(d.uid, d.op)
|
|
f(&c)
|
|
|
|
desc := fmt.Sprintf("test[%d]: %+v", i, d)
|
|
checkUIDConstraints(assert, c, d.c, desc)
|
|
}
|
|
}
|
|
|
|
func TestNeedRoot(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
c := Constraints{}
|
|
|
|
f := NeedRoot()
|
|
f(&c)
|
|
|
|
checkUIDConstraints(assert, c, uidEqualsRootData.c, "TestNeedRoot")
|
|
}
|
|
|
|
func TestNeedNonRoot(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
c := Constraints{}
|
|
|
|
f := NeedNonRoot()
|
|
f(&c)
|
|
|
|
checkUIDConstraints(assert, c, uidNotEqualsRootData.c, "TestNeedNonRoot")
|
|
}
|
|
|
|
func TestNeedDistroWithOp(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
if getDistroErr == errUnknownDistroName {
|
|
t.Skip(skipUnknownDistroName)
|
|
}
|
|
|
|
data := []testDataDistro{
|
|
distroEqualsCurrentData,
|
|
distroNotEqualsCurrentData,
|
|
|
|
// check name provided is lower-cased
|
|
{
|
|
strings.ToUpper(distroName),
|
|
eqOperator,
|
|
Constraints{
|
|
DistroName: distroName,
|
|
Operator: eqOperator,
|
|
},
|
|
},
|
|
}
|
|
|
|
for i, d := range data {
|
|
|
|
c := Constraints{}
|
|
|
|
f := NeedDistroWithOp(d.distro, d.op)
|
|
f(&c)
|
|
|
|
desc := fmt.Sprintf("test[%d]: %+v, constraints: %+v", i, d, c)
|
|
checkDistroConstraints(assert, d.c, c, desc)
|
|
}
|
|
}
|
|
|
|
func TestNeedDistroEquals(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
c := Constraints{}
|
|
|
|
f := NeedDistroEquals(distroName)
|
|
f(&c)
|
|
|
|
checkDistroConstraints(assert, c, distroEqualsCurrentData.c, "TestNeedDistroEquals")
|
|
}
|
|
|
|
func TestNeedDistroNotEquals(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
c := Constraints{}
|
|
|
|
f := NeedDistroNotEquals(distroName)
|
|
f(&c)
|
|
|
|
checkDistroConstraints(assert, c, distroNotEqualsCurrentData.c, "TestNeedDistroNotEquals")
|
|
}
|
|
|
|
func TestWithIssue(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
c := Constraints{}
|
|
|
|
issue := "issue"
|
|
|
|
f := WithIssue(issue)
|
|
f(&c)
|
|
|
|
assert.Equal(c.Issue, issue)
|
|
}
|
|
|
|
func TestNeedKernelVersionWithOp(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
type testData struct {
|
|
version string
|
|
op Operator
|
|
}
|
|
|
|
version := "version"
|
|
|
|
data := []testData{
|
|
{version, eqOperator},
|
|
{version, geOperator},
|
|
{version, gtOperator},
|
|
{version, leOperator},
|
|
{version, ltOperator},
|
|
{version, neOperator},
|
|
}
|
|
|
|
for i, d := range data {
|
|
msg := fmt.Sprintf("test[%d]: %+v", i, d)
|
|
|
|
c := NeedKernelVersionWithOp(d.version, d.op)
|
|
|
|
checkKernelConstraint(assert, c, d.version, d.op, msg)
|
|
}
|
|
}
|
|
|
|
func TestNeedKernelVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
version := "version"
|
|
f := NeedKernelVersion(version)
|
|
checkKernelConstraint(assert, f, version, eqOperator, "TestNeedKernelVersion")
|
|
}
|
|
|
|
func TestNeedKernelVersionEquals(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
version := "version"
|
|
f := NeedKernelVersionEquals(version)
|
|
checkKernelConstraint(assert, f, version, eqOperator, "TestNeedKernelVersionEquals")
|
|
}
|
|
|
|
func TestNeedKernelVersionLE(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
version := "version"
|
|
f := NeedKernelVersionLE(version)
|
|
checkKernelConstraint(assert, f, version, leOperator, "TestNeedKernelVersionLE")
|
|
}
|
|
|
|
func TestNeedKernelVersionLT(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
version := "version"
|
|
f := NeedKernelVersionLT(version)
|
|
checkKernelConstraint(assert, f, version, ltOperator, "TestNeedKernelVersionLT")
|
|
}
|
|
|
|
func TestNeedKernelVersionGE(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
version := "version"
|
|
f := NeedKernelVersionGE(version)
|
|
checkKernelConstraint(assert, f, version, geOperator, "TestNeedKernelVersionGE")
|
|
}
|
|
|
|
func TestNeedKernelVersionGT(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
version := "version"
|
|
f := NeedKernelVersionGT(version)
|
|
checkKernelConstraint(assert, f, version, gtOperator, "TestNeedKernelVersionGT")
|
|
}
|
|
|
|
func TestConstraintNotValid(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
// Ensure no params is an error
|
|
assert.Panics(func() {
|
|
_ = tc.NotValid()
|
|
})
|
|
|
|
// Test specification of a single constraint
|
|
if root {
|
|
result := tc.NotValid(NeedRoot())
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedNonRoot())
|
|
assert.True(result)
|
|
} else {
|
|
result := tc.NotValid(NeedRoot())
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedNonRoot())
|
|
assert.False(result)
|
|
}
|
|
|
|
// Now test specification of multiple constraints
|
|
if root {
|
|
result := tc.NotValid(NeedRoot(), NeedDistro(distroName))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedNonRoot(), NeedDistro(distroName))
|
|
assert.True(result)
|
|
} else {
|
|
result := tc.NotValid(NeedRoot(), NeedDistro(distroName))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedNonRoot(), NeedDistro(distroName))
|
|
assert.False(result)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestConstraintNotValidKernelVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
assert.NotNil(kernelVersion)
|
|
|
|
// Generate new kernel versions for testing purposes based on the
|
|
// current kernel version.
|
|
higherVersion, err := incrementVersion(kernelVersion)
|
|
assert.NoError(err)
|
|
assert.NotEqual(kernelVersion, higherVersion)
|
|
|
|
lowerVersion, err := decrementVersion(kernelVersion)
|
|
assert.NoError(err)
|
|
assert.NotEqual(kernelVersion, lowerVersion)
|
|
|
|
// Antique kernel version numbers.
|
|
//
|
|
// Note: Not all are actually real kernel releases - we're just trying
|
|
// to do a thorough test.
|
|
lowKernelVersions := []string{
|
|
"0.0.0",
|
|
"0.0.1",
|
|
"1.0.0",
|
|
"1.0.6-1.1.0",
|
|
"2.0.0",
|
|
"2.6.0",
|
|
lowerVersion,
|
|
}
|
|
|
|
// Host kernel is expected to be newer than all the low kernel versions
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for _, ver := range lowKernelVersions {
|
|
result := tc.NotValid(NeedKernelVersionEquals(ver))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionLE(ver))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionLT(ver))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionGT(ver))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionGE(ver))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionNotEquals(ver))
|
|
assert.False(result)
|
|
}
|
|
}
|
|
|
|
// Ridiculously high kernel version numbers. The host kernel is
|
|
// expected to never reach these values.
|
|
highKernelVersions := []string{
|
|
higherVersion,
|
|
"999.0.0",
|
|
"999.0.999",
|
|
"999.999.999",
|
|
"1024.0.0",
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
for _, ver := range highKernelVersions {
|
|
result := tc.NotValid(NeedKernelVersionEquals(ver))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionGE(ver))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionGT(ver))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionLE(ver))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionLT(ver))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedKernelVersionNotEquals(ver))
|
|
assert.False(result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConstraintNotValidDistroVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
assert.NotNil(distroVersion)
|
|
|
|
// Generate new distro versions for testing purposes based on the
|
|
// current kernel version.
|
|
higherVersion, err := incrementVersion(distroVersion)
|
|
assert.NoError(err)
|
|
assert.NotEqual(distroVersion, higherVersion)
|
|
|
|
lowerVersion, err := decrementVersion(distroVersion)
|
|
assert.NoError(err)
|
|
assert.NotEqual(distroVersion, lowerVersion)
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
result := tc.NotValid(NeedDistroVersionEquals(higherVersion))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionEquals(distroVersion))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionLE(higherVersion))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionLE(distroVersion))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionLT(higherVersion))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionLT(distroVersion))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionGE(higherVersion))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionGE(distroVersion))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionGT(higherVersion))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionGT(distroVersion))
|
|
assert.True(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionNotEquals(higherVersion))
|
|
assert.False(result)
|
|
|
|
result = tc.NotValid(NeedDistroVersionNotEquals(distroVersion))
|
|
assert.True(result)
|
|
}
|
|
}
|
|
|
|
func TestConstraintConstraintValid(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
fn Constraint
|
|
valid bool
|
|
expected TestConstraint
|
|
}
|
|
|
|
issue := "issue"
|
|
|
|
data := []testData{
|
|
{
|
|
WithIssue(issue),
|
|
true,
|
|
TestConstraint{Issue: issue},
|
|
},
|
|
|
|
{
|
|
NeedDistroWithOp(distroName, eqOperator),
|
|
true,
|
|
TestConstraint{
|
|
Passed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
NeedDistroWithOp(distroName, neOperator),
|
|
false,
|
|
TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
NeedDistroWithOp(getAnotherDistro(distroName), eqOperator),
|
|
false,
|
|
TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
NeedDistroWithOp(getAnotherDistro(distroName), neOperator),
|
|
true,
|
|
TestConstraint{
|
|
Failed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
},
|
|
|
|
{
|
|
NeedDistroEquals(distroName),
|
|
true,
|
|
TestConstraint{
|
|
Passed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
NeedDistroEquals(getAnotherDistro(distroName)),
|
|
false,
|
|
TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
},
|
|
|
|
{
|
|
NeedDistroNotEquals(getAnotherDistro(distroName)),
|
|
true,
|
|
TestConstraint{
|
|
Passed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
NeedDistroNotEquals(distroName),
|
|
false,
|
|
TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
},
|
|
|
|
{
|
|
NeedDistro(distroName),
|
|
true,
|
|
TestConstraint{
|
|
Passed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
NeedDistro(getAnotherDistro(distroName)),
|
|
false,
|
|
TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
if root {
|
|
td := testData{
|
|
fn: NeedRoot(),
|
|
valid: true,
|
|
expected: TestConstraint{
|
|
Passed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
}
|
|
|
|
data = append(data, td)
|
|
|
|
td = testData{
|
|
fn: NeedNonRoot(),
|
|
valid: false,
|
|
expected: TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
}
|
|
|
|
data = append(data, td)
|
|
} else {
|
|
td := testData{
|
|
fn: NeedRoot(),
|
|
valid: false,
|
|
expected: TestConstraint{
|
|
Failed: []Result{
|
|
{Success: false},
|
|
},
|
|
},
|
|
}
|
|
|
|
data = append(data, td)
|
|
|
|
td = testData{
|
|
fn: NeedNonRoot(),
|
|
valid: true,
|
|
expected: TestConstraint{
|
|
Passed: []Result{
|
|
{Success: true},
|
|
},
|
|
},
|
|
}
|
|
|
|
data = append(data, td)
|
|
}
|
|
|
|
for _, debug := range []bool{true, false} {
|
|
for i, d := range data {
|
|
tc := NewTestConstraint(debug)
|
|
|
|
result := tc.constraintValid(d.fn)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, result: %v", i, d, result)
|
|
|
|
if d.expected.Issue != "" {
|
|
assert.Equal(tc.Issue, d.expected.Issue, msg)
|
|
}
|
|
|
|
if d.valid {
|
|
assert.True(result, msg)
|
|
|
|
if len(d.expected.Passed) != 0 {
|
|
assert.Equal(d.expected.Passed[0].Success, tc.Passed[0].Success, msg)
|
|
}
|
|
} else {
|
|
assert.False(result, msg)
|
|
|
|
if len(d.expected.Failed) != 0 {
|
|
assert.Equal(d.expected.Failed[0].Success, tc.Failed[0].Success, msg)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvalIntVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
currentVer string
|
|
op Operator
|
|
newVer string
|
|
expectSuccess bool
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
//----------
|
|
|
|
{"", eqOperator, "", false, true},
|
|
{"", eqOperator, "1", false, true},
|
|
{"1", eqOperator, "", false, true},
|
|
|
|
{"foo", eqOperator, "", false, true},
|
|
{"", eqOperator, "foo", false, true},
|
|
{"foo", eqOperator, "1", false, true},
|
|
{"1", eqOperator, "foo", false, true},
|
|
|
|
{"1", eqOperator, "1", true, false},
|
|
{"1", eqOperator, "2", false, false},
|
|
|
|
//----------
|
|
|
|
{"", geOperator, "", false, true},
|
|
{"foo", geOperator, "", false, true},
|
|
{"", geOperator, "foo", false, true},
|
|
{"1", geOperator, "", false, true},
|
|
{"", geOperator, "1", false, true},
|
|
|
|
{"1", geOperator, "2", false, false},
|
|
{"2", geOperator, "1", true, false},
|
|
{"2", geOperator, "2", true, false},
|
|
|
|
//----------
|
|
|
|
{"", gtOperator, "", false, true},
|
|
{"foo", gtOperator, "", false, true},
|
|
{"", gtOperator, "foo", false, true},
|
|
{"1", gtOperator, "", false, true},
|
|
{"", gtOperator, "1", false, true},
|
|
|
|
{"2", gtOperator, "1", true, false},
|
|
{"1", gtOperator, "2", false, false},
|
|
{"1", gtOperator, "1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", leOperator, "", false, true},
|
|
{"foo", leOperator, "", false, true},
|
|
{"", leOperator, "foo", false, true},
|
|
{"1", leOperator, "", false, true},
|
|
{"", leOperator, "1", false, true},
|
|
|
|
{"2", leOperator, "1", false, false},
|
|
{"1", leOperator, "2", true, false},
|
|
{"1", leOperator, "1", true, false},
|
|
|
|
//----------
|
|
|
|
{"", ltOperator, "", false, true},
|
|
{"foo", ltOperator, "", false, true},
|
|
{"", ltOperator, "foo", false, true},
|
|
{"1", ltOperator, "", false, true},
|
|
{"", ltOperator, "1", false, true},
|
|
|
|
{"1", ltOperator, "2", true, false},
|
|
{"2", ltOperator, "1", false, false},
|
|
{"1", ltOperator, "1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", neOperator, "", false, true},
|
|
{"foo", neOperator, "", false, true},
|
|
{"", neOperator, "foo", false, true},
|
|
{"1", neOperator, "", false, true},
|
|
{"", neOperator, "1", false, true},
|
|
|
|
{"2", neOperator, "2", false, false},
|
|
{"1", neOperator, "2", true, false},
|
|
{"2", neOperator, "1", true, false},
|
|
}
|
|
|
|
for i, d := range data {
|
|
success, err := evalIntVersion(d.currentVer, d.op, d.newVer)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, success: %v", i, d, success)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
if d.expectSuccess {
|
|
assert.True(success, msg)
|
|
} else {
|
|
assert.False(success, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvalFloatVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
currentVer string
|
|
op Operator
|
|
newVer string
|
|
expectSuccess bool
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
//----------
|
|
|
|
{"", eqOperator, "", false, true},
|
|
{"foo", eqOperator, "", false, true},
|
|
{"", eqOperator, "foo", false, true},
|
|
{"foo", eqOperator, "1", false, true},
|
|
{"1", eqOperator, "foo", false, true},
|
|
|
|
{"1", eqOperator, "1", true, false},
|
|
{"1", eqOperator, "2", false, false},
|
|
|
|
{"1.1", eqOperator, "1.1", true, false},
|
|
{"1.1", eqOperator, "2.1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", geOperator, "", false, true},
|
|
{"foo", geOperator, "", false, true},
|
|
{"", geOperator, "foo", false, true},
|
|
|
|
{"1", geOperator, "2", false, false},
|
|
{"2", geOperator, "1", true, false},
|
|
{"2", geOperator, "2", true, false},
|
|
|
|
{"1.1", geOperator, "2.1", false, false},
|
|
{"2.1", geOperator, "1.1", true, false},
|
|
{"2.1", geOperator, "2.1", true, false},
|
|
|
|
//----------
|
|
|
|
{"", gtOperator, "", false, true},
|
|
{"foo", gtOperator, "", false, true},
|
|
{"", gtOperator, "foo", false, true},
|
|
|
|
{"2", gtOperator, "1", true, false},
|
|
{"1", gtOperator, "2", false, false},
|
|
{"1", gtOperator, "1", false, false},
|
|
|
|
{"2.1", gtOperator, "1.1", true, false},
|
|
{"1.1", gtOperator, "2.1", false, false},
|
|
{"1.1", gtOperator, "1.1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", leOperator, "", false, true},
|
|
{"foo", leOperator, "", false, true},
|
|
{"", leOperator, "foo", false, true},
|
|
|
|
{"2", leOperator, "1", false, false},
|
|
{"1", leOperator, "2", true, false},
|
|
{"1", leOperator, "1", true, false},
|
|
|
|
{"2.1", leOperator, "1.1", false, false},
|
|
{"1.1", leOperator, "2.1", true, false},
|
|
{"1.1", leOperator, "1.1", true, false},
|
|
|
|
//----------
|
|
|
|
{"", ltOperator, "", false, true},
|
|
{"foo", ltOperator, "", false, true},
|
|
{"", ltOperator, "foo", false, true},
|
|
|
|
{"1", ltOperator, "2", true, false},
|
|
{"2", ltOperator, "1", false, false},
|
|
{"1", ltOperator, "1", false, false},
|
|
|
|
{"1.1", ltOperator, "2.1", true, false},
|
|
{"2.1", ltOperator, "1.1", false, false},
|
|
{"1.1", ltOperator, "1.1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", neOperator, "", false, true},
|
|
{"foo", neOperator, "", false, true},
|
|
{"", neOperator, "foo", false, true},
|
|
|
|
{"2", neOperator, "2", false, false},
|
|
{"1", neOperator, "2", true, false},
|
|
{"2", neOperator, "1", true, false},
|
|
|
|
{"2.1", neOperator, "2.1", false, false},
|
|
{"1.1", neOperator, "2.1", true, false},
|
|
{"2.1", neOperator, "1.1", true, false},
|
|
}
|
|
|
|
for i, d := range data {
|
|
success, err := evalFloatVersion(d.currentVer, d.op, d.newVer)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, success: %v", i, d, success)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
if d.expectSuccess {
|
|
assert.True(success, msg)
|
|
} else {
|
|
assert.False(success, msg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEvalSemverVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
// nolint: govet
|
|
type testData struct {
|
|
currentVer string
|
|
op Operator
|
|
newVer string
|
|
expectSuccess bool
|
|
expectError bool
|
|
}
|
|
|
|
data := []testData{
|
|
//----------
|
|
|
|
{"", eqOperator, "", false, true},
|
|
{"foo", eqOperator, "", false, true},
|
|
{"", eqOperator, "foo", false, true},
|
|
{"foo", eqOperator, "1", false, true},
|
|
{"1", eqOperator, "foo", false, true},
|
|
|
|
{"1.1.1", eqOperator, "1.1.1", true, false},
|
|
{"1.1.1", eqOperator, "2.2.2", false, false},
|
|
|
|
//----------
|
|
|
|
{"", geOperator, "", false, true},
|
|
{"foo", geOperator, "", false, true},
|
|
{"", geOperator, "foo", false, true},
|
|
|
|
{"1.1.1", geOperator, "2.2.2", false, false},
|
|
{"2.2.2", geOperator, "1.1.1", true, false},
|
|
{"2.2.2", geOperator, "2.2.2", true, false},
|
|
|
|
//----------
|
|
|
|
{"", gtOperator, "", false, true},
|
|
{"foo", gtOperator, "", false, true},
|
|
{"", gtOperator, "foo", false, true},
|
|
|
|
{"2.2.2", gtOperator, "1.1.1", true, false},
|
|
{"1.1.1", gtOperator, "2.2.2", false, false},
|
|
{"1.1.1", gtOperator, "1.1.1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", leOperator, "", false, true},
|
|
{"foo", leOperator, "", false, true},
|
|
{"", leOperator, "foo", false, true},
|
|
|
|
{"2.2.2", leOperator, "1.1.1", false, false},
|
|
{"1.1.1", leOperator, "2.2.2", true, false},
|
|
{"1.1.1", leOperator, "1.1.1", true, false},
|
|
|
|
//----------
|
|
|
|
{"", ltOperator, "", false, true},
|
|
{"foo", ltOperator, "", false, true},
|
|
{"", ltOperator, "foo", false, true},
|
|
|
|
{"1.1.1", ltOperator, "2.2.2", true, false},
|
|
{"2.2.2", ltOperator, "1.1.1", false, false},
|
|
{"1.1.1", ltOperator, "1.1.1", false, false},
|
|
|
|
//----------
|
|
|
|
{"", neOperator, "", false, true},
|
|
{"foo", neOperator, "", false, true},
|
|
{"", neOperator, "foo", false, true},
|
|
|
|
{"2.2.2", neOperator, "2.2.2", false, false},
|
|
{"1.1.1", neOperator, "2.2.2", true, false},
|
|
{"2.2.2", neOperator, "1.1.1", true, false},
|
|
}
|
|
|
|
for i, d := range data {
|
|
success, err := evalSemverVersion(d.currentVer, d.op, d.newVer)
|
|
|
|
msg := fmt.Sprintf("test[%d]: %+v, success: %v", i, d, success)
|
|
|
|
if d.expectError {
|
|
assert.Error(err, msg)
|
|
continue
|
|
}
|
|
|
|
if d.expectSuccess {
|
|
assert.True(success, msg)
|
|
} else {
|
|
assert.False(success, msg)
|
|
}
|
|
}
|
|
}
|