github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/util/version/version_test.go (about)

     1  /*
     2  Copyright 2016 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  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  )
    24  
    25  type testItem struct {
    26  	version    string
    27  	unparsed   string
    28  	equalsPrev bool
    29  }
    30  
    31  func testOne(v *Version, item, prev testItem) error {
    32  	str := v.String()
    33  	if item.unparsed == "" {
    34  		if str != item.version {
    35  			return fmt.Errorf("bad round-trip: %q -> %q", item.version, str)
    36  		}
    37  	} else {
    38  		if str != item.unparsed {
    39  			return fmt.Errorf("bad unparse: %q -> %q, expected %q", item.version, str, item.unparsed)
    40  		}
    41  	}
    42  
    43  	if prev.version != "" {
    44  		cmp, err := v.Compare(prev.version)
    45  		if err != nil {
    46  			return fmt.Errorf("unexpected parse error: %v", err)
    47  		}
    48  		rv, err := parse(prev.version, v.semver)
    49  		if err != nil {
    50  			return fmt.Errorf("unexpected parse error: %v", err)
    51  		}
    52  		rcmp, err := rv.Compare(item.version)
    53  		if err != nil {
    54  			return fmt.Errorf("unexpected parse error: %v", err)
    55  		}
    56  
    57  		switch {
    58  		case cmp == -1:
    59  			return fmt.Errorf("unexpected ordering %q < %q", item.version, prev.version)
    60  		case cmp == 0 && !item.equalsPrev:
    61  			return fmt.Errorf("unexpected comparison %q == %q", item.version, prev.version)
    62  		case cmp == 1 && item.equalsPrev:
    63  			return fmt.Errorf("unexpected comparison %q != %q", item.version, prev.version)
    64  		case cmp != -rcmp:
    65  			return fmt.Errorf("unexpected reverse comparison %q <=> %q %v %v %v %v", item.version, prev.version, cmp, rcmp, v.Components(), rv.Components())
    66  		}
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func TestSemanticVersions(t *testing.T) {
    73  	tests := []testItem{
    74  		// This is every version string that appears in the 2.0 semver spec,
    75  		// sorted in strictly increasing order except as noted.
    76  		{version: "0.1.0"},
    77  		{version: "1.0.0-0.3.7"},
    78  		{version: "1.0.0-alpha"},
    79  		{version: "1.0.0-alpha+001", equalsPrev: true},
    80  		{version: "1.0.0-alpha.1"},
    81  		{version: "1.0.0-alpha.beta"},
    82  		{version: "1.0.0-beta"},
    83  		{version: "1.0.0-beta+exp.sha.5114f85", equalsPrev: true},
    84  		{version: "1.0.0-beta.2"},
    85  		{version: "1.0.0-beta.11"},
    86  		{version: "1.0.0-rc.1"},
    87  		{version: "1.0.0-x.7.z.92"},
    88  		{version: "1.0.0"},
    89  		{version: "1.0.0+20130313144700", equalsPrev: true},
    90  		{version: "1.8.0-alpha.3"},
    91  		{version: "1.8.0-alpha.3.673+73326ef01d2d7c"},
    92  		{version: "1.9.0"},
    93  		{version: "1.10.0"},
    94  		{version: "1.11.0"},
    95  		{version: "2.0.0"},
    96  		{version: "2.1.0"},
    97  		{version: "2.1.1"},
    98  		{version: "42.0.0"},
    99  
   100  		// We also allow whitespace and "v" prefix
   101  		{version: "   42.0.0", unparsed: "42.0.0", equalsPrev: true},
   102  		{version: "\t42.0.0  ", unparsed: "42.0.0", equalsPrev: true},
   103  		{version: "43.0.0-1", unparsed: "43.0.0-1"},
   104  		{version: "43.0.0-1  ", unparsed: "43.0.0-1", equalsPrev: true},
   105  		{version: "v43.0.0-1", unparsed: "43.0.0-1", equalsPrev: true},
   106  		{version: "  v43.0.0", unparsed: "43.0.0"},
   107  		{version: " 43.0.0 ", unparsed: "43.0.0", equalsPrev: true},
   108  	}
   109  
   110  	var prev testItem
   111  	for _, item := range tests {
   112  		v, err := ParseSemantic(item.version)
   113  		if err != nil {
   114  			t.Errorf("unexpected parse error: %v", err)
   115  			continue
   116  		}
   117  		err = testOne(v, item, prev)
   118  		if err != nil {
   119  			t.Errorf("%v", err)
   120  		}
   121  		prev = item
   122  	}
   123  }
   124  
   125  func TestBadSemanticVersions(t *testing.T) {
   126  	tests := []string{
   127  		// "MUST take the form X.Y.Z"
   128  		"1",
   129  		"1.2",
   130  		"1.2.3.4",
   131  		".2.3",
   132  		"1..3",
   133  		"1.2.",
   134  		"",
   135  		"..",
   136  		// "where X, Y, and Z are non-negative integers"
   137  		"-1.2.3",
   138  		"1.-2.3",
   139  		"1.2.-3",
   140  		"1a.2.3",
   141  		"1.2a.3",
   142  		"1.2.3a",
   143  		"a1.2.3",
   144  		"a.b.c",
   145  		"1 .2.3",
   146  		"1. 2.3",
   147  		// "and MUST NOT contain leading zeroes."
   148  		"01.2.3",
   149  		"1.02.3",
   150  		"1.2.03",
   151  		// "[pre-release] identifiers MUST comprise only ASCII alphanumerics and hyphen"
   152  		"1.2.3-/",
   153  		// "[pre-release] identifiers MUST NOT be empty"
   154  		"1.2.3-",
   155  		"1.2.3-.",
   156  		"1.2.3-foo.",
   157  		"1.2.3-.foo",
   158  		// "Numeric [pre-release] identifiers MUST NOT include leading zeroes"
   159  		"1.2.3-01",
   160  		// "[build metadata] identifiers MUST comprise only ASCII alphanumerics and hyphen"
   161  		"1.2.3+/",
   162  		// "[build metadata] identifiers MUST NOT be empty"
   163  		"1.2.3+",
   164  		"1.2.3+.",
   165  		"1.2.3+foo.",
   166  		"1.2.3+.foo",
   167  
   168  		// whitespace/"v"-prefix checks
   169  		"v 1.2.3",
   170  		"vv1.2.3",
   171  	}
   172  
   173  	for i := range tests {
   174  		_, err := ParseSemantic(tests[i])
   175  		if err == nil {
   176  			t.Errorf("unexpected success parsing invalid semver %q", tests[i])
   177  		}
   178  	}
   179  }
   180  
   181  func TestGenericVersions(t *testing.T) {
   182  	tests := []testItem{
   183  		// This is all of the strings from TestSemanticVersions, plus some strings
   184  		// from TestBadSemanticVersions that should parse as generic versions,
   185  		// plus some additional strings.
   186  		{version: "0.1.0", unparsed: "0.1.0"},
   187  		{version: "1.0.0-0.3.7", unparsed: "1.0.0"},
   188  		{version: "1.0.0-alpha", unparsed: "1.0.0", equalsPrev: true},
   189  		{version: "1.0.0-alpha+001", unparsed: "1.0.0", equalsPrev: true},
   190  		{version: "1.0.0-alpha.1", unparsed: "1.0.0", equalsPrev: true},
   191  		{version: "1.0.0-alpha.beta", unparsed: "1.0.0", equalsPrev: true},
   192  		{version: "1.0.0.beta", unparsed: "1.0.0", equalsPrev: true},
   193  		{version: "1.0.0-beta+exp.sha.5114f85", unparsed: "1.0.0", equalsPrev: true},
   194  		{version: "1.0.0.beta.2", unparsed: "1.0.0", equalsPrev: true},
   195  		{version: "1.0.0.beta.11", unparsed: "1.0.0", equalsPrev: true},
   196  		{version: "1.0.0.rc.1", unparsed: "1.0.0", equalsPrev: true},
   197  		{version: "1.0.0-x.7.z.92", unparsed: "1.0.0", equalsPrev: true},
   198  		{version: "1.0.0", unparsed: "1.0.0", equalsPrev: true},
   199  		{version: "1.0.0+20130313144700", unparsed: "1.0.0", equalsPrev: true},
   200  		{version: "1.2", unparsed: "1.2"},
   201  		{version: "1.2a.3", unparsed: "1.2", equalsPrev: true},
   202  		{version: "1.2.3", unparsed: "1.2.3"},
   203  		{version: "1.2.3.0", unparsed: "1.2.3.0", equalsPrev: true},
   204  		{version: "1.2.3a", unparsed: "1.2.3", equalsPrev: true},
   205  		{version: "1.2.3-foo.", unparsed: "1.2.3", equalsPrev: true},
   206  		{version: "1.2.3-.foo", unparsed: "1.2.3", equalsPrev: true},
   207  		{version: "1.2.3-01", unparsed: "1.2.3", equalsPrev: true},
   208  		{version: "1.2.3+", unparsed: "1.2.3", equalsPrev: true},
   209  		{version: "1.2.3+foo.", unparsed: "1.2.3", equalsPrev: true},
   210  		{version: "1.2.3+.foo", unparsed: "1.2.3", equalsPrev: true},
   211  		{version: "1.02.3", unparsed: "1.2.3", equalsPrev: true},
   212  		{version: "1.2.03", unparsed: "1.2.3", equalsPrev: true},
   213  		{version: "1.2.003", unparsed: "1.2.3", equalsPrev: true},
   214  		{version: "1.2.3.4", unparsed: "1.2.3.4"},
   215  		{version: "1.2.3.4b3", unparsed: "1.2.3.4", equalsPrev: true},
   216  		{version: "1.2.3.4.5", unparsed: "1.2.3.4.5"},
   217  		{version: "1.9.0", unparsed: "1.9.0"},
   218  		{version: "1.9.0.0.0.0.0.0", unparsed: "1.9.0.0.0.0.0.0", equalsPrev: true},
   219  		{version: "1.10.0", unparsed: "1.10.0"},
   220  		{version: "1.11.0", unparsed: "1.11.0"},
   221  		{version: "1.11.0.0.5", unparsed: "1.11.0.0.5"},
   222  		{version: "2.0.0", unparsed: "2.0.0"},
   223  		{version: "2.1.0", unparsed: "2.1.0"},
   224  		{version: "2.1.1", unparsed: "2.1.1"},
   225  		{version: "42.0.0", unparsed: "42.0.0"},
   226  		{version: "   42.0.0", unparsed: "42.0.0", equalsPrev: true},
   227  		{version: "\t42.0.0  ", unparsed: "42.0.0", equalsPrev: true},
   228  		{version: "42.0.0-1", unparsed: "42.0.0", equalsPrev: true},
   229  		{version: "42.0.0-1  ", unparsed: "42.0.0", equalsPrev: true},
   230  		{version: "v42.0.0-1", unparsed: "42.0.0", equalsPrev: true},
   231  		{version: "  v43.0.0", unparsed: "43.0.0"},
   232  		{version: " 43.0.0 ", unparsed: "43.0.0", equalsPrev: true},
   233  	}
   234  
   235  	var prev testItem
   236  	for _, item := range tests {
   237  		v, err := ParseGeneric(item.version)
   238  		if err != nil {
   239  			t.Errorf("unexpected parse error: %v", err)
   240  			continue
   241  		}
   242  		err = testOne(v, item, prev)
   243  		if err != nil {
   244  			t.Errorf("%v", err)
   245  		}
   246  		prev = item
   247  	}
   248  }
   249  
   250  func TestBadGenericVersions(t *testing.T) {
   251  	tests := []string{
   252  		"1",
   253  		"01.2.3",
   254  		"-1.2.3",
   255  		"1.-2.3",
   256  		".2.3",
   257  		"1..3",
   258  		"1a.2.3",
   259  		"a1.2.3",
   260  		"1 .2.3",
   261  		"1. 2.3",
   262  		"1.bob",
   263  		"bob",
   264  		"v 1.2.3",
   265  		"vv1.2.3",
   266  		"",
   267  		".",
   268  	}
   269  
   270  	for i := range tests {
   271  		_, err := ParseGeneric(tests[i])
   272  		if err == nil {
   273  			t.Errorf("unexpected success parsing invalid version %q", tests[i])
   274  		}
   275  	}
   276  }
   277  
   278  func TestComponents(t *testing.T) {
   279  
   280  	var tests = []struct {
   281  		version               string
   282  		semver                bool
   283  		expectedComponents    []uint
   284  		expectedMajor         uint
   285  		expectedMinor         uint
   286  		expectedPatch         uint
   287  		expectedPreRelease    string
   288  		expectedBuildMetadata string
   289  	}{
   290  		{
   291  			version:            "1.0.2",
   292  			semver:             true,
   293  			expectedComponents: []uint{1, 0, 2},
   294  			expectedMajor:      1,
   295  			expectedMinor:      0,
   296  			expectedPatch:      2,
   297  		},
   298  		{
   299  			version:               "1.0.2-alpha+001",
   300  			semver:                true,
   301  			expectedComponents:    []uint{1, 0, 2},
   302  			expectedMajor:         1,
   303  			expectedMinor:         0,
   304  			expectedPatch:         2,
   305  			expectedPreRelease:    "alpha",
   306  			expectedBuildMetadata: "001",
   307  		},
   308  		{
   309  			version:            "1.2",
   310  			semver:             false,
   311  			expectedComponents: []uint{1, 2},
   312  			expectedMajor:      1,
   313  			expectedMinor:      2,
   314  		},
   315  		{
   316  			version:               "1.0.2-beta+exp.sha.5114f85",
   317  			semver:                true,
   318  			expectedComponents:    []uint{1, 0, 2},
   319  			expectedMajor:         1,
   320  			expectedMinor:         0,
   321  			expectedPatch:         2,
   322  			expectedPreRelease:    "beta",
   323  			expectedBuildMetadata: "exp.sha.5114f85",
   324  		},
   325  	}
   326  
   327  	for _, test := range tests {
   328  		version, _ := parse(test.version, test.semver)
   329  		if !reflect.DeepEqual(test.expectedComponents, version.Components()) {
   330  			t.Error("parse returned un'expected components")
   331  		}
   332  		if test.expectedMajor != version.Major() {
   333  			t.Errorf("parse returned version.Major %d, expected %d", test.expectedMajor, version.Major())
   334  		}
   335  		if test.expectedMinor != version.Minor() {
   336  			t.Errorf("parse returned version.Minor %d, expected %d", test.expectedMinor, version.Minor())
   337  		}
   338  		if test.expectedPatch != version.Patch() {
   339  			t.Errorf("parse returned version.Patch %d, expected %d", test.expectedPatch, version.Patch())
   340  		}
   341  		if test.expectedPreRelease != version.PreRelease() {
   342  			t.Errorf("parse returned version.PreRelease %s, expected %s", test.expectedPreRelease, version.PreRelease())
   343  		}
   344  		if test.expectedBuildMetadata != version.BuildMetadata() {
   345  			t.Errorf("parse returned version.BuildMetadata %s, expected %s", test.expectedBuildMetadata, version.BuildMetadata())
   346  		}
   347  	}
   348  }