semver_test.go 12 KB

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