sigs.k8s.io/cluster-api@v1.7.1/util/version/version_test.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package version
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/blang/semver/v4"
    23  	. "github.com/onsi/gomega"
    24  )
    25  
    26  func TestParseMajorMinorPatch(t *testing.T) {
    27  	g := NewWithT(t)
    28  
    29  	var testcases = []struct {
    30  		name        string
    31  		input       string
    32  		output      semver.Version
    33  		expectError bool
    34  	}{
    35  		{
    36  			name:  "should parse an OCI compliant string",
    37  			input: "v1.2.16_foo-1",
    38  			output: semver.Version{
    39  				Major: 1,
    40  				Minor: 2,
    41  				Patch: 16,
    42  			},
    43  		},
    44  		{
    45  			name:  "should parse a valid semver",
    46  			input: "v1.16.6+foobar-0",
    47  			output: semver.Version{
    48  				Major: 1,
    49  				Minor: 16,
    50  				Patch: 6,
    51  			},
    52  		},
    53  		{
    54  			name:        "should error if there is no patch version",
    55  			input:       "v1.16+foobar-0",
    56  			expectError: true,
    57  		},
    58  		{
    59  			name:        "should error if there is no minor and patch",
    60  			input:       "v1+foobar-0",
    61  			expectError: true,
    62  		},
    63  		{
    64  			name:        "should error if there is no v prefix",
    65  			input:       "1.4.7",
    66  			expectError: true,
    67  		},
    68  	}
    69  
    70  	for _, tc := range testcases {
    71  		t.Run(tc.name, func(*testing.T) {
    72  			out, err := ParseMajorMinorPatch(tc.input)
    73  			g.Expect(err != nil).To(Equal(tc.expectError))
    74  			g.Expect(out).To(BeComparableTo(tc.output))
    75  		})
    76  	}
    77  }
    78  
    79  func TestParseMajorMinorPatchTolerant(t *testing.T) {
    80  	g := NewWithT(t)
    81  
    82  	var testcases = []struct {
    83  		name        string
    84  		input       string
    85  		output      semver.Version
    86  		expectError bool
    87  	}{
    88  		{
    89  			name:  "should parse an OCI compliant string",
    90  			input: "v1.2.16_foo-1",
    91  			output: semver.Version{
    92  				Major: 1,
    93  				Minor: 2,
    94  				Patch: 16,
    95  			},
    96  		},
    97  		{
    98  			name:  "should parse a valid semver with no v prefix",
    99  			input: "1.16.6+foobar-0",
   100  			output: semver.Version{
   101  				Major: 1,
   102  				Minor: 16,
   103  				Patch: 6,
   104  			},
   105  		},
   106  		{
   107  			name:        "should error if there is no patch version",
   108  			input:       "1.16+foobar-0",
   109  			expectError: true,
   110  		},
   111  		{
   112  			name:        "should error if there is no minor and patch",
   113  			input:       "1+foobar-0",
   114  			expectError: true,
   115  		},
   116  	}
   117  
   118  	for _, tc := range testcases {
   119  		t.Run(tc.name, func(*testing.T) {
   120  			out, err := ParseMajorMinorPatchTolerant(tc.input)
   121  			g.Expect(err != nil).To(Equal(tc.expectError))
   122  			g.Expect(out).To(BeComparableTo(tc.output))
   123  		})
   124  	}
   125  }
   126  
   127  func TestCompare(t *testing.T) {
   128  	tests := []struct {
   129  		name     string
   130  		aVersion semver.Version
   131  		bVersion semver.Version
   132  		options  []CompareOption
   133  		want     int
   134  	}{
   135  		{
   136  			name:     "comparing with no options should perform standard compare",
   137  			aVersion: semver.MustParse("1.2.3"),
   138  			bVersion: semver.MustParse("1.3.1"),
   139  			want:     -1,
   140  		},
   141  		{
   142  			name:     "comparing with no options should perform standard compare - equal versions",
   143  			aVersion: semver.MustParse("1.2.3+xyz.1"),
   144  			bVersion: semver.MustParse("1.2.3+xyz.2"),
   145  			want:     0,
   146  		},
   147  		{
   148  			name:     "compare with build tags using the WithBuildTags option",
   149  			aVersion: semver.MustParse("1.2.3+xyz.1"),
   150  			bVersion: semver.MustParse("1.2.3+xyz.2"),
   151  			options:  []CompareOption{WithBuildTags()},
   152  			want:     -1,
   153  		},
   154  		{
   155  			name:     "compare with no build identifiers",
   156  			aVersion: mustParseTolerant("v1.20.1"),
   157  			bVersion: mustParseTolerant("v1.20.2"),
   158  			options:  []CompareOption{WithBuildTags()},
   159  			want:     -1,
   160  		},
   161  		{
   162  			name:     "compare with pre release versions and no build identifiers",
   163  			aVersion: mustParseTolerant("v1.20.1-alpha.1"),
   164  			bVersion: mustParseTolerant("v1.20.1-alpha.2"),
   165  			options:  []CompareOption{WithBuildTags()},
   166  			want:     -1,
   167  		},
   168  		{
   169  			name:     "compare with pre release versions and build identifiers",
   170  			aVersion: mustParseTolerant("v1.20.1-alpha.1+xyz.1"),
   171  			bVersion: mustParseTolerant("v1.20.1-alpha.1+xyz.2"),
   172  			options:  []CompareOption{WithBuildTags()},
   173  			want:     -1,
   174  		},
   175  		{
   176  			name:     "compare with build identifiers - smaller",
   177  			aVersion: mustParseTolerant("v1.20.1+xyz.1"),
   178  			bVersion: mustParseTolerant("v1.20.1+xyz.2"),
   179  			options:  []CompareOption{WithBuildTags()},
   180  			want:     -1,
   181  		},
   182  		{
   183  			name:     "compare with build identifiers - equal",
   184  			aVersion: mustParseTolerant("v1.20.1+xyz.1"),
   185  			bVersion: mustParseTolerant("v1.20.1+xyz.1"),
   186  			options:  []CompareOption{WithBuildTags()},
   187  			want:     0,
   188  		},
   189  		{
   190  			name:     "compare with build identifiers - greater",
   191  			aVersion: mustParseTolerant("v1.20.1+xyz.3"),
   192  			bVersion: mustParseTolerant("v1.20.1+xyz.2"),
   193  			options:  []CompareOption{WithBuildTags()},
   194  			want:     1,
   195  		},
   196  		{
   197  			name:     "compare with build identifiers - smaller by sub version",
   198  			aVersion: mustParseTolerant("v1.20.1+xyz.1.0"),
   199  			bVersion: mustParseTolerant("v1.20.1+xyz.1.1"),
   200  			options:  []CompareOption{WithBuildTags()},
   201  			want:     -1,
   202  		},
   203  		{
   204  			name:     "compare with build identifiers - smaller - different version lengths",
   205  			aVersion: mustParseTolerant("v1.20.1+xyz.1.1"),
   206  			bVersion: mustParseTolerant("v1.20.1+xyz.2"),
   207  			options:  []CompareOption{WithBuildTags()},
   208  			want:     -1,
   209  		},
   210  		{
   211  			name:     "compare with build identifiers - greater by length",
   212  			aVersion: mustParseTolerant("v1.20.1+xyz.1.1"),
   213  			bVersion: mustParseTolerant("v1.20.1+xyz.1"),
   214  			options:  []CompareOption{WithBuildTags()},
   215  			want:     1,
   216  		},
   217  		{
   218  			name:     "compare with build identifiers - different non numeric",
   219  			aVersion: mustParseTolerant("v1.20.1+xyz.a"),
   220  			bVersion: mustParseTolerant("v1.20.1+xyz.b"),
   221  			options:  []CompareOption{WithBuildTags()},
   222  			want:     2,
   223  		},
   224  		{
   225  			name:     "compare with build identifiers - equal non numeric",
   226  			aVersion: mustParseTolerant("v1.20.1+xyz.a"),
   227  			bVersion: mustParseTolerant("v1.20.1+xyz.a"),
   228  			options:  []CompareOption{WithBuildTags()},
   229  			want:     0,
   230  		},
   231  		{
   232  			name:     "compare with build identifiers - smaller - a is numeric b is not",
   233  			aVersion: mustParseTolerant("v1.20.1+xyz.1"),
   234  			bVersion: mustParseTolerant("v1.20.1+xyz.abc"),
   235  			options:  []CompareOption{WithBuildTags()},
   236  			want:     -1,
   237  		},
   238  	}
   239  
   240  	for _, tt := range tests {
   241  		t.Run(tt.name, func(t *testing.T) {
   242  			g := NewWithT(t)
   243  			g.Expect(Compare(tt.aVersion, tt.bVersion, tt.options...)).To(Equal(tt.want))
   244  		})
   245  	}
   246  }
   247  
   248  func mustParseTolerant(s string) semver.Version {
   249  	v, err := semver.ParseTolerant(s)
   250  	if err != nil {
   251  		panic(`semver: ParseTolerant(` + s + `): ` + err.Error())
   252  	}
   253  	return v
   254  }