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

     1  // Copyright (c) 2019 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  // This file contains the public API for the test constraints facility.
     7  
     8  package katatestutils
     9  
    10  import (
    11  	"os"
    12  	"strings"
    13  )
    14  
    15  // Operator represents an operator to apply to a test constraint value.
    16  type Operator int
    17  
    18  const (
    19  	eqOperator Operator = iota
    20  	geOperator Operator = iota
    21  	gtOperator Operator = iota
    22  	leOperator Operator = iota
    23  	ltOperator Operator = iota
    24  	neOperator Operator = iota
    25  )
    26  
    27  // Constraints encapsulates all information about a test constraint.
    28  type Constraints struct {
    29  	Issue string
    30  
    31  	UID int
    32  
    33  	// Not ideal: set when UID needs to be checked. This allows
    34  	// a test for UID 0 to be detected.
    35  	UIDSet bool
    36  
    37  	// DistroName is the name of a distro in all lower-case letters.
    38  	DistroName string
    39  
    40  	// DistroVersion is the version of the particular distro in string
    41  	// format. It may contain periods and dashes.
    42  	DistroVersion string
    43  
    44  	// KernelVersion is the version of a particular kernel.
    45  	KernelVersion string
    46  
    47  	// Operator is the operator to apply to one of the constraints.
    48  	Operator Operator
    49  }
    50  
    51  // Constraint is a function that operates on a Constraints object to set
    52  // particular values.
    53  type Constraint func(c *Constraints)
    54  
    55  // TestConstraint records details about test constraints.
    56  type TestConstraint struct {
    57  	Debug bool
    58  
    59  	// Effective user ID of running test
    60  	ActualEUID int
    61  
    62  	DistroName    string
    63  	DistroVersion string
    64  	KernelVersion string
    65  
    66  	// Used to record all passed and failed constraints in
    67  	// human-readable form.
    68  	Passed []Result
    69  	Failed []Result
    70  
    71  	// Optionally used to record an issue number that relates to the
    72  	// constraint.
    73  	Issue string
    74  }
    75  
    76  // NewKataTest creates a new TestConstraint object and is the main interface
    77  // to the test constraints feature.
    78  func NewTestConstraint(debug bool) TestConstraint {
    79  	distroName, distroVersion, err := getDistroDetails()
    80  	if err != nil {
    81  		panic(err)
    82  	}
    83  
    84  	kernelVersion, err := getKernelVersion()
    85  	if err != nil {
    86  		panic(err)
    87  	}
    88  
    89  	return TestConstraint{
    90  		Debug: debug,
    91  
    92  		ActualEUID:    os.Geteuid(),
    93  		DistroName:    distroName,
    94  		DistroVersion: distroVersion,
    95  		KernelVersion: kernelVersion,
    96  	}
    97  }
    98  
    99  // NotValid checks if the specified list of constraints are all valid,
   100  // returning true if any _fail_.
   101  //
   102  // Notes:
   103  //
   104  // - Constraints are applied in the order specified.
   105  // - A constraint type (user, distro) can only be specified once.
   106  // - If the function fails to determine whether it can check the constraints,
   107  //   it will panic. Since this is facility is used for testing, this seems like
   108  //   the best approach as it unburdens the caller from checking for an error
   109  //   (which should never be ignored).
   110  func (tc *TestConstraint) NotValid(constraints ...Constraint) bool {
   111  	if len(constraints) == 0 {
   112  		panic("need atleast one constraint")
   113  	}
   114  
   115  	// Reset in case of a previous call
   116  	tc.Passed = nil
   117  	tc.Failed = nil
   118  	tc.Issue = ""
   119  
   120  	for _, c := range constraints {
   121  		valid := tc.constraintValid(c)
   122  		if !valid {
   123  			return true
   124  		}
   125  	}
   126  
   127  	return false
   128  }
   129  
   130  // NeedUID skips the test unless running as a user with the specified user ID.
   131  func NeedUID(uid int, op Operator) Constraint {
   132  	return func(c *Constraints) {
   133  		c.Operator = op
   134  		c.UID = uid
   135  		c.UIDSet = true
   136  	}
   137  }
   138  
   139  // NeedNonRoot skips the test unless running as root.
   140  func NeedRoot() Constraint {
   141  	return NeedUID(0, eqOperator)
   142  }
   143  
   144  // NeedNonRoot skips the test if running as the root user.
   145  func NeedNonRoot() Constraint {
   146  	return NeedUID(0, neOperator)
   147  }
   148  
   149  // NeedDistroWithOp skips the test unless the distro constraint specified by
   150  // the arguments is true.
   151  func NeedDistroWithOp(distro string, op Operator) Constraint {
   152  	return func(c *Constraints) {
   153  		c.DistroName = strings.ToLower(distro)
   154  		c.Operator = op
   155  	}
   156  }
   157  
   158  // NeedDistroEquals will skip the test unless running on the specified distro.
   159  func NeedDistroEquals(distro string) Constraint {
   160  	return NeedDistroWithOp(distro, eqOperator)
   161  }
   162  
   163  // NeedDistroNotEquals will skip the test unless run a distro that does not
   164  // match the specified name.
   165  func NeedDistroNotEquals(distro string) Constraint {
   166  	return NeedDistroWithOp(distro, neOperator)
   167  }
   168  
   169  // NeedDistro will skip the test unless running on the specified distro.
   170  func NeedDistro(distro string) Constraint {
   171  	return NeedDistroEquals(distro)
   172  }
   173  
   174  // NeedDistroVersionWithOp skips the test unless the distro version constraint
   175  // specified by the arguments is true.
   176  //
   177  // Note: distro versions vary in format.
   178  func NeedDistroVersionWithOp(version string, op Operator) Constraint {
   179  	return func(c *Constraints) {
   180  		c.DistroVersion = version
   181  		c.Operator = op
   182  	}
   183  }
   184  
   185  // NeedDistroVersionEquals will skip the test unless the distro version is the
   186  // same as the specified version.
   187  //
   188  // Note: distro versions vary in format.
   189  func NeedDistroVersionEquals(version string) Constraint {
   190  	return NeedDistroVersionWithOp(version, eqOperator)
   191  }
   192  
   193  // NeedDistroVersionNotEquals will skip the test unless the distro version is
   194  // different to the specified version.
   195  //
   196  // Note: distro versions vary in format.
   197  func NeedDistroVersionNotEquals(version string) Constraint {
   198  	return NeedDistroVersionWithOp(version, neOperator)
   199  }
   200  
   201  // NeedDistroVersionLE will skip the test unless the distro version is older
   202  // than or the same as the specified version.
   203  //
   204  // Note: distro versions vary in format.
   205  func NeedDistroVersionLE(version string) Constraint {
   206  	return NeedDistroVersionWithOp(version, leOperator)
   207  }
   208  
   209  // NeedDistroVersionLT will skip the test unless the distro version is older
   210  // than the specified version.
   211  //
   212  // Note: distro versions vary in format.
   213  func NeedDistroVersionLT(version string) Constraint {
   214  	return NeedDistroVersionWithOp(version, ltOperator)
   215  }
   216  
   217  // NeedDistroVersionGE will skip the test unless the distro version is newer
   218  // than or the same as the specified version.
   219  //
   220  // Note: distro versions vary in format.
   221  func NeedDistroVersionGE(version string) Constraint {
   222  	return NeedDistroVersionWithOp(version, geOperator)
   223  }
   224  
   225  // NeedDistroVersionGT will skip the test unless the distro version is newer
   226  // than the specified version.
   227  //
   228  // Note: distro versions vary in format.
   229  func NeedDistroVersionGT(version string) Constraint {
   230  	return NeedDistroVersionWithOp(version, gtOperator)
   231  }
   232  
   233  // NeedDistroVersion will skip the test unless running on the specified
   234  // (exact) version of some distro.
   235  //
   236  // Note: distro versions vary in format.
   237  func NeedDistroVersion(version string) Constraint {
   238  	return NeedDistroVersionEquals(version)
   239  }
   240  
   241  // NeedKernelVersionWithOp skips the test unless the distro version constraint
   242  // specified by the arguments is true.
   243  func NeedKernelVersionWithOp(version string, op Operator) Constraint {
   244  	return func(c *Constraints) {
   245  		c.KernelVersion = version
   246  		c.Operator = op
   247  	}
   248  }
   249  
   250  // NeedKernelVersionLT will skip the test unless the distro version is older
   251  // than the specified version.
   252  func NeedKernelVersionEquals(version string) Constraint {
   253  	return NeedKernelVersionWithOp(version, eqOperator)
   254  }
   255  
   256  // NeedKernelVersionNotEquals will skip the test unless the distro version is
   257  // different to the specified version.
   258  func NeedKernelVersionNotEquals(version string) Constraint {
   259  	return NeedKernelVersionWithOp(version, neOperator)
   260  }
   261  
   262  // NeedKernelVersionLT will skip the test unless the distro version is older
   263  // than the specified version.
   264  //
   265  // Note: distro versions vary in format.
   266  func NeedKernelVersionLT(version string) Constraint {
   267  	return NeedKernelVersionWithOp(version, ltOperator)
   268  }
   269  
   270  // NeedKernelVersionLE will skip the test unless the distro version is older
   271  // than or the same as the specified version.
   272  //
   273  // Note: distro versions vary in format.
   274  func NeedKernelVersionLE(version string) Constraint {
   275  	return NeedKernelVersionWithOp(version, leOperator)
   276  }
   277  
   278  // NeedKernelVersionGT will skip the test unless the distro version is newer
   279  // than the specified version.
   280  //
   281  // Note: distro versions vary in format.
   282  func NeedKernelVersionGT(version string) Constraint {
   283  	return NeedKernelVersionWithOp(version, gtOperator)
   284  }
   285  
   286  // NeedKernelVersionGE will skip the test unless the distro version is newer
   287  // than or the same as the specified version.
   288  //
   289  // Note: distro versions vary in format.
   290  func NeedKernelVersionGE(version string) Constraint {
   291  	return NeedKernelVersionWithOp(version, geOperator)
   292  }
   293  
   294  // NeedKernelVersion will skip the test unless running on the specified
   295  // (exact) version of some distro.
   296  //
   297  // Note: distro versions vary in format.
   298  func NeedKernelVersion(version string) Constraint {
   299  	return NeedKernelVersionEquals(version)
   300  }
   301  
   302  // WithIssue allows the specification of an issue URL.
   303  //
   304  // Note that the issue is not checked for validity.
   305  func WithIssue(issue string) Constraint {
   306  	return func(c *Constraints) {
   307  		c.Issue = issue
   308  	}
   309  }