go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/core/resources/versions/rpm/version_test.go (about)

     1  // Copyright 2016 clair authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rpm
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  const (
    24  	LESS    = -1
    25  	EQUAL   = 0
    26  	GREATER = 1
    27  )
    28  
    29  func TestParse(t *testing.T) {
    30  	cases := []struct {
    31  		str string
    32  		ver version
    33  		err bool
    34  	}{
    35  		// Test 0
    36  		{"0", version{epoch: 0, version: "0", release: ""}, false},
    37  		{"0:0", version{epoch: 0, version: "0", release: ""}, false},
    38  		{"0:0-", version{epoch: 0, version: "0", release: ""}, false},
    39  		{"0:0-0", version{epoch: 0, version: "0", release: "0"}, false},
    40  		{"0:0.0-0.0", version{epoch: 0, version: "0.0", release: "0.0"}, false},
    41  		// Test epoched
    42  		{"1:0", version{epoch: 1, version: "0", release: ""}, false},
    43  		{"5:1", version{epoch: 5, version: "1", release: ""}, false},
    44  		// Test multiple hyphens
    45  		{"0:0-0-0", version{epoch: 0, version: "0", release: "0-0"}, false},
    46  		{"0:0-0-0-0", version{epoch: 0, version: "0", release: "0-0-0"}, false},
    47  		// Test multiple colons
    48  		{"0:0:0-0", version{epoch: 0, version: "0:0", release: "0"}, false},
    49  		{"0:0:0:0-0", version{epoch: 0, version: "0:0:0", release: "0"}, false},
    50  		// Test multiple hyphens and colons
    51  		{"0:0:0-0-0", version{epoch: 0, version: "0:0", release: "0-0"}, false},
    52  		{"0:0-0:0-0", version{epoch: 0, version: "0", release: "0:0-0"}, false},
    53  		// Test version with leading and trailing spaces
    54  		{"  	0:0-1", version{epoch: 0, version: "0", release: "1"}, false},
    55  		{"0:0-1	  ", version{epoch: 0, version: "0", release: "1"}, false},
    56  		{"	  0:0-1  	", version{epoch: 0, version: "0", release: "1"}, false},
    57  		// Test empty version
    58  		{"", version{}, true},
    59  		{" ", version{}, true},
    60  		{"0:", version{}, true},
    61  		// Test version with embedded spaces
    62  		{"0:0 0-1", version{}, true},
    63  		// Test version with negative epoch
    64  		{"-1:0-1", version{}, true},
    65  		// Test invalid characters in epoch
    66  		{"a:0-0", version{}, true},
    67  		{"A:0-0", version{}, true},
    68  		// Test version not starting with a digit
    69  		{"0:abc3-0", version{epoch: 0, version: "abc3", release: "0"}, false},
    70  	}
    71  	for _, c := range cases {
    72  		v, err := newVersion(c.str)
    73  
    74  		if c.err {
    75  			assert.Error(t, err, "When parsing '%s'", c.str)
    76  		} else {
    77  			assert.Nil(t, err, "When parsing '%s'", c.str)
    78  		}
    79  		assert.Equal(t, c.ver, v, "When parsing '%s'", c.str)
    80  	}
    81  }
    82  
    83  func TestParseAndCompare(t *testing.T) {
    84  	cases := []struct {
    85  		v1       string
    86  		expected int
    87  		v2       string
    88  	}{
    89  		// Oracle Linux corner cases.
    90  		{"2.9.1-6.0.1.el7_2.3", GREATER, "2.9.1-6.el7_2.3"},
    91  		{"3.10.0-327.28.3.el7", GREATER, "3.10.0-327.el7"},
    92  		{"3.14.3-23.3.el6_8", GREATER, "3.14.3-23.el6_7"},
    93  		{"2.23.2-22.el7_1", LESS, "2.23.2-22.el7_1.1"},
    94  
    95  		// Tests imported from tests/rpmvercmp.at
    96  		{"1.0", EQUAL, "1.0"},
    97  		{"1.0", LESS, "2.0"},
    98  		{"2.0", GREATER, "1.0"},
    99  		{"2.0.1", EQUAL, "2.0.1"},
   100  		{"2.0", LESS, "2.0.1"},
   101  		{"2.0.1", GREATER, "2.0"},
   102  		{"2.0.1a", EQUAL, "2.0.1a"},
   103  		{"2.0.1a", GREATER, "2.0.1"},
   104  		{"2.0.1", LESS, "2.0.1a"},
   105  		{"5.5p1", EQUAL, "5.5p1"},
   106  		{"5.5p1", LESS, "5.5p2"},
   107  		{"5.5p2", GREATER, "5.5p1"},
   108  		{"5.5p10", EQUAL, "5.5p10"},
   109  		{"5.5p1", LESS, "5.5p10"},
   110  		{"5.5p10", GREATER, "5.5p1"},
   111  		{"10xyz", LESS, "10.1xyz"},
   112  		{"10.1xyz", GREATER, "10xyz"},
   113  		{"xyz10", EQUAL, "xyz10"},
   114  		{"xyz10", LESS, "xyz10.1"},
   115  		{"xyz10.1", GREATER, "xyz10"},
   116  		{"xyz.4", EQUAL, "xyz.4"},
   117  		{"xyz.4", LESS, "8"},
   118  		{"8", GREATER, "xyz.4"},
   119  		{"xyz.4", LESS, "2"},
   120  		{"2", GREATER, "xyz.4"},
   121  		{"5.5p2", LESS, "5.6p1"},
   122  		{"5.6p1", GREATER, "5.5p2"},
   123  		{"5.6p1", LESS, "6.5p1"},
   124  		{"6.5p1", GREATER, "5.6p1"},
   125  		{"6.0.rc1", GREATER, "6.0"},
   126  		{"6.0", LESS, "6.0.rc1"},
   127  		{"10b2", GREATER, "10a1"},
   128  		{"10a2", LESS, "10b2"},
   129  		{"1.0aa", EQUAL, "1.0aa"},
   130  		{"1.0a", LESS, "1.0aa"},
   131  		{"1.0aa", GREATER, "1.0a"},
   132  		{"10.0001", EQUAL, "10.0001"},
   133  		{"10.0001", EQUAL, "10.1"},
   134  		{"10.1", EQUAL, "10.0001"},
   135  		{"10.0001", LESS, "10.0039"},
   136  		{"10.0039", GREATER, "10.0001"},
   137  		{"4.999.9", LESS, "5.0"},
   138  		{"5.0", GREATER, "4.999.9"},
   139  		{"20101121", EQUAL, "20101121"},
   140  		{"20101121", LESS, "20101122"},
   141  		{"20101122", GREATER, "20101121"},
   142  		{"2_0", EQUAL, "2_0"},
   143  		{"2.0", EQUAL, "2_0"},
   144  		{"2_0", EQUAL, "2.0"},
   145  		{"a", EQUAL, "a"},
   146  		{"a+", EQUAL, "a+"},
   147  		{"a+", EQUAL, "a_"},
   148  		{"a_", EQUAL, "a+"},
   149  		{"+a", EQUAL, "+a"},
   150  		{"+a", EQUAL, "_a"},
   151  		{"_a", EQUAL, "+a"},
   152  		{"+_", EQUAL, "+_"},
   153  		{"_+", EQUAL, "+_"},
   154  		{"_+", EQUAL, "_+"},
   155  		{"+", EQUAL, "_"},
   156  		{"_", EQUAL, "+"},
   157  		{"1.0~rc1", EQUAL, "1.0~rc1"},
   158  		{"1.0~rc1", LESS, "1.0"},
   159  		{"1.0", GREATER, "1.0~rc1"},
   160  		{"1.0~rc1", LESS, "1.0~rc2"},
   161  		{"1.0~rc2", GREATER, "1.0~rc1"},
   162  		{"1.0~rc1~git123", EQUAL, "1.0~rc1~git123"},
   163  		{"1.0~rc1~git123", LESS, "1.0~rc1"},
   164  		{"1.0~rc1", GREATER, "1.0~rc1~git123"},
   165  		{"1~", GREATER, "1~~"},
   166  		{"2~", GREATER, "1"},
   167  		{"1.0", GREATER, "1.0-~"},
   168  		{"1.0", LESS, "1.0-1~"},
   169  		{"~", GREATER, "~~"},
   170  	}
   171  
   172  	var (
   173  		p   Parser
   174  		cmp int
   175  		err error
   176  	)
   177  	for _, c := range cases {
   178  		cmp, err = p.Compare(c.v1, c.v2)
   179  		assert.Nil(t, err)
   180  		assert.Equal(t, c.expected, cmp, "%s vs. %s, = %d, expected %d", c.v1, c.v2, cmp, c.expected)
   181  
   182  		cmp, err = p.Compare(c.v2, c.v1)
   183  		assert.Nil(t, err)
   184  		assert.Equal(t, -c.expected, cmp, "%s vs. %s, = %d, expected %d", c.v2, c.v1, cmp, -c.expected)
   185  	}
   186  }