gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/pkg/katatestutils/constraints_test.go (about)

     1  // Copyright (c) 2019 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package katatestutils
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"os/exec"
    14  	"path/filepath"
    15  	"strconv"
    16  	"strings"
    17  	"testing"
    18  
    19  	"github.com/blang/semver"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  const (
    24  	testFileMode    = os.FileMode(0640)
    25  	invalidOperator = 1234
    26  
    27  	skipUnknownDistroName = "skipping test as cannot determine distro name"
    28  )
    29  
    30  type testDataUID struct {
    31  	uid int
    32  	op  Operator
    33  	c   Constraints
    34  }
    35  
    36  type testDataDistro struct {
    37  	distro string
    38  	op     Operator
    39  	c      Constraints
    40  }
    41  
    42  var distros = []string{
    43  	"centos",
    44  	"clear-linux-os",
    45  	"debian",
    46  	"fedora",
    47  	"opensuse",
    48  	"rhel",
    49  	"sles",
    50  	"ubuntu",
    51  }
    52  
    53  var thisUID = os.Getuid()
    54  var rootUID = 0
    55  
    56  // name and version of current distro and kernel version of system tests are
    57  // running on
    58  var distroName string
    59  var distroVersion string
    60  var kernelVersion string
    61  
    62  // error saved when attempting to determine distro name+version and kernel
    63  // version.
    64  var getDistroErr error
    65  var getKernelErr error
    66  
    67  // true if running as root
    68  var root = thisUID == rootUID
    69  
    70  var uidEqualsRootData = testDataUID{
    71  	uid: rootUID,
    72  	op:  eqOperator,
    73  	c: Constraints{
    74  		Operator: eqOperator,
    75  		UID:      rootUID,
    76  		UIDSet:   true,
    77  	},
    78  }
    79  
    80  var uidNotEqualsRootData = testDataUID{
    81  	uid: rootUID,
    82  	op:  neOperator,
    83  	c: Constraints{
    84  		Operator: neOperator,
    85  		UID:      rootUID,
    86  		UIDSet:   true,
    87  	},
    88  }
    89  
    90  var distroEqualsCurrentData testDataDistro
    91  var distroNotEqualsCurrentData testDataDistro
    92  
    93  func init() {
    94  	distroName, distroVersion, getDistroErr = testGetDistro()
    95  	kernelVersion, getKernelErr = testGetKernelVersion()
    96  
    97  	distroEqualsCurrentData = testDataDistro{
    98  		distro: distroName,
    99  		op:     eqOperator,
   100  		c: Constraints{
   101  			DistroName: distroName,
   102  			Operator:   eqOperator,
   103  		},
   104  	}
   105  
   106  	distroNotEqualsCurrentData = testDataDistro{
   107  		distro: distroName,
   108  		op:     neOperator,
   109  		c: Constraints{
   110  			DistroName: distroName,
   111  			Operator:   neOperator,
   112  		},
   113  	}
   114  }
   115  
   116  func fileExists(path string) bool {
   117  	if _, err := os.Stat(path); os.IsNotExist(err) {
   118  		return false
   119  	}
   120  
   121  	return true
   122  }
   123  
   124  // getAnotherDistro returns a distro name not equal to the one specified.
   125  func getAnotherDistro(distro string) string {
   126  	for _, d := range distros {
   127  		if d != distro {
   128  			return d
   129  		}
   130  	}
   131  
   132  	panic(fmt.Sprintf("failed to find a distro different to %s", distro))
   133  }
   134  
   135  func checkUIDConstraints(assert *assert.Assertions, a, b Constraints, desc string) {
   136  	msg := fmt.Sprintf("%s: a: %+v, b: %+v", desc, a, b)
   137  
   138  	assert.Equal(a.UID, b.UID, msg)
   139  	assert.Equal(a.Operator, b.Operator, msg)
   140  	assert.Equal(a.UIDSet, b.UIDSet, msg)
   141  }
   142  
   143  func checkDistroConstraints(assert *assert.Assertions, a, b Constraints, desc string) {
   144  	msg := fmt.Sprintf("%s: a: %+v, b: %+v", desc, a, b)
   145  
   146  	assert.Equal(a.DistroName, b.DistroName, msg)
   147  	assert.Equal(a.Operator, b.Operator, msg)
   148  }
   149  
   150  func checkKernelConstraint(assert *assert.Assertions, f Constraint, version string, op Operator, msg string) {
   151  	c := Constraints{}
   152  
   153  	f(&c)
   154  
   155  	assert.Equal(c.KernelVersion, version, msg)
   156  	assert.Equal(c.Operator, op, msg)
   157  }
   158  
   159  // runCommand runs a command and returns its output
   160  func runCommand(args ...string) ([]string, error) {
   161  	cmd := exec.Command(args[0], args[1:]...)
   162  	bytes, err := cmd.Output()
   163  	if err != nil {
   164  		return []string{}, err
   165  	}
   166  
   167  	output := strings.Split(string(bytes), "\n")
   168  
   169  	return output, nil
   170  }
   171  
   172  // semverBumpVersion takes an existing semantic version and increments one or
   173  // more parts of it, returning the new version number as a string.
   174  func semverBumpVersion(ver semver.Version, bumpMajor, bumpMinor, bumpPatch bool) (string, error) {
   175  	if bumpMajor {
   176  		err := ver.IncrementMajor()
   177  		if err != nil {
   178  			return "", err
   179  		}
   180  	}
   181  
   182  	if bumpMinor {
   183  		err := ver.IncrementMinor()
   184  		if err != nil {
   185  			return "", err
   186  		}
   187  	}
   188  
   189  	if bumpPatch {
   190  		err := ver.IncrementPatch()
   191  		if err != nil {
   192  			return "", err
   193  		}
   194  	}
   195  
   196  	return ver.String(), nil
   197  }
   198  
   199  // changeVersion modifies the specified version and returns the
   200  // string representation. If decrement is true the returned version is smaller
   201  // than the specified version, else it is larger.
   202  func changeVersion(version string, decrement bool) (string, error) {
   203  	operand := int64(1)
   204  
   205  	if decrement {
   206  		operand = -1
   207  	}
   208  
   209  	// Is it an integer?
   210  	intResult, err := strconv.ParseUint(version, 10, 0)
   211  	if err == nil {
   212  		if intResult == 0 && decrement {
   213  			return "", fmt.Errorf("cannot decrement integer version with value zero")
   214  		}
   215  
   216  		return fmt.Sprintf("%d", uint64(int64(intResult)+operand)), nil
   217  	}
   218  
   219  	// Is it a float?
   220  	floatResult, err := strconv.ParseFloat(version, 32)
   221  	if err == nil {
   222  		if int(floatResult) == 0 && decrement {
   223  			return "", fmt.Errorf("cannot decrement integer part of floating point version with value zero: %v", version)
   224  		}
   225  
   226  		return fmt.Sprintf("%f", floatResult+float64(operand)), nil
   227  	}
   228  
   229  	// Not an int nor a float, so it must be a semantic version
   230  	ver, err := semver.Make(version)
   231  	if err != nil {
   232  		// but if not, bail as we've run out of options
   233  		return "", err
   234  	}
   235  
   236  	if decrement {
   237  		// the semver package only provides increment operations, so
   238  		// handle decrement ourselves.
   239  		major := ver.Major
   240  
   241  		if major == 0 {
   242  			return "", fmt.Errorf("cannot decrement semver with zero major version: %+v", version)
   243  		}
   244  
   245  		major--
   246  
   247  		ver.Major = major
   248  	} else {
   249  		err = ver.IncrementMajor()
   250  		if err != nil {
   251  			return "", err
   252  		}
   253  	}
   254  
   255  	return ver.String(), nil
   256  }
   257  
   258  func incrementVersion(version string) (string, error) {
   259  	return changeVersion(version, false)
   260  }
   261  
   262  func decrementVersion(version string) (string, error) {
   263  	return changeVersion(version, true)
   264  }
   265  
   266  // testGetDistro is an alternative implementation of getDistroDetails() used
   267  // for testing.
   268  func testGetDistro() (name, version string, err error) {
   269  	files := []string{"/etc/os-release", "/usr/lib/os-release"}
   270  
   271  	for _, file := range files {
   272  		if !fileExists(file) {
   273  			continue
   274  		}
   275  
   276  		output, err := runCommand("grep", "^ID=", file)
   277  		if err != nil {
   278  			return "", "", err
   279  		}
   280  
   281  		line := output[0]
   282  		fields := strings.Split(line, "=")
   283  		if name == "" {
   284  			name = strings.Trim(fields[1], `"`)
   285  			name = strings.ToLower(name)
   286  		}
   287  
   288  		output, err = runCommand("grep", "^VERSION_ID=", file)
   289  		if err != nil {
   290  			return "", "", err
   291  		}
   292  
   293  		line = output[0]
   294  		fields = strings.Split(line, "=")
   295  		if version == "" {
   296  			version = strings.Trim(fields[1], `"`)
   297  			version = strings.ToLower(version)
   298  		}
   299  	}
   300  
   301  	if name != "" && version != "" {
   302  		return name, version, nil
   303  	}
   304  
   305  	if name == "" {
   306  		return "", "", errUnknownDistroName
   307  	}
   308  
   309  	if version == "" {
   310  		return "", "", errUnknownDistroVersion
   311  	}
   312  
   313  	return "", "", errors.New("BUG: something bad happened")
   314  }
   315  
   316  func testGetKernelVersion() (version string, err error) {
   317  	const file = "/proc/version"
   318  
   319  	bytes, err := ioutil.ReadFile(file)
   320  	if err != nil {
   321  		return "", err
   322  	}
   323  
   324  	line := string(bytes)
   325  	fields := strings.Fields(line)
   326  
   327  	const minFields = 3
   328  
   329  	count := len(fields)
   330  
   331  	if count < minFields {
   332  		return "", fmt.Errorf("expected atleast %d fields in file %q, got %d",
   333  			minFields, file, count)
   334  	}
   335  
   336  	version = fixKernelVersion(fields[2])
   337  
   338  	return version, nil
   339  }
   340  
   341  func TestOperatorString(t *testing.T) {
   342  	assert := assert.New(t)
   343  
   344  	type testData struct {
   345  		op    Operator
   346  		value string
   347  	}
   348  
   349  	data := []testData{
   350  		{eqOperator, "=="},
   351  		{neOperator, "!="},
   352  	}
   353  
   354  	for i, d := range data {
   355  		value := d.op.String()
   356  
   357  		assert.Equal(value, d.value, "test[%d]: %+v", i, d)
   358  	}
   359  }
   360  
   361  func TestNewTestConstraint(t *testing.T) {
   362  	if getDistroErr != nil {
   363  		t.Skipf("skipping as unable to determine distro name/version: %v",
   364  			getDistroErr)
   365  	}
   366  
   367  	if getKernelErr != nil {
   368  		t.Skipf("skipping as unable to determine kernel version: %v",
   369  			getKernelErr)
   370  	}
   371  
   372  	assert := assert.New(t)
   373  
   374  	for i, debug := range []bool{true, false} {
   375  		c := NewTestConstraint(debug)
   376  
   377  		msg := fmt.Sprintf("test[%d]: debug: %v, constraint: %+v", i, debug, c)
   378  
   379  		assert.Equal(debug, c.Debug, msg)
   380  
   381  		assert.Equal(distroName, c.DistroName, msg)
   382  		assert.Equal(distroVersion, c.DistroVersion, msg)
   383  		assert.Equal(kernelVersion, c.KernelVersion, msg)
   384  		assert.Equal(thisUID, c.ActualEUID)
   385  
   386  		toCheck := []string{
   387  			distroName,
   388  			distroVersion,
   389  			kernelVersion,
   390  			c.DistroName,
   391  			c.DistroVersion,
   392  			c.KernelVersion,
   393  		}
   394  
   395  		for _, str := range toCheck {
   396  			assert.NotNil(str, msg)
   397  		}
   398  	}
   399  }
   400  
   401  func TestGetFileContents(t *testing.T) {
   402  	assert := assert.New(t)
   403  
   404  	type testData struct {
   405  		contents string
   406  	}
   407  
   408  	data := []testData{
   409  		{""},
   410  		{" "},
   411  		{"\n"},
   412  		{"\n\n"},
   413  		{"\n\n\n"},
   414  		{"foo"},
   415  		{"foo\nbar"},
   416  	}
   417  
   418  	dir, err := ioutil.TempDir("", "")
   419  	assert.NoError(err)
   420  	defer os.RemoveAll(dir)
   421  
   422  	file := filepath.Join(dir, "foo")
   423  
   424  	// file doesn't exist
   425  	_, err = getFileContents(file)
   426  	assert.Error(err)
   427  
   428  	for _, d := range data {
   429  		// create the file
   430  		err = ioutil.WriteFile(file, []byte(d.contents), testFileMode)
   431  		assert.NoError(err)
   432  		defer os.Remove(file)
   433  
   434  		contents, err := getFileContents(file)
   435  		assert.NoError(err)
   436  		assert.Equal(contents, d.contents)
   437  	}
   438  }
   439  
   440  func TestGetDistroDetails(t *testing.T) {
   441  	assert := assert.New(t)
   442  
   443  	if getDistroErr == errUnknownDistroName {
   444  		t.Skip(skipUnknownDistroName)
   445  	}
   446  
   447  	assert.NoError(getDistroErr)
   448  	assert.NotNil(distroName)
   449  	assert.NotNil(distroVersion)
   450  
   451  	name, version, err := getDistroDetails()
   452  	assert.NoError(err)
   453  	assert.NotNil(name)
   454  	assert.NotNil(version)
   455  
   456  	assert.Equal(name, distroName)
   457  	assert.Equal(version, distroVersion)
   458  }
   459  
   460  func TestGetKernelVersion(t *testing.T) {
   461  	assert := assert.New(t)
   462  
   463  	assert.NoError(getKernelErr)
   464  	assert.NotNil(kernelVersion)
   465  
   466  	version, err := getKernelVersion()
   467  	assert.NoError(err)
   468  	assert.NotNil(version)
   469  
   470  	assert.Equal(version, kernelVersion)
   471  }
   472  
   473  func TestConstraintHandleDistroName(t *testing.T) {
   474  	assert := assert.New(t)
   475  
   476  	type testData struct {
   477  		distro      string
   478  		op          Operator
   479  		result      Result
   480  		expectError bool
   481  	}
   482  
   483  	distroName, _, err := testGetDistro()
   484  	if err != nil && err == errUnknownDistroName {
   485  		t.Skip(skipUnknownDistroName)
   486  	}
   487  
   488  	// Look for the first distro that is not the same as the distro this
   489  	// test is currently running on.
   490  	differentDistro := getAnotherDistro(distroName)
   491  
   492  	data := []testData{
   493  		{"", eqOperator, Result{}, true},
   494  		{"", neOperator, Result{}, true},
   495  		{"", invalidOperator, Result{}, true},
   496  		{distroName, invalidOperator, Result{}, true},
   497  		{distroName, invalidOperator, Result{}, true},
   498  
   499  		{
   500  			distroName,
   501  			eqOperator,
   502  			Result{
   503  				Description: distroName,
   504  				Success:     true,
   505  			},
   506  			false,
   507  		},
   508  		{
   509  			distroName,
   510  			neOperator,
   511  			Result{
   512  				Description: distroName,
   513  				Success:     false,
   514  			},
   515  			false,
   516  		},
   517  		{
   518  			differentDistro,
   519  			eqOperator,
   520  			Result{
   521  				Description: differentDistro,
   522  				Success:     false,
   523  			},
   524  			false,
   525  		},
   526  
   527  		{
   528  			differentDistro,
   529  			neOperator,
   530  			Result{
   531  				Description: differentDistro,
   532  				Success:     true,
   533  			},
   534  			false,
   535  		},
   536  	}
   537  
   538  	for _, debug := range []bool{true, false} {
   539  		tc := NewTestConstraint(debug)
   540  
   541  		for i, d := range data {
   542  			result, err := tc.handleDistroName(d.distro, d.op)
   543  
   544  			msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
   545  
   546  			if d.expectError {
   547  				assert.Error(err, msg)
   548  				continue
   549  
   550  			}
   551  
   552  			assert.NoError(err, msg)
   553  			assert.Equal(result.Success, d.result.Success, msg)
   554  			assert.NotNil(result.Description, msg)
   555  		}
   556  	}
   557  }
   558  
   559  func TestConstraintHandleDistroVersion(t *testing.T) {
   560  	assert := assert.New(t)
   561  
   562  	assert.NotNil(distroVersion)
   563  
   564  	// Generate a new distro version for testing purposes. Since we don't
   565  	// know the format of this particular distros versioning scheme, we
   566  	// need to calculate it.
   567  	higherVersion, err := incrementVersion(distroVersion)
   568  	assert.NoError(err)
   569  	assert.NotEqual(distroVersion, higherVersion)
   570  
   571  	type testData struct {
   572  		version     string
   573  		op          Operator
   574  		result      Result
   575  		expectError bool
   576  	}
   577  
   578  	data := []testData{
   579  		{"", eqOperator, Result{}, true},
   580  		{"", geOperator, Result{}, true},
   581  		{"", gtOperator, Result{}, true},
   582  		{"", leOperator, Result{}, true},
   583  		{"", ltOperator, Result{}, true},
   584  		{"", neOperator, Result{}, true},
   585  
   586  		{distroVersion, eqOperator, Result{Success: true}, false},
   587  		{higherVersion, eqOperator, Result{Success: false}, false},
   588  
   589  		{distroVersion, gtOperator, Result{Success: false}, false},
   590  		{higherVersion, gtOperator, Result{Success: false}, false},
   591  
   592  		{distroVersion, geOperator, Result{Success: true}, false},
   593  		{higherVersion, geOperator, Result{Success: false}, false},
   594  
   595  		{distroVersion, ltOperator, Result{Success: false}, false},
   596  		{higherVersion, ltOperator, Result{Success: true}, false},
   597  
   598  		{distroVersion, leOperator, Result{Success: true}, false},
   599  		{higherVersion, leOperator, Result{Success: true}, false},
   600  
   601  		{distroVersion, neOperator, Result{Success: false}, false},
   602  		{higherVersion, neOperator, Result{Success: true}, false},
   603  	}
   604  
   605  	for _, debug := range []bool{true, false} {
   606  		tc := NewTestConstraint(debug)
   607  
   608  		for i, d := range data {
   609  			result, err := tc.handleDistroVersion(d.version, d.op)
   610  
   611  			msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
   612  
   613  			if d.expectError {
   614  				assert.Error(err, msg)
   615  				continue
   616  			}
   617  
   618  			assert.Equal(d.result.Success, result.Success, msg)
   619  		}
   620  	}
   621  }
   622  
   623  func TestConstraintHandleVersionType(t *testing.T) {
   624  	assert := assert.New(t)
   625  
   626  	type testData struct {
   627  		versionName    string
   628  		currentVersion string
   629  		op             Operator
   630  		newVersion     string
   631  		result         Result
   632  		expectError    bool
   633  	}
   634  
   635  	data := []testData{
   636  		//----------
   637  
   638  		{"", "", eqOperator, "", Result{}, true},
   639  
   640  		{"name", "foo", eqOperator, "", Result{}, true},
   641  		{"name", "", eqOperator, "foo", Result{}, true},
   642  		{"name", "1", eqOperator, "", Result{}, true},
   643  		{"name", "", eqOperator, "1", Result{}, true},
   644  
   645  		{"name", "1", eqOperator, "1", Result{Success: true}, false},
   646  		{"name", "1", eqOperator, "2", Result{Success: false}, false},
   647  		{"name", "2", eqOperator, "1", Result{Success: false}, false},
   648  
   649  		{"name", "3.141", eqOperator, "3.141", Result{Success: true}, false},
   650  		{"name", "4.141", eqOperator, "3.141", Result{Success: false}, false},
   651  		{"name", "3.141", eqOperator, "4.141", Result{Success: false}, false},
   652  
   653  		{"name", "3.1.4-1", eqOperator, "3.1.4-1", Result{Success: true}, false},
   654  		{"name", "3.1.4-1", eqOperator, "4.1.4-1", Result{Success: false}, false},
   655  		{"name", "4.1.4-1", eqOperator, "3.1.4-1", Result{Success: false}, false},
   656  
   657  		//----------
   658  
   659  		{"", "", ltOperator, "", Result{}, true},
   660  
   661  		{"name", "foo", ltOperator, "", Result{}, true},
   662  		{"name", "", ltOperator, "foo", Result{}, true},
   663  		{"name", "1", ltOperator, "", Result{}, true},
   664  		{"name", "", ltOperator, "1", Result{}, true},
   665  
   666  		{"name", "1", ltOperator, "2", Result{Success: true}, false},
   667  		{"name", "2", ltOperator, "1", Result{Success: false}, false},
   668  		{"name", "1", ltOperator, "1", Result{Success: false}, false},
   669  
   670  		{"name", "1.3", ltOperator, "2.3", Result{Success: true}, false},
   671  		{"name", "2.3", ltOperator, "1.3", Result{Success: false}, false},
   672  		{"name", "1.3", ltOperator, "1.3", Result{Success: false}, false},
   673  
   674  		{"name", "3.1.4", ltOperator, "3.1.5", Result{Success: true}, false},
   675  		{"name", "3.1.5", ltOperator, "3.1.4", Result{Success: false}, false},
   676  		{"name", "3.1.4", ltOperator, "3.1.4", Result{Success: false}, false},
   677  
   678  		//----------
   679  
   680  		{"", "", leOperator, "", Result{}, true},
   681  
   682  		{"name", "foo", leOperator, "", Result{}, true},
   683  		{"name", "", leOperator, "foo", Result{}, true},
   684  		{"name", "1", leOperator, "", Result{}, true},
   685  		{"name", "", leOperator, "1", Result{}, true},
   686  
   687  		{"name", "1", leOperator, "2", Result{Success: true}, false},
   688  		{"name", "2", leOperator, "1", Result{Success: false}, false},
   689  		{"name", "1", leOperator, "1", Result{Success: true}, false},
   690  
   691  		{"name", "1.3", leOperator, "2.3", Result{Success: true}, false},
   692  		{"name", "2.3", leOperator, "1.3", Result{Success: false}, false},
   693  		{"name", "1.3", leOperator, "1.3", Result{Success: true}, false},
   694  
   695  		{"name", "3.1.4", leOperator, "3.1.5", Result{Success: true}, false},
   696  		{"name", "3.1.5", leOperator, "3.1.4", Result{Success: false}, false},
   697  		{"name", "3.1.4", leOperator, "3.1.4", Result{Success: true}, false},
   698  
   699  		//----------
   700  
   701  		{"", "", gtOperator, "", Result{}, true},
   702  
   703  		{"name", "foo", gtOperator, "", Result{}, true},
   704  		{"name", "", gtOperator, "foo", Result{}, true},
   705  		{"name", "1", gtOperator, "", Result{}, true},
   706  		{"name", "", gtOperator, "1", Result{}, true},
   707  
   708  		{"name", "1", gtOperator, "2", Result{Success: false}, false},
   709  		{"name", "2", gtOperator, "1", Result{Success: true}, false},
   710  		{"name", "1", gtOperator, "1", Result{Success: false}, false},
   711  
   712  		{"name", "1.3", gtOperator, "2.3", Result{Success: false}, false},
   713  		{"name", "2.3", gtOperator, "1.3", Result{Success: true}, false},
   714  		{"name", "1.3", gtOperator, "1.3", Result{Success: false}, false},
   715  
   716  		{"name", "3.1.4", gtOperator, "3.1.5", Result{Success: false}, false},
   717  		{"name", "3.1.5", gtOperator, "3.1.4", Result{Success: true}, false},
   718  		{"name", "3.1.4", gtOperator, "3.1.4", Result{Success: false}, false},
   719  
   720  		//----------
   721  
   722  		{"", "", geOperator, "", Result{}, true},
   723  
   724  		{"name", "foo", geOperator, "", Result{}, true},
   725  		{"name", "", geOperator, "foo", Result{}, true},
   726  		{"name", "1", geOperator, "", Result{}, true},
   727  		{"name", "", geOperator, "1", Result{}, true},
   728  
   729  		{"name", "1", geOperator, "2", Result{Success: false}, false},
   730  		{"name", "2", geOperator, "1", Result{Success: true}, false},
   731  		{"name", "1", geOperator, "1", Result{Success: true}, false},
   732  
   733  		{"name", "1.3", geOperator, "2.3", Result{Success: false}, false},
   734  		{"name", "2.3", geOperator, "1.3", Result{Success: true}, false},
   735  		{"name", "1.3", geOperator, "1.3", Result{Success: true}, false},
   736  
   737  		{"name", "3.1.4", geOperator, "3.1.5", Result{Success: false}, false},
   738  		{"name", "3.1.5", geOperator, "3.1.4", Result{Success: true}, false},
   739  		{"name", "3.1.4", geOperator, "3.1.4", Result{Success: true}, false},
   740  
   741  		//----------
   742  
   743  		{"", "", neOperator, "", Result{}, true},
   744  
   745  		{"name", "foo", neOperator, "", Result{}, true},
   746  		{"name", "", neOperator, "foo", Result{}, true},
   747  		{"name", "1", neOperator, "", Result{}, true},
   748  		{"name", "", neOperator, "1", Result{}, true},
   749  
   750  		{"name", "1", neOperator, "2", Result{Success: true}, false},
   751  		{"name", "2", neOperator, "1", Result{Success: true}, false},
   752  		{"name", "1", neOperator, "1", Result{Success: false}, false},
   753  
   754  		{"name", "1.3", neOperator, "2.3", Result{Success: true}, false},
   755  		{"name", "2.3", neOperator, "1.3", Result{Success: true}, false},
   756  		{"name", "1.3", neOperator, "1.3", Result{Success: false}, false},
   757  
   758  		{"name", "3.1.4", neOperator, "3.1.5", Result{Success: true}, false},
   759  		{"name", "3.1.5", neOperator, "3.1.4", Result{Success: true}, false},
   760  		{"name", "3.1.4", neOperator, "3.1.4", Result{Success: false}, false},
   761  
   762  		//----------
   763  	}
   764  
   765  	for i, d := range data {
   766  		result, err := handleVersionType(d.versionName, d.currentVersion, d.op, d.newVersion)
   767  
   768  		msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
   769  
   770  		if d.expectError {
   771  			assert.Error(err, msg)
   772  			continue
   773  		}
   774  
   775  		assert.Equal(d.result.Success, result.Success, msg)
   776  	}
   777  }
   778  
   779  func TestConstraintHandleKernelVersion(t *testing.T) {
   780  	assert := assert.New(t)
   781  
   782  	ver, err := semver.Make(kernelVersion)
   783  	assert.NoError(err)
   784  
   785  	newerMajor, err := semverBumpVersion(ver, true, false, false)
   786  	assert.NoError(err)
   787  
   788  	newerMinor, err := semverBumpVersion(ver, false, true, false)
   789  	assert.NoError(err)
   790  
   791  	newerPatch, err := semverBumpVersion(ver, false, false, true)
   792  	assert.NoError(err)
   793  
   794  	type testData struct {
   795  		version     string
   796  		op          Operator
   797  		result      Result
   798  		expectError bool
   799  	}
   800  
   801  	data := []testData{
   802  		{"", eqOperator, Result{}, true},
   803  		{"", geOperator, Result{}, true},
   804  		{"", gtOperator, Result{}, true},
   805  		{"", leOperator, Result{}, true},
   806  		{"", ltOperator, Result{}, true},
   807  		{"", neOperator, Result{}, true},
   808  
   809  		{kernelVersion, eqOperator, Result{Success: true}, false},
   810  		{kernelVersion, neOperator, Result{Success: false}, false},
   811  
   812  		{newerMajor, eqOperator, Result{Success: false}, false},
   813  		{newerMajor, geOperator, Result{Success: false}, false},
   814  		{newerMajor, gtOperator, Result{Success: false}, false},
   815  		{newerMajor, ltOperator, Result{Success: true}, false},
   816  		{newerMajor, leOperator, Result{Success: true}, false},
   817  		{newerMajor, neOperator, Result{Success: true}, false},
   818  
   819  		{newerMinor, eqOperator, Result{Success: false}, false},
   820  		{newerMinor, geOperator, Result{Success: false}, false},
   821  		{newerMinor, gtOperator, Result{Success: false}, false},
   822  		{newerMinor, ltOperator, Result{Success: true}, false},
   823  		{newerMinor, leOperator, Result{Success: true}, false},
   824  		{newerMinor, neOperator, Result{Success: true}, false},
   825  
   826  		{newerPatch, eqOperator, Result{Success: false}, false},
   827  		{newerPatch, geOperator, Result{Success: false}, false},
   828  		{newerPatch, gtOperator, Result{Success: false}, false},
   829  		{newerPatch, ltOperator, Result{Success: true}, false},
   830  		{newerPatch, leOperator, Result{Success: true}, false},
   831  		{newerPatch, neOperator, Result{Success: true}, false},
   832  	}
   833  
   834  	for _, debug := range []bool{true, false} {
   835  		tc := NewTestConstraint(debug)
   836  
   837  		for i, d := range data {
   838  			result, err := tc.handleKernelVersion(d.version, d.op)
   839  
   840  			msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
   841  
   842  			if d.expectError {
   843  				assert.Error(err, msg)
   844  				continue
   845  			}
   846  
   847  			assert.Equal(d.result.Success, result.Success, msg)
   848  		}
   849  	}
   850  }
   851  
   852  func TestConstraintHandleUID(t *testing.T) {
   853  	assert := assert.New(t)
   854  
   855  	type testData struct {
   856  		uid         int
   857  		op          Operator
   858  		result      Result
   859  		expectError bool
   860  	}
   861  
   862  	data := []testData{
   863  		{-1, eqOperator, Result{}, true},
   864  		{-1, neOperator, Result{}, true},
   865  		{-2, eqOperator, Result{}, true},
   866  		{-2, neOperator, Result{}, true},
   867  		{rootUID, invalidOperator, Result{}, true},
   868  		{thisUID, invalidOperator, Result{}, true},
   869  
   870  		{rootUID, eqOperator, Result{Success: root}, false},
   871  		{rootUID, neOperator, Result{Success: !root}, false},
   872  
   873  		{thisUID, eqOperator, Result{Success: true}, false},
   874  		{thisUID, neOperator, Result{Success: false}, false},
   875  	}
   876  
   877  	for _, debug := range []bool{true, false} {
   878  		tc := NewTestConstraint(debug)
   879  
   880  		for i, d := range data {
   881  			result, err := tc.handleUID(d.uid, d.op)
   882  
   883  			msg := fmt.Sprintf("test[%d]: %+v, result: %+v", i, d, result)
   884  
   885  			if d.expectError {
   886  				assert.Error(err, msg)
   887  				continue
   888  			}
   889  
   890  			assert.NoError(err, msg)
   891  			assert.Equal(result.Success, d.result.Success, msg)
   892  			assert.NotNil(result.Description, msg)
   893  		}
   894  	}
   895  }
   896  
   897  func TestConstraintHandleResults(t *testing.T) {
   898  	assert := assert.New(t)
   899  
   900  	type testData struct {
   901  		result Result
   902  		err    error
   903  	}
   904  
   905  	data := []testData{
   906  		{Result{}, errors.New("foo")},
   907  
   908  		{Result{Success: true}, nil},
   909  		{Result{Success: false}, nil},
   910  	}
   911  
   912  	for _, debug := range []bool{true, false} {
   913  		tc := NewTestConstraint(debug)
   914  
   915  		for i, d := range data {
   916  			tc.Passed = nil
   917  			tc.Failed = nil
   918  
   919  			msg := fmt.Sprintf("test[%d]: %+v", i, d)
   920  
   921  			if d.err != nil {
   922  				assert.Panics(func() {
   923  					tc.handleResults(d.result, d.err)
   924  				}, msg)
   925  				continue
   926  			}
   927  
   928  			tc.handleResults(d.result, d.err)
   929  
   930  			passedLen := len(tc.Passed)
   931  			failedLen := len(tc.Failed)
   932  
   933  			var expectedPassedLen int
   934  			var expectedFailedLen int
   935  
   936  			if d.result.Success {
   937  				expectedPassedLen = 1
   938  				expectedFailedLen = 0
   939  			} else {
   940  				expectedPassedLen = 0
   941  				expectedFailedLen = 1
   942  			}
   943  
   944  			assert.Equal(passedLen, expectedPassedLen, msg)
   945  			assert.Equal(failedLen, expectedFailedLen, msg)
   946  		}
   947  	}
   948  }
   949  
   950  func TestNeedUID(t *testing.T) {
   951  	assert := assert.New(t)
   952  
   953  	data := []testDataUID{
   954  		uidEqualsRootData,
   955  		uidNotEqualsRootData,
   956  		{thisUID, eqOperator, Constraints{
   957  			Operator: eqOperator,
   958  			UID:      thisUID,
   959  			UIDSet:   true},
   960  		},
   961  	}
   962  
   963  	for i, d := range data {
   964  		c := Constraints{}
   965  
   966  		f := NeedUID(d.uid, d.op)
   967  		f(&c)
   968  
   969  		desc := fmt.Sprintf("test[%d]: %+v", i, d)
   970  		checkUIDConstraints(assert, c, d.c, desc)
   971  	}
   972  }
   973  
   974  func TestNeedRoot(t *testing.T) {
   975  	assert := assert.New(t)
   976  
   977  	c := Constraints{}
   978  
   979  	f := NeedRoot()
   980  	f(&c)
   981  
   982  	checkUIDConstraints(assert, c, uidEqualsRootData.c, "TestNeedRoot")
   983  }
   984  
   985  func TestNeedNonRoot(t *testing.T) {
   986  	assert := assert.New(t)
   987  
   988  	c := Constraints{}
   989  
   990  	f := NeedNonRoot()
   991  	f(&c)
   992  
   993  	checkUIDConstraints(assert, c, uidNotEqualsRootData.c, "TestNeedNonRoot")
   994  }
   995  
   996  func TestNeedDistroWithOp(t *testing.T) {
   997  	assert := assert.New(t)
   998  
   999  	if getDistroErr == errUnknownDistroName {
  1000  		t.Skip(skipUnknownDistroName)
  1001  	}
  1002  
  1003  	data := []testDataDistro{
  1004  		distroEqualsCurrentData,
  1005  		distroNotEqualsCurrentData,
  1006  
  1007  		// check name provided is lower-cased
  1008  		{
  1009  			strings.ToUpper(distroName),
  1010  			eqOperator,
  1011  			Constraints{
  1012  				DistroName: distroName,
  1013  				Operator:   eqOperator,
  1014  			},
  1015  		},
  1016  	}
  1017  
  1018  	for i, d := range data {
  1019  
  1020  		c := Constraints{}
  1021  
  1022  		f := NeedDistroWithOp(d.distro, d.op)
  1023  		f(&c)
  1024  
  1025  		desc := fmt.Sprintf("test[%d]: %+v, constraints: %+v", i, d, c)
  1026  		checkDistroConstraints(assert, d.c, c, desc)
  1027  	}
  1028  }
  1029  
  1030  func TestNeedDistroEquals(t *testing.T) {
  1031  	assert := assert.New(t)
  1032  
  1033  	c := Constraints{}
  1034  
  1035  	f := NeedDistroEquals(distroName)
  1036  	f(&c)
  1037  
  1038  	checkDistroConstraints(assert, c, distroEqualsCurrentData.c, "TestNeedDistroEquals")
  1039  }
  1040  
  1041  func TestNeedDistroNotEquals(t *testing.T) {
  1042  	assert := assert.New(t)
  1043  
  1044  	c := Constraints{}
  1045  
  1046  	f := NeedDistroNotEquals(distroName)
  1047  	f(&c)
  1048  
  1049  	checkDistroConstraints(assert, c, distroNotEqualsCurrentData.c, "TestNeedDistroNotEquals")
  1050  }
  1051  
  1052  func TestWithIssue(t *testing.T) {
  1053  	assert := assert.New(t)
  1054  
  1055  	c := Constraints{}
  1056  
  1057  	issue := "issue"
  1058  
  1059  	f := WithIssue(issue)
  1060  	f(&c)
  1061  
  1062  	assert.Equal(c.Issue, issue)
  1063  }
  1064  
  1065  func TestNeedKernelVersionWithOp(t *testing.T) {
  1066  	assert := assert.New(t)
  1067  
  1068  	type testData struct {
  1069  		version string
  1070  		op      Operator
  1071  	}
  1072  
  1073  	version := "version"
  1074  
  1075  	data := []testData{
  1076  		{version, eqOperator},
  1077  		{version, geOperator},
  1078  		{version, gtOperator},
  1079  		{version, leOperator},
  1080  		{version, ltOperator},
  1081  		{version, neOperator},
  1082  	}
  1083  
  1084  	for i, d := range data {
  1085  		msg := fmt.Sprintf("test[%d]: %+v", i, d)
  1086  
  1087  		c := NeedKernelVersionWithOp(d.version, d.op)
  1088  
  1089  		checkKernelConstraint(assert, c, d.version, d.op, msg)
  1090  	}
  1091  }
  1092  
  1093  func TestNeedKernelVersion(t *testing.T) {
  1094  	assert := assert.New(t)
  1095  
  1096  	version := "version"
  1097  	f := NeedKernelVersion(version)
  1098  	checkKernelConstraint(assert, f, version, eqOperator, "TestNeedKernelVersion")
  1099  }
  1100  
  1101  func TestNeedKernelVersionEquals(t *testing.T) {
  1102  	assert := assert.New(t)
  1103  
  1104  	version := "version"
  1105  	f := NeedKernelVersionEquals(version)
  1106  	checkKernelConstraint(assert, f, version, eqOperator, "TestNeedKernelVersionEquals")
  1107  }
  1108  
  1109  func TestNeedKernelVersionLE(t *testing.T) {
  1110  	assert := assert.New(t)
  1111  
  1112  	version := "version"
  1113  	f := NeedKernelVersionLE(version)
  1114  	checkKernelConstraint(assert, f, version, leOperator, "TestNeedKernelVersionLE")
  1115  }
  1116  
  1117  func TestNeedKernelVersionLT(t *testing.T) {
  1118  	assert := assert.New(t)
  1119  
  1120  	version := "version"
  1121  	f := NeedKernelVersionLT(version)
  1122  	checkKernelConstraint(assert, f, version, ltOperator, "TestNeedKernelVersionLT")
  1123  }
  1124  
  1125  func TestNeedKernelVersionGE(t *testing.T) {
  1126  	assert := assert.New(t)
  1127  
  1128  	version := "version"
  1129  	f := NeedKernelVersionGE(version)
  1130  	checkKernelConstraint(assert, f, version, geOperator, "TestNeedKernelVersionGE")
  1131  }
  1132  
  1133  func TestNeedKernelVersionGT(t *testing.T) {
  1134  	assert := assert.New(t)
  1135  
  1136  	version := "version"
  1137  	f := NeedKernelVersionGT(version)
  1138  	checkKernelConstraint(assert, f, version, gtOperator, "TestNeedKernelVersionGT")
  1139  }
  1140  
  1141  func TestConstraintNotValid(t *testing.T) {
  1142  	assert := assert.New(t)
  1143  
  1144  	for _, debug := range []bool{true, false} {
  1145  		tc := NewTestConstraint(debug)
  1146  
  1147  		// Ensure no params is an error
  1148  		assert.Panics(func() {
  1149  			_ = tc.NotValid()
  1150  		})
  1151  
  1152  		// Test specification of a single constraint
  1153  		if root {
  1154  			result := tc.NotValid(NeedRoot())
  1155  			assert.False(result)
  1156  
  1157  			result = tc.NotValid(NeedNonRoot())
  1158  			assert.True(result)
  1159  		} else {
  1160  			result := tc.NotValid(NeedRoot())
  1161  			assert.True(result)
  1162  
  1163  			result = tc.NotValid(NeedNonRoot())
  1164  			assert.False(result)
  1165  		}
  1166  
  1167  		// Now test specification of multiple constraints
  1168  		if root {
  1169  			result := tc.NotValid(NeedRoot(), NeedDistro(distroName))
  1170  			assert.False(result)
  1171  
  1172  			result = tc.NotValid(NeedNonRoot(), NeedDistro(distroName))
  1173  			assert.True(result)
  1174  		} else {
  1175  			result := tc.NotValid(NeedRoot(), NeedDistro(distroName))
  1176  			assert.True(result)
  1177  
  1178  			result = tc.NotValid(NeedNonRoot(), NeedDistro(distroName))
  1179  			assert.False(result)
  1180  		}
  1181  	}
  1182  
  1183  }
  1184  
  1185  func TestConstraintNotValidKernelVersion(t *testing.T) {
  1186  	assert := assert.New(t)
  1187  
  1188  	assert.NotNil(kernelVersion)
  1189  
  1190  	// Generate new kernel versions for testing purposes based on the
  1191  	// current kernel version.
  1192  	higherVersion, err := incrementVersion(kernelVersion)
  1193  	assert.NoError(err)
  1194  	assert.NotEqual(kernelVersion, higherVersion)
  1195  
  1196  	lowerVersion, err := decrementVersion(kernelVersion)
  1197  	assert.NoError(err)
  1198  	assert.NotEqual(kernelVersion, lowerVersion)
  1199  
  1200  	// Antique kernel version numbers.
  1201  	//
  1202  	// Note: Not all are actually real kernel releases - we're just trying
  1203  	// to do a thorough test.
  1204  	lowKernelVersions := []string{
  1205  		"0.0.0",
  1206  		"0.0.1",
  1207  		"1.0.0",
  1208  		"1.0.6-1.1.0",
  1209  		"2.0.0",
  1210  		"2.6.0",
  1211  		lowerVersion,
  1212  	}
  1213  
  1214  	// Host kernel is expected to be newer than all the low kernel versions
  1215  	for _, debug := range []bool{true, false} {
  1216  		tc := NewTestConstraint(debug)
  1217  
  1218  		for _, ver := range lowKernelVersions {
  1219  			result := tc.NotValid(NeedKernelVersionEquals(ver))
  1220  			assert.True(result)
  1221  
  1222  			result = tc.NotValid(NeedKernelVersionLE(ver))
  1223  			assert.True(result)
  1224  
  1225  			result = tc.NotValid(NeedKernelVersionLT(ver))
  1226  			assert.True(result)
  1227  
  1228  			result = tc.NotValid(NeedKernelVersionGT(ver))
  1229  			assert.False(result)
  1230  
  1231  			result = tc.NotValid(NeedKernelVersionGE(ver))
  1232  			assert.False(result)
  1233  
  1234  			result = tc.NotValid(NeedKernelVersionNotEquals(ver))
  1235  			assert.False(result)
  1236  		}
  1237  	}
  1238  
  1239  	// Ridiculously high kernel version numbers. The host kernel is
  1240  	// expected to never reach these values.
  1241  	highKernelVersions := []string{
  1242  		higherVersion,
  1243  		"999.0.0",
  1244  		"999.0.999",
  1245  		"999.999.999",
  1246  		"1024.0.0",
  1247  	}
  1248  
  1249  	for _, debug := range []bool{true, false} {
  1250  		tc := NewTestConstraint(debug)
  1251  
  1252  		for _, ver := range highKernelVersions {
  1253  			result := tc.NotValid(NeedKernelVersionEquals(ver))
  1254  			assert.True(result)
  1255  
  1256  			result = tc.NotValid(NeedKernelVersionGE(ver))
  1257  			assert.True(result)
  1258  
  1259  			result = tc.NotValid(NeedKernelVersionGT(ver))
  1260  			assert.True(result)
  1261  
  1262  			result = tc.NotValid(NeedKernelVersionLE(ver))
  1263  			assert.False(result)
  1264  
  1265  			result = tc.NotValid(NeedKernelVersionLT(ver))
  1266  			assert.False(result)
  1267  
  1268  			result = tc.NotValid(NeedKernelVersionNotEquals(ver))
  1269  			assert.False(result)
  1270  		}
  1271  	}
  1272  }
  1273  
  1274  func TestConstraintNotValidDistroVersion(t *testing.T) {
  1275  	assert := assert.New(t)
  1276  
  1277  	assert.NotNil(distroVersion)
  1278  
  1279  	// Generate new distro versions for testing purposes based on the
  1280  	// current kernel version.
  1281  	higherVersion, err := incrementVersion(distroVersion)
  1282  	assert.NoError(err)
  1283  	assert.NotEqual(distroVersion, higherVersion)
  1284  
  1285  	lowerVersion, err := decrementVersion(distroVersion)
  1286  	assert.NoError(err)
  1287  	assert.NotEqual(distroVersion, lowerVersion)
  1288  
  1289  	for _, debug := range []bool{true, false} {
  1290  		tc := NewTestConstraint(debug)
  1291  
  1292  		result := tc.NotValid(NeedDistroVersionEquals(higherVersion))
  1293  		assert.True(result)
  1294  
  1295  		result = tc.NotValid(NeedDistroVersionEquals(distroVersion))
  1296  		assert.False(result)
  1297  
  1298  		result = tc.NotValid(NeedDistroVersionLE(higherVersion))
  1299  		assert.False(result)
  1300  
  1301  		result = tc.NotValid(NeedDistroVersionLE(distroVersion))
  1302  		assert.False(result)
  1303  
  1304  		result = tc.NotValid(NeedDistroVersionLT(higherVersion))
  1305  		assert.False(result)
  1306  
  1307  		result = tc.NotValid(NeedDistroVersionLT(distroVersion))
  1308  		assert.True(result)
  1309  
  1310  		result = tc.NotValid(NeedDistroVersionGE(higherVersion))
  1311  		assert.True(result)
  1312  
  1313  		result = tc.NotValid(NeedDistroVersionGE(distroVersion))
  1314  		assert.False(result)
  1315  
  1316  		result = tc.NotValid(NeedDistroVersionGT(higherVersion))
  1317  		assert.True(result)
  1318  
  1319  		result = tc.NotValid(NeedDistroVersionGT(distroVersion))
  1320  		assert.True(result)
  1321  
  1322  		result = tc.NotValid(NeedDistroVersionNotEquals(higherVersion))
  1323  		assert.False(result)
  1324  
  1325  		result = tc.NotValid(NeedDistroVersionNotEquals(distroVersion))
  1326  		assert.True(result)
  1327  	}
  1328  }
  1329  
  1330  func TestConstraintConstraintValid(t *testing.T) {
  1331  	assert := assert.New(t)
  1332  
  1333  	type testData struct {
  1334  		fn       Constraint
  1335  		valid    bool
  1336  		expected TestConstraint
  1337  	}
  1338  
  1339  	issue := "issue"
  1340  
  1341  	data := []testData{
  1342  		{
  1343  			WithIssue(issue),
  1344  			true,
  1345  			TestConstraint{Issue: issue},
  1346  		},
  1347  
  1348  		{
  1349  			NeedDistroWithOp(distroName, eqOperator),
  1350  			true,
  1351  			TestConstraint{
  1352  				Passed: []Result{
  1353  					{Success: true},
  1354  				},
  1355  			},
  1356  		},
  1357  		{
  1358  			NeedDistroWithOp(distroName, neOperator),
  1359  			false,
  1360  			TestConstraint{
  1361  				Failed: []Result{
  1362  					{Success: false},
  1363  				},
  1364  			},
  1365  		},
  1366  		{
  1367  			NeedDistroWithOp(getAnotherDistro(distroName), eqOperator),
  1368  			false,
  1369  			TestConstraint{
  1370  				Failed: []Result{
  1371  					{Success: false},
  1372  				},
  1373  			},
  1374  		},
  1375  		{
  1376  			NeedDistroWithOp(getAnotherDistro(distroName), neOperator),
  1377  			true,
  1378  			TestConstraint{
  1379  				Failed: []Result{
  1380  					{Success: true},
  1381  				},
  1382  			},
  1383  		},
  1384  
  1385  		{
  1386  			NeedDistroEquals(distroName),
  1387  			true,
  1388  			TestConstraint{
  1389  				Passed: []Result{
  1390  					{Success: true},
  1391  				},
  1392  			},
  1393  		},
  1394  		{
  1395  			NeedDistroEquals(getAnotherDistro(distroName)),
  1396  			false,
  1397  			TestConstraint{
  1398  				Failed: []Result{
  1399  					{Success: false},
  1400  				},
  1401  			},
  1402  		},
  1403  
  1404  		{
  1405  			NeedDistroNotEquals(getAnotherDistro(distroName)),
  1406  			true,
  1407  			TestConstraint{
  1408  				Passed: []Result{
  1409  					{Success: true},
  1410  				},
  1411  			},
  1412  		},
  1413  		{
  1414  			NeedDistroNotEquals(distroName),
  1415  			false,
  1416  			TestConstraint{
  1417  				Failed: []Result{
  1418  					{Success: false},
  1419  				},
  1420  			},
  1421  		},
  1422  
  1423  		{
  1424  			NeedDistro(distroName),
  1425  			true,
  1426  			TestConstraint{
  1427  				Passed: []Result{
  1428  					{Success: true},
  1429  				},
  1430  			},
  1431  		},
  1432  		{
  1433  			NeedDistro(getAnotherDistro(distroName)),
  1434  			false,
  1435  			TestConstraint{
  1436  				Failed: []Result{
  1437  					{Success: false},
  1438  				},
  1439  			},
  1440  		},
  1441  	}
  1442  
  1443  	if root {
  1444  		td := testData{
  1445  			fn:    NeedRoot(),
  1446  			valid: true,
  1447  			expected: TestConstraint{
  1448  				Passed: []Result{
  1449  					{Success: true},
  1450  				},
  1451  			},
  1452  		}
  1453  
  1454  		data = append(data, td)
  1455  
  1456  		td = testData{
  1457  			fn:    NeedNonRoot(),
  1458  			valid: false,
  1459  			expected: TestConstraint{
  1460  				Failed: []Result{
  1461  					{Success: false},
  1462  				},
  1463  			},
  1464  		}
  1465  
  1466  		data = append(data, td)
  1467  	} else {
  1468  		td := testData{
  1469  			fn:    NeedRoot(),
  1470  			valid: false,
  1471  			expected: TestConstraint{
  1472  				Failed: []Result{
  1473  					{Success: false},
  1474  				},
  1475  			},
  1476  		}
  1477  
  1478  		data = append(data, td)
  1479  
  1480  		td = testData{
  1481  			fn:    NeedNonRoot(),
  1482  			valid: true,
  1483  			expected: TestConstraint{
  1484  				Passed: []Result{
  1485  					{Success: true},
  1486  				},
  1487  			},
  1488  		}
  1489  
  1490  		data = append(data, td)
  1491  	}
  1492  
  1493  	for _, debug := range []bool{true, false} {
  1494  		for i, d := range data {
  1495  			tc := NewTestConstraint(debug)
  1496  
  1497  			result := tc.constraintValid(d.fn)
  1498  
  1499  			msg := fmt.Sprintf("test[%d]: %+v, result: %v", i, d, result)
  1500  
  1501  			if d.expected.Issue != "" {
  1502  				assert.Equal(tc.Issue, d.expected.Issue, msg)
  1503  			}
  1504  
  1505  			if d.valid {
  1506  				assert.True(result, msg)
  1507  
  1508  				if len(d.expected.Passed) != 0 {
  1509  					assert.Equal(d.expected.Passed[0].Success, tc.Passed[0].Success, msg)
  1510  				}
  1511  			} else {
  1512  				assert.False(result, msg)
  1513  
  1514  				if len(d.expected.Failed) != 0 {
  1515  					assert.Equal(d.expected.Failed[0].Success, tc.Failed[0].Success, msg)
  1516  				}
  1517  			}
  1518  		}
  1519  	}
  1520  }
  1521  
  1522  func TestEvalIntVersion(t *testing.T) {
  1523  	assert := assert.New(t)
  1524  
  1525  	type testData struct {
  1526  		currentVer    string
  1527  		op            Operator
  1528  		newVer        string
  1529  		expectSuccess bool
  1530  		expectError   bool
  1531  	}
  1532  
  1533  	data := []testData{
  1534  		//----------
  1535  
  1536  		{"", eqOperator, "", false, true},
  1537  		{"", eqOperator, "1", false, true},
  1538  		{"1", eqOperator, "", false, true},
  1539  
  1540  		{"foo", eqOperator, "", false, true},
  1541  		{"", eqOperator, "foo", false, true},
  1542  		{"foo", eqOperator, "1", false, true},
  1543  		{"1", eqOperator, "foo", false, true},
  1544  
  1545  		{"1", eqOperator, "1", true, false},
  1546  		{"1", eqOperator, "2", false, false},
  1547  
  1548  		//----------
  1549  
  1550  		{"", geOperator, "", false, true},
  1551  		{"foo", geOperator, "", false, true},
  1552  		{"", geOperator, "foo", false, true},
  1553  		{"1", geOperator, "", false, true},
  1554  		{"", geOperator, "1", false, true},
  1555  
  1556  		{"1", geOperator, "2", false, false},
  1557  		{"2", geOperator, "1", true, false},
  1558  		{"2", geOperator, "2", true, false},
  1559  
  1560  		//----------
  1561  
  1562  		{"", gtOperator, "", false, true},
  1563  		{"foo", gtOperator, "", false, true},
  1564  		{"", gtOperator, "foo", false, true},
  1565  		{"1", gtOperator, "", false, true},
  1566  		{"", gtOperator, "1", false, true},
  1567  
  1568  		{"2", gtOperator, "1", true, false},
  1569  		{"1", gtOperator, "2", false, false},
  1570  		{"1", gtOperator, "1", false, false},
  1571  
  1572  		//----------
  1573  
  1574  		{"", leOperator, "", false, true},
  1575  		{"foo", leOperator, "", false, true},
  1576  		{"", leOperator, "foo", false, true},
  1577  		{"1", leOperator, "", false, true},
  1578  		{"", leOperator, "1", false, true},
  1579  
  1580  		{"2", leOperator, "1", false, false},
  1581  		{"1", leOperator, "2", true, false},
  1582  		{"1", leOperator, "1", true, false},
  1583  
  1584  		//----------
  1585  
  1586  		{"", ltOperator, "", false, true},
  1587  		{"foo", ltOperator, "", false, true},
  1588  		{"", ltOperator, "foo", false, true},
  1589  		{"1", ltOperator, "", false, true},
  1590  		{"", ltOperator, "1", false, true},
  1591  
  1592  		{"1", ltOperator, "2", true, false},
  1593  		{"2", ltOperator, "1", false, false},
  1594  		{"1", ltOperator, "1", false, false},
  1595  
  1596  		//----------
  1597  
  1598  		{"", neOperator, "", false, true},
  1599  		{"foo", neOperator, "", false, true},
  1600  		{"", neOperator, "foo", false, true},
  1601  		{"1", neOperator, "", false, true},
  1602  		{"", neOperator, "1", false, true},
  1603  
  1604  		{"2", neOperator, "2", false, false},
  1605  		{"1", neOperator, "2", true, false},
  1606  		{"2", neOperator, "1", true, false},
  1607  	}
  1608  
  1609  	for i, d := range data {
  1610  		success, err := evalIntVersion(d.currentVer, d.op, d.newVer)
  1611  
  1612  		msg := fmt.Sprintf("test[%d]: %+v, success: %v", i, d, success)
  1613  
  1614  		if d.expectError {
  1615  			assert.Error(err, msg)
  1616  			continue
  1617  		}
  1618  
  1619  		if d.expectSuccess {
  1620  			assert.True(success, msg)
  1621  		} else {
  1622  			assert.False(success, msg)
  1623  		}
  1624  	}
  1625  }
  1626  
  1627  func TestEvalFloatVersion(t *testing.T) {
  1628  	assert := assert.New(t)
  1629  
  1630  	type testData struct {
  1631  		currentVer    string
  1632  		op            Operator
  1633  		newVer        string
  1634  		expectSuccess bool
  1635  		expectError   bool
  1636  	}
  1637  
  1638  	data := []testData{
  1639  		//----------
  1640  
  1641  		{"", eqOperator, "", false, true},
  1642  		{"foo", eqOperator, "", false, true},
  1643  		{"", eqOperator, "foo", false, true},
  1644  		{"foo", eqOperator, "1", false, true},
  1645  		{"1", eqOperator, "foo", false, true},
  1646  
  1647  		{"1", eqOperator, "1", true, false},
  1648  		{"1", eqOperator, "2", false, false},
  1649  
  1650  		{"1.1", eqOperator, "1.1", true, false},
  1651  		{"1.1", eqOperator, "2.1", false, false},
  1652  
  1653  		//----------
  1654  
  1655  		{"", geOperator, "", false, true},
  1656  		{"foo", geOperator, "", false, true},
  1657  		{"", geOperator, "foo", false, true},
  1658  
  1659  		{"1", geOperator, "2", false, false},
  1660  		{"2", geOperator, "1", true, false},
  1661  		{"2", geOperator, "2", true, false},
  1662  
  1663  		{"1.1", geOperator, "2.1", false, false},
  1664  		{"2.1", geOperator, "1.1", true, false},
  1665  		{"2.1", geOperator, "2.1", true, false},
  1666  
  1667  		//----------
  1668  
  1669  		{"", gtOperator, "", false, true},
  1670  		{"foo", gtOperator, "", false, true},
  1671  		{"", gtOperator, "foo", false, true},
  1672  
  1673  		{"2", gtOperator, "1", true, false},
  1674  		{"1", gtOperator, "2", false, false},
  1675  		{"1", gtOperator, "1", false, false},
  1676  
  1677  		{"2.1", gtOperator, "1.1", true, false},
  1678  		{"1.1", gtOperator, "2.1", false, false},
  1679  		{"1.1", gtOperator, "1.1", false, false},
  1680  
  1681  		//----------
  1682  
  1683  		{"", leOperator, "", false, true},
  1684  		{"foo", leOperator, "", false, true},
  1685  		{"", leOperator, "foo", false, true},
  1686  
  1687  		{"2", leOperator, "1", false, false},
  1688  		{"1", leOperator, "2", true, false},
  1689  		{"1", leOperator, "1", true, false},
  1690  
  1691  		{"2.1", leOperator, "1.1", false, false},
  1692  		{"1.1", leOperator, "2.1", true, false},
  1693  		{"1.1", leOperator, "1.1", true, false},
  1694  
  1695  		//----------
  1696  
  1697  		{"", ltOperator, "", false, true},
  1698  		{"foo", ltOperator, "", false, true},
  1699  		{"", ltOperator, "foo", false, true},
  1700  
  1701  		{"1", ltOperator, "2", true, false},
  1702  		{"2", ltOperator, "1", false, false},
  1703  		{"1", ltOperator, "1", false, false},
  1704  
  1705  		{"1.1", ltOperator, "2.1", true, false},
  1706  		{"2.1", ltOperator, "1.1", false, false},
  1707  		{"1.1", ltOperator, "1.1", false, false},
  1708  
  1709  		//----------
  1710  
  1711  		{"", neOperator, "", false, true},
  1712  		{"foo", neOperator, "", false, true},
  1713  		{"", neOperator, "foo", false, true},
  1714  
  1715  		{"2", neOperator, "2", false, false},
  1716  		{"1", neOperator, "2", true, false},
  1717  		{"2", neOperator, "1", true, false},
  1718  
  1719  		{"2.1", neOperator, "2.1", false, false},
  1720  		{"1.1", neOperator, "2.1", true, false},
  1721  		{"2.1", neOperator, "1.1", true, false},
  1722  	}
  1723  
  1724  	for i, d := range data {
  1725  		success, err := evalFloatVersion(d.currentVer, d.op, d.newVer)
  1726  
  1727  		msg := fmt.Sprintf("test[%d]: %+v, success: %v", i, d, success)
  1728  
  1729  		if d.expectError {
  1730  			assert.Error(err, msg)
  1731  			continue
  1732  		}
  1733  
  1734  		if d.expectSuccess {
  1735  			assert.True(success, msg)
  1736  		} else {
  1737  			assert.False(success, msg)
  1738  		}
  1739  	}
  1740  }
  1741  
  1742  func TestEvalSemverVersion(t *testing.T) {
  1743  	assert := assert.New(t)
  1744  
  1745  	type testData struct {
  1746  		currentVer    string
  1747  		op            Operator
  1748  		newVer        string
  1749  		expectSuccess bool
  1750  		expectError   bool
  1751  	}
  1752  
  1753  	data := []testData{
  1754  		//----------
  1755  
  1756  		{"", eqOperator, "", false, true},
  1757  		{"foo", eqOperator, "", false, true},
  1758  		{"", eqOperator, "foo", false, true},
  1759  		{"foo", eqOperator, "1", false, true},
  1760  		{"1", eqOperator, "foo", false, true},
  1761  
  1762  		{"1.1.1", eqOperator, "1.1.1", true, false},
  1763  		{"1.1.1", eqOperator, "2.2.2", false, false},
  1764  
  1765  		//----------
  1766  
  1767  		{"", geOperator, "", false, true},
  1768  		{"foo", geOperator, "", false, true},
  1769  		{"", geOperator, "foo", false, true},
  1770  
  1771  		{"1.1.1", geOperator, "2.2.2", false, false},
  1772  		{"2.2.2", geOperator, "1.1.1", true, false},
  1773  		{"2.2.2", geOperator, "2.2.2", true, false},
  1774  
  1775  		//----------
  1776  
  1777  		{"", gtOperator, "", false, true},
  1778  		{"foo", gtOperator, "", false, true},
  1779  		{"", gtOperator, "foo", false, true},
  1780  
  1781  		{"2.2.2", gtOperator, "1.1.1", true, false},
  1782  		{"1.1.1", gtOperator, "2.2.2", false, false},
  1783  		{"1.1.1", gtOperator, "1.1.1", false, false},
  1784  
  1785  		//----------
  1786  
  1787  		{"", leOperator, "", false, true},
  1788  		{"foo", leOperator, "", false, true},
  1789  		{"", leOperator, "foo", false, true},
  1790  
  1791  		{"2.2.2", leOperator, "1.1.1", false, false},
  1792  		{"1.1.1", leOperator, "2.2.2", true, false},
  1793  		{"1.1.1", leOperator, "1.1.1", true, false},
  1794  
  1795  		//----------
  1796  
  1797  		{"", ltOperator, "", false, true},
  1798  		{"foo", ltOperator, "", false, true},
  1799  		{"", ltOperator, "foo", false, true},
  1800  
  1801  		{"1.1.1", ltOperator, "2.2.2", true, false},
  1802  		{"2.2.2", ltOperator, "1.1.1", false, false},
  1803  		{"1.1.1", ltOperator, "1.1.1", false, false},
  1804  
  1805  		//----------
  1806  
  1807  		{"", neOperator, "", false, true},
  1808  		{"foo", neOperator, "", false, true},
  1809  		{"", neOperator, "foo", false, true},
  1810  
  1811  		{"2.2.2", neOperator, "2.2.2", false, false},
  1812  		{"1.1.1", neOperator, "2.2.2", true, false},
  1813  		{"2.2.2", neOperator, "1.1.1", true, false},
  1814  	}
  1815  
  1816  	for i, d := range data {
  1817  		success, err := evalSemverVersion(d.currentVer, d.op, d.newVer)
  1818  
  1819  		msg := fmt.Sprintf("test[%d]: %+v, success: %v", i, d, success)
  1820  
  1821  		if d.expectError {
  1822  			assert.Error(err, msg)
  1823  			continue
  1824  		}
  1825  
  1826  		if d.expectSuccess {
  1827  			assert.True(success, msg)
  1828  		} else {
  1829  			assert.False(success, msg)
  1830  		}
  1831  	}
  1832  }