semver_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. package semver
  2. import (
  3. "testing"
  4. )
  5. func prstr(s string) PRVersion {
  6. return PRVersion{s, 0, false}
  7. }
  8. func prnum(i uint64) PRVersion {
  9. return PRVersion{"", i, true}
  10. }
  11. type formatTest struct {
  12. v Version
  13. result string
  14. }
  15. var formatTests = []formatTest{
  16. {Version{1, 2, 3, nil, nil}, "1.2.3"},
  17. {Version{0, 0, 1, nil, nil}, "0.0.1"},
  18. {Version{0, 0, 1, []PRVersion{prstr("alpha"), prstr("preview")}, []string{"123", "456"}}, "0.0.1-alpha.preview+123.456"},
  19. {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, []string{"123", "456"}}, "1.2.3-alpha.1+123.456"},
  20. {Version{1, 2, 3, []PRVersion{prstr("alpha"), prnum(1)}, nil}, "1.2.3-alpha.1"},
  21. {Version{1, 2, 3, nil, []string{"123", "456"}}, "1.2.3+123.456"},
  22. // Prereleases and build metadata hyphens
  23. {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, []string{"123", "b-uild"}}, "1.2.3-alpha.b-eta+123.b-uild"},
  24. {Version{1, 2, 3, nil, []string{"123", "b-uild"}}, "1.2.3+123.b-uild"},
  25. {Version{1, 2, 3, []PRVersion{prstr("alpha"), prstr("b-eta")}, nil}, "1.2.3-alpha.b-eta"},
  26. }
  27. func TestStringer(t *testing.T) {
  28. for _, test := range formatTests {
  29. if res := test.v.String(); res != test.result {
  30. t.Errorf("Stringer, expected %q but got %q", test.result, res)
  31. }
  32. }
  33. }
  34. func TestParse(t *testing.T) {
  35. for _, test := range formatTests {
  36. if v, err := Parse(test.result); err != nil {
  37. t.Errorf("Error parsing %q: %q", test.result, err)
  38. } else if comp := v.Compare(test.v); comp != 0 {
  39. t.Errorf("Parsing, expected %q but got %q, comp: %d ", test.v, v, comp)
  40. } else if err := v.Validate(); err != nil {
  41. t.Errorf("Error validating parsed version %q: %q", test.v, err)
  42. }
  43. }
  44. }
  45. func TestMustParse(t *testing.T) {
  46. _ = MustParse("32.2.1-alpha")
  47. }
  48. func TestMustParse_panic(t *testing.T) {
  49. defer func() {
  50. if recover() == nil {
  51. t.Errorf("Should have panicked")
  52. }
  53. }()
  54. _ = MustParse("invalid version")
  55. }
  56. func TestValidate(t *testing.T) {
  57. for _, test := range formatTests {
  58. if err := test.v.Validate(); err != nil {
  59. t.Errorf("Error validating %q: %q", test.v, err)
  60. }
  61. }
  62. }
  63. type compareTest struct {
  64. v1 Version
  65. v2 Version
  66. result int
  67. }
  68. var compareTests = []compareTest{
  69. {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 0},
  70. {Version{2, 0, 0, nil, nil}, Version{1, 0, 0, nil, nil}, 1},
  71. {Version{0, 1, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 0},
  72. {Version{0, 2, 0, nil, nil}, Version{0, 1, 0, nil, nil}, 1},
  73. {Version{0, 0, 1, nil, nil}, Version{0, 0, 1, nil, nil}, 0},
  74. {Version{0, 0, 2, nil, nil}, Version{0, 0, 1, nil, nil}, 1},
  75. {Version{1, 2, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 0},
  76. {Version{2, 2, 4, nil, nil}, Version{1, 2, 4, nil, nil}, 1},
  77. {Version{1, 3, 3, nil, nil}, Version{1, 2, 3, nil, nil}, 1},
  78. {Version{1, 2, 4, nil, nil}, Version{1, 2, 3, nil, nil}, 1},
  79. // Spec Examples #11
  80. {Version{1, 0, 0, nil, nil}, Version{2, 0, 0, nil, nil}, -1},
  81. {Version{2, 0, 0, nil, nil}, Version{2, 1, 0, nil, nil}, -1},
  82. {Version{2, 1, 0, nil, nil}, Version{2, 1, 1, nil, nil}, -1},
  83. // Spec Examples #9
  84. {Version{1, 0, 0, nil, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, 1},
  85. {Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, -1},
  86. {Version{1, 0, 0, []PRVersion{prstr("alpha"), prnum(1)}, nil}, Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, -1},
  87. {Version{1, 0, 0, []PRVersion{prstr("alpha"), prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, -1},
  88. {Version{1, 0, 0, []PRVersion{prstr("beta")}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, -1},
  89. {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(2)}, nil}, Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, -1},
  90. {Version{1, 0, 0, []PRVersion{prstr("beta"), prnum(11)}, nil}, Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, -1},
  91. {Version{1, 0, 0, []PRVersion{prstr("rc"), prnum(1)}, nil}, Version{1, 0, 0, nil, nil}, -1},
  92. // Ignore Build metadata
  93. {Version{1, 0, 0, nil, []string{"1", "2", "3"}}, Version{1, 0, 0, nil, nil}, 0},
  94. }
  95. func TestCompare(t *testing.T) {
  96. for _, test := range compareTests {
  97. if res := test.v1.Compare(test.v2); res != test.result {
  98. t.Errorf("Comparing %q : %q, expected %d but got %d", test.v1, test.v2, test.result, res)
  99. }
  100. //Test counterpart
  101. if res := test.v2.Compare(test.v1); res != -test.result {
  102. t.Errorf("Comparing %q : %q, expected %d but got %d", test.v2, test.v1, -test.result, res)
  103. }
  104. }
  105. }
  106. type wrongformatTest struct {
  107. v *Version
  108. str string
  109. }
  110. var wrongformatTests = []wrongformatTest{
  111. {nil, ""},
  112. {nil, "."},
  113. {nil, "1."},
  114. {nil, ".1"},
  115. {nil, "a.b.c"},
  116. {nil, "1.a.b"},
  117. {nil, "1.1.a"},
  118. {nil, "1.a.1"},
  119. {nil, "a.1.1"},
  120. {nil, ".."},
  121. {nil, "1.."},
  122. {nil, "1.1."},
  123. {nil, "1..1"},
  124. {nil, "1.1.+123"},
  125. {nil, "1.1.-beta"},
  126. {nil, "-1.1.1"},
  127. {nil, "1.-1.1"},
  128. {nil, "1.1.-1"},
  129. // giant numbers
  130. {nil, "20000000000000000000.1.1"},
  131. {nil, "1.20000000000000000000.1"},
  132. {nil, "1.1.20000000000000000000"},
  133. {nil, "1.1.1-20000000000000000000"},
  134. // Leading zeroes
  135. {nil, "01.1.1"},
  136. {nil, "001.1.1"},
  137. {nil, "1.01.1"},
  138. {nil, "1.001.1"},
  139. {nil, "1.1.01"},
  140. {nil, "1.1.001"},
  141. {nil, "1.1.1-01"},
  142. {nil, "1.1.1-001"},
  143. {nil, "1.1.1-beta.01"},
  144. {nil, "1.1.1-beta.001"},
  145. {&Version{0, 0, 0, []PRVersion{prstr("!")}, nil}, "0.0.0-!"},
  146. {&Version{0, 0, 0, nil, []string{"!"}}, "0.0.0+!"},
  147. // empty prversion
  148. {&Version{0, 0, 0, []PRVersion{prstr(""), prstr("alpha")}, nil}, "0.0.0-.alpha"},
  149. // empty build meta data
  150. {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{""}}, "0.0.0-alpha+"},
  151. {&Version{0, 0, 0, []PRVersion{prstr("alpha")}, []string{"test", ""}}, "0.0.0-alpha+test."},
  152. }
  153. func TestWrongFormat(t *testing.T) {
  154. for _, test := range wrongformatTests {
  155. if res, err := Parse(test.str); err == nil {
  156. t.Errorf("Parsing wrong format version %q, expected error but got %q", test.str, res)
  157. }
  158. if test.v != nil {
  159. if err := test.v.Validate(); err == nil {
  160. t.Errorf("Validating wrong format version %q (%q), expected error", test.v, test.str)
  161. }
  162. }
  163. }
  164. }
  165. func TestCompareHelper(t *testing.T) {
  166. v := Version{1, 0, 0, []PRVersion{prstr("alpha")}, nil}
  167. v1 := Version{1, 0, 0, nil, nil}
  168. if !v.EQ(v) {
  169. t.Errorf("%q should be equal to %q", v, v)
  170. }
  171. if !v.Equals(v) {
  172. t.Errorf("%q should be equal to %q", v, v)
  173. }
  174. if !v1.NE(v) {
  175. t.Errorf("%q should not be equal to %q", v1, v)
  176. }
  177. if !v.GTE(v) {
  178. t.Errorf("%q should be greater than or equal to %q", v, v)
  179. }
  180. if !v.LTE(v) {
  181. t.Errorf("%q should be less than or equal to %q", v, v)
  182. }
  183. if !v.LT(v1) {
  184. t.Errorf("%q should be less than %q", v, v1)
  185. }
  186. if !v.LTE(v1) {
  187. t.Errorf("%q should be less than or equal %q", v, v1)
  188. }
  189. if !v.LE(v1) {
  190. t.Errorf("%q should be less than or equal %q", v, v1)
  191. }
  192. if !v1.GT(v) {
  193. t.Errorf("%q should be greater than %q", v1, v)
  194. }
  195. if !v1.GTE(v) {
  196. t.Errorf("%q should be greater than or equal %q", v1, v)
  197. }
  198. if !v1.GE(v) {
  199. t.Errorf("%q should be greater than or equal %q", v1, v)
  200. }
  201. }
  202. func TestPreReleaseVersions(t *testing.T) {
  203. p1, err := NewPRVersion("123")
  204. if !p1.IsNumeric() {
  205. t.Errorf("Expected numeric prversion, got %q", p1)
  206. }
  207. if p1.VersionNum != 123 {
  208. t.Error("Wrong prversion number")
  209. }
  210. if err != nil {
  211. t.Errorf("Not expected error %q", err)
  212. }
  213. p2, err := NewPRVersion("alpha")
  214. if p2.IsNumeric() {
  215. t.Errorf("Expected non-numeric prversion, got %q", p2)
  216. }
  217. if p2.VersionStr != "alpha" {
  218. t.Error("Wrong prversion string")
  219. }
  220. if err != nil {
  221. t.Errorf("Not expected error %q", err)
  222. }
  223. }
  224. func TestBuildMetaDataVersions(t *testing.T) {
  225. _, err := NewBuildVersion("123")
  226. if err != nil {
  227. t.Errorf("Unexpected error %q", err)
  228. }
  229. _, err = NewBuildVersion("build")
  230. if err != nil {
  231. t.Errorf("Unexpected error %q", err)
  232. }
  233. _, err = NewBuildVersion("test?")
  234. if err == nil {
  235. t.Error("Expected error, got none")
  236. }
  237. _, err = NewBuildVersion("")
  238. if err == nil {
  239. t.Error("Expected error, got none")
  240. }
  241. }
  242. func TestNewHelper(t *testing.T) {
  243. v, err := New("1.2.3")
  244. if err != nil {
  245. t.Fatalf("Unexpected error %q", err)
  246. }
  247. // New returns pointer
  248. if v == nil {
  249. t.Fatal("Version is nil")
  250. }
  251. if v.Compare(Version{1, 2, 3, nil, nil}) != 0 {
  252. t.Fatal("Unexpected comparison problem")
  253. }
  254. }
  255. func TestMakeHelper(t *testing.T) {
  256. v, err := Make("1.2.3")
  257. if err != nil {
  258. t.Fatalf("Unexpected error %q", err)
  259. }
  260. if v.Compare(Version{1, 2, 3, nil, nil}) != 0 {
  261. t.Fatal("Unexpected comparison problem")
  262. }
  263. }
  264. func BenchmarkParseSimple(b *testing.B) {
  265. const VERSION = "0.0.1"
  266. b.ReportAllocs()
  267. b.ResetTimer()
  268. for n := 0; n < b.N; n++ {
  269. Parse(VERSION)
  270. }
  271. }
  272. func BenchmarkParseComplex(b *testing.B) {
  273. const VERSION = "0.0.1-alpha.preview+123.456"
  274. b.ReportAllocs()
  275. b.ResetTimer()
  276. for n := 0; n < b.N; n++ {
  277. Parse(VERSION)
  278. }
  279. }
  280. func BenchmarkParseAverage(b *testing.B) {
  281. l := len(formatTests)
  282. b.ReportAllocs()
  283. b.ResetTimer()
  284. for n := 0; n < b.N; n++ {
  285. Parse(formatTests[n%l].result)
  286. }
  287. }
  288. func BenchmarkStringSimple(b *testing.B) {
  289. const VERSION = "0.0.1"
  290. v, _ := Parse(VERSION)
  291. b.ReportAllocs()
  292. b.ResetTimer()
  293. for n := 0; n < b.N; n++ {
  294. v.String()
  295. }
  296. }
  297. func BenchmarkStringLarger(b *testing.B) {
  298. const VERSION = "11.15.2012"
  299. v, _ := Parse(VERSION)
  300. b.ReportAllocs()
  301. b.ResetTimer()
  302. for n := 0; n < b.N; n++ {
  303. v.String()
  304. }
  305. }
  306. func BenchmarkStringComplex(b *testing.B) {
  307. const VERSION = "0.0.1-alpha.preview+123.456"
  308. v, _ := Parse(VERSION)
  309. b.ReportAllocs()
  310. b.ResetTimer()
  311. for n := 0; n < b.N; n++ {
  312. v.String()
  313. }
  314. }
  315. func BenchmarkStringAverage(b *testing.B) {
  316. l := len(formatTests)
  317. b.ReportAllocs()
  318. b.ResetTimer()
  319. for n := 0; n < b.N; n++ {
  320. formatTests[n%l].v.String()
  321. }
  322. }
  323. func BenchmarkValidateSimple(b *testing.B) {
  324. const VERSION = "0.0.1"
  325. v, _ := Parse(VERSION)
  326. b.ReportAllocs()
  327. b.ResetTimer()
  328. for n := 0; n < b.N; n++ {
  329. v.Validate()
  330. }
  331. }
  332. func BenchmarkValidateComplex(b *testing.B) {
  333. const VERSION = "0.0.1-alpha.preview+123.456"
  334. v, _ := Parse(VERSION)
  335. b.ReportAllocs()
  336. b.ResetTimer()
  337. for n := 0; n < b.N; n++ {
  338. v.Validate()
  339. }
  340. }
  341. func BenchmarkValidateAverage(b *testing.B) {
  342. l := len(formatTests)
  343. b.ReportAllocs()
  344. b.ResetTimer()
  345. for n := 0; n < b.N; n++ {
  346. formatTests[n%l].v.Validate()
  347. }
  348. }
  349. func BenchmarkCompareSimple(b *testing.B) {
  350. const VERSION = "0.0.1"
  351. v, _ := Parse(VERSION)
  352. b.ReportAllocs()
  353. b.ResetTimer()
  354. for n := 0; n < b.N; n++ {
  355. v.Compare(v)
  356. }
  357. }
  358. func BenchmarkCompareComplex(b *testing.B) {
  359. const VERSION = "0.0.1-alpha.preview+123.456"
  360. v, _ := Parse(VERSION)
  361. b.ReportAllocs()
  362. b.ResetTimer()
  363. for n := 0; n < b.N; n++ {
  364. v.Compare(v)
  365. }
  366. }
  367. func BenchmarkCompareAverage(b *testing.B) {
  368. l := len(compareTests)
  369. b.ReportAllocs()
  370. b.ResetTimer()
  371. for n := 0; n < b.N; n++ {
  372. compareTests[n%l].v1.Compare((compareTests[n%l].v2))
  373. }
  374. }