11package semver
22
33import (
4+ "fmt"
45 "testing"
56
67 "github.com/stretchr/testify/assert"
78 "github.com/stretchr/testify/require"
89)
910
11+ // In order to catch parsing bugs that depend on the number or order of digits, we use ValuesGenerator
12+ // (in values_generator.go) to create permutations of many integer values. However, as a practical
13+ // measure to avoid very long test times, we don't use an equally large range for every value: when
14+ // generating major, minor, and patch version numbers, we cover a 3-digit range for the major and only
15+ // one digit for the others, on the assumption that the same numeric parsing logic is used for each.
16+
1017func assertVersionComponents (t * testing.T , v Version , major int , minor int , patch int , pre string , b string ) {
1118 assert .Equal (t , major , v .GetMajor ())
1219 assert .Equal (t , minor , v .GetMinor ())
@@ -36,8 +43,12 @@ func TestParseStrict(t *testing.T) {
3643 strictParsingTests := func (t * testing.T , parseFn func (string ) (Version , error )) {
3744 parsingTestsForAnyMode (t , parseFn )
3845
39- t .Run ("patch version cannot be omitted" , parsingShouldFail (parseFn , "2.3" ))
40- t .Run ("micro and patch versions cannot be omitted" , parsingShouldFail (parseFn , "2" ))
46+ NewValuesGenerator ().AddValue (0 , 199 ).AddValue (0 , 9 ).TestAll2 (t , func (t * testing.T , a , b int ) {
47+ t .Run ("patch version cannot be omitted" , parsingShouldFail (parseFn , fmt .Sprintf ("%d.%d" , a , b )))
48+ })
49+ NewValuesGenerator ().AddValue (0 , 199 ).TestAll1 (t , func (t * testing.T , a int ) {
50+ t .Run ("micro and patch versions cannot be omitted" , parsingShouldFail (parseFn , fmt .Sprintf ("%d" , a )))
51+ })
4152 }
4253
4354 t .Run ("Parse(s)" , func (t * testing.T ) {
@@ -54,86 +65,94 @@ func TestParseAllowMissingMinorAndPatch(t *testing.T) {
5465
5566 parsingTestsForAnyMode (t , parseFn )
5667
57- t .Run ("patch version can be omitted" , parsingShouldSucceed (parseFn ,
58- "2.3" , 2 , 3 , 0 , "" , "" ))
68+ NewValuesGenerator ().AddValue (0 , 199 ).AddValue (0 , 9 ).TestAll2 (t , func (t * testing.T , a , b int ) {
69+ s := fmt .Sprintf ("%d.%d" , a , b )
70+
71+ t .Run ("patch version can be omitted" , parsingShouldSucceed (parseFn ,
72+ s , a , b , 0 , "" , "" ))
5973
60- t .Run ("patch version can be omitted with prerelease" , parsingShouldSucceed (parseFn ,
61- "2.3-beta1" , 2 , 3 , 0 , "beta1" , "" ))
74+ t .Run ("patch version can be omitted with prerelease" , parsingShouldSucceed (parseFn ,
75+ s + "-beta1" , a , b , 0 , "beta1" , "" ))
76+
77+ t .Run ("patch version can be omitted with build" , parsingShouldSucceed (parseFn ,
78+ s + "+build1" , a , b , 0 , "" , "build1" ))
79+ })
6280
63- t . Run ( "patch version can be omitted with build" , parsingShouldSucceed ( parseFn ,
64- "2.3+build1" , 2 , 3 , 0 , " " , "build1" ) )
81+ NewValuesGenerator (). AddValue ( 0 , 199 ). TestAll1 ( t , func ( t * testing. T , a int ) {
82+ s := fmt . Sprintf ( "%d " , a )
6583
66- t .Run ("micro and patch versions can be omitted" , parsingShouldSucceed (parseFn ,
67- "2" , 2 , 0 , 0 , "" , "" ))
84+ t .Run ("micro and patch versions can be omitted" , parsingShouldSucceed (parseFn ,
85+ s , a , 0 , 0 , "" , "" ))
6886
69- t .Run ("micro and patch versions can be omitted with prerelease" , parsingShouldSucceed (parseFn ,
70- "2 -beta1" , 2 , 0 , 0 , "beta1" , "" ))
87+ t .Run ("micro and patch versions can be omitted with prerelease" , parsingShouldSucceed (parseFn ,
88+ s + " -beta1" , a , 0 , 0 , "beta1" , "" ))
7189
72- t .Run ("micro and patch versions can be omitted with build" , parsingShouldSucceed (parseFn ,
73- "2+build1" , 2 , 0 , 0 , "" , "build1" ))
90+ t .Run ("micro and patch versions can be omitted with build" , parsingShouldSucceed (parseFn ,
91+ s + "+build1" , a , 0 , 0 , "" , "build1" ))
92+ })
7493}
7594
7695func parsingTestsForAnyMode (t * testing.T , parseFn func (string ) (Version , error )) {
7796 t .Run ("valid" , func (t * testing.T ) {
78- t .Run ("simple complete version" , parsingShouldSucceed (parseFn ,
79- "2.3.4" , 2 , 3 , 4 , "" , "" ))
80-
81- t .Run ("version with prerelease (single identifier)" , parsingShouldSucceed (parseFn ,
82- "2.3.4-beta1" , 2 , 3 , 4 , "beta1" , "" ))
83-
84- t .Run ("version with prerelease (multi-identifier)" , parsingShouldSucceed (parseFn ,
85- "2.3.4-beta1.2" , 2 , 3 , 4 , "beta1.2" , "" ))
86-
87- t .Run ("version with prerelease (multi-identifier with hyphens)" , parsingShouldSucceed (parseFn ,
88- "2.3.4-beta1-final.2" , 2 , 3 , 4 , "beta1-final.2" , "" ))
97+ NewValuesGenerator ().AddValue (0 , 199 ).AddValue (0 , 9 ).AddValue (0 , 9 ).
98+ TestAll3 (t , func (t * testing.T , a , b , c int ) {
99+ s := fmt .Sprintf ("%d.%d.%d" , a , b , c )
100+ t .Run ("simple complete version" , parsingShouldSucceed (parseFn ,
101+ s , a , b , c , "" , "" ))
89102
90- t .Run ("version with build (single identifier)" , parsingShouldSucceed (parseFn ,
91- "2.3.4+build2" , 2 , 3 , 4 , "" , "build2 " ))
103+ t .Run ("version with prerelease (single identifier)" , parsingShouldSucceed (parseFn ,
104+ s + "-beta1" , a , b , c , "beta1 " , "" ))
92105
93- t .Run ("version with build (multi- identifier)" , parsingShouldSucceed (parseFn ,
94- "2.3.4 +build2.4 " , 2 , 3 , 4 , "" , "build2.4 " ))
106+ t .Run ("version with build (single identifier)" , parsingShouldSucceed (parseFn ,
107+ s + " +build2" , a , b , c , "" , "build2" ))
95108
96- t .Run ("version with build (multi- identifier with hyphens) " , parsingShouldSucceed (parseFn ,
97- "2.3.4+build2-other.4 " , 2 , 3 , 4 , "" , "build2-other.4 " ))
109+ t .Run ("prerelease identifier of only letters " , parsingShouldSucceed (parseFn ,
110+ s + "-abc " , a , b , c , "abc " , "" ))
98111
99- t .Run ("version with prerelease and build " , parsingShouldSucceed (parseFn ,
100- "2.3.4-beta1.rc2+build2.4 " , 2 , 3 , 4 , "beta1.rc2 " , "build2.4 " ))
112+ t .Run ("prerelease identifier of only digits " , parsingShouldSucceed (parseFn ,
113+ s + "-123 " , a , b , c , "123 " , "" ))
101114
102- t .Run ("major version zero " , parsingShouldSucceed (parseFn ,
103- "0.3.4 " , 0 , 3 , 4 , "" , "" ))
115+ t .Run ("prerelease identifier of only hyphens " , parsingShouldSucceed (parseFn ,
116+ s + "---- " , a , b , c , "--- " , "" ))
104117
105- t .Run ("minor version zero" , parsingShouldSucceed (parseFn ,
106- "2.0.4 " , 2 , 0 , 4 , "" , "" ))
118+ t .Run ("alphanumeric prerelease identifier with leading zero" , parsingShouldSucceed (parseFn ,
119+ s + "-beta1.0yes " , a , b , c , "beta1.0yes " , "" ))
107120
108- t .Run ("patch version zero " , parsingShouldSucceed (parseFn ,
109- "2.3.0 " , 2 , 3 , 0 , "" , "" ))
121+ t .Run ("build identifier of only letters " , parsingShouldSucceed (parseFn ,
122+ s + "+abc " , a , b , c , "" , "abc " ))
110123
111- t .Run ("prerelease identifier of only letters " , parsingShouldSucceed (parseFn ,
112- "2.3.4-abc " , 2 , 3 , 4 , "abc " , "" ))
124+ t .Run ("build identifier of only digits " , parsingShouldSucceed (parseFn ,
125+ s + "+123 " , a , b , c , "" , "123 " ))
113126
114- t .Run ("prerelease identifier of only digits " , parsingShouldSucceed (parseFn ,
115- "2.3.4-123 " , 2 , 3 , 4 , "123 " , "" ))
127+ t .Run ("build identifier of only hyphens " , parsingShouldSucceed (parseFn ,
128+ s + "+--- " , a , b , c , "" , "--- " ))
116129
117- t .Run ("prerelease identifier of only hyphens " , parsingShouldSucceed (parseFn ,
118- "2.3.4---- " , 2 , 3 , 4 , "--- " , "" ))
130+ t .Run ("alphanumeric build identifier with leading zero " , parsingShouldSucceed (parseFn ,
131+ s + "+build1.0yes " , a , b , c , "" , "build1.0yes " ))
119132
120- t .Run ("alphanumeric prerelease identifier with leading zero" , parsingShouldSucceed (parseFn ,
121- "2.3.4-beta1.0yes" , 2 , 3 , 4 , "beta1.0yes" , "" ))
133+ t .Run ("leading zero in numeric build identifier" , parsingShouldSucceed (parseFn ,
134+ s + "+build1.02" , a , b , c , "" , "build1.02" ))
135+ })
122136
123- t .Run ("build identifier of only letters" , parsingShouldSucceed (parseFn ,
124- "2.3.4+abc" , 2 , 3 , 4 , "" , "abc" ))
137+ NewValuesGenerator ().AddValue (0 , 199 ).AddValue (0 , 9 ).AddValue (0 , 9 ).AddValue (0 , 2 ).
138+ TestAll4 (t , func (t * testing.T , a , b , c , d int ) {
139+ s := fmt .Sprintf ("%d.%d.%d" , a , b , c )
140+ dd := fmt .Sprintf ("%d" , d )
141+ t .Run ("version with prerelease (multi-identifier)" , parsingShouldSucceed (parseFn ,
142+ s + "-beta1." + dd , a , b , c , "beta1." + dd , "" ))
125143
126- t .Run ("build identifier of only digits " , parsingShouldSucceed (parseFn ,
127- "2.3.4+123" , 2 , 3 , 4 , "" , "123 " ))
144+ t .Run ("version with prerelease (multi-identifier with hyphens) " , parsingShouldSucceed (parseFn ,
145+ s + "-beta1-final." + dd , a , b , c , "beta1-final." + dd , "" ))
128146
129- t .Run ("build identifier of only hyphens " , parsingShouldSucceed (parseFn ,
130- "2.3.4+---" , 2 , 3 , 4 , "" , "---" ))
147+ t .Run ("version with build (multi-identifier) " , parsingShouldSucceed (parseFn ,
148+ s + "+build2." + dd , a , b , c , "" , "build2." + dd ))
131149
132- t .Run ("alphanumeric build identifier with leading zero " , parsingShouldSucceed (parseFn ,
133- "2.3.4+build1.0yes" , 2 , 3 , 4 , "" , "build1.0yes" ))
150+ t .Run ("version with build (multi- identifier with hyphens) " , parsingShouldSucceed (parseFn ,
151+ s + "+build2-other." + dd , a , b , c , "" , "build2-other." + dd ))
134152
135- t .Run ("leading zero in numeric build identifier" , parsingShouldSucceed (parseFn ,
136- "2.3.4+build1.02" , 2 , 3 , 4 , "" , "build1.02" ))
153+ t .Run ("version with prerelease and build" , parsingShouldSucceed (parseFn ,
154+ s + "-beta1.rc2+build2." + dd , a , b , c , "beta1.rc2" , "build2." + dd ))
155+ })
137156 })
138157
139158 t .Run ("invalid" , func (t * testing.T ) {
0 commit comments