diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 3c216ed..ddbe0cb 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@master - uses: actions/setup-go@v1 with: - go-version: "1.21" + go-version: "1.24" - name: Build native run: GOARCH=amd64 go build -v ./... shell: bash @@ -33,10 +33,13 @@ jobs: - uses: actions/checkout@master - uses: actions/setup-go@v1 with: - go-version: "1.21" + go-version: "1.24" - name: Run unit tests with coverage run: go test -v -race -covermode=atomic -coverprofile=coverage.out ./... shell: bash - - uses: codecov/codecov-action@v2 + - uses: codecov/codecov-action@v5 with: verbose: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + diff --git a/LICENSE b/LICENSE index 27899f0..e7337e9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2018-2022, Cristian Maglie. +Copyright (c) 2018-2025, Cristian Maglie. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.md b/README.md index 109fa2b..b969727 100644 --- a/README.md +++ b/README.md @@ -95,3 +95,40 @@ The `Version` and `RelaxedVersion` provides optimized `MarshalBinary`/`Unmarshal ## Yaml parsable with `gopkg.in/yaml.v3` The `Version` and `RelaxedVersion` have the YAML un/marshaler implemented so they can be YAML decoded/encoded with the excellent `gopkg.in/yaml.v3` library. + +## SQL support + +The `Version` and `RelaxedVersion` types provides the `sql.Scanner` and `driver.Valuer` interfaces. Those objects could be directly used in SQL queries, their value will be mapped into a string field. + +## Lexicographic sortable strings that keeps semantic versioning order + +The `Version` and `RelaxedVersion` objects provides the `SortableString()` method that returns a string with a peculiar property: the alphanumeric sorting of two `Version.SortableString()` matches the semantic versioning ordering of the underling `Version` objects. In other words, given two `Version` object `a` and `b`: +* if `a.LessThan(b)` is true then `a.SortableString() < b.SortableString()` is true and vice-versa. +* if `a.Equals(b)` is true then `a.SortableString() == b.SortableString()` is true and vice-versa. +* more generally, the following assertion is always true: `a.CompareTo(b) == cmp.Compare(a.SortableString(), b.SortableString())` + +This is accomplished by adding some adjustment characters to the original semver `Version` string with the purpose to change the behaviour of the natural alphabetic ordering, in particular: +* to allow comparison of numeric values (keeping digits aligned by unit, tenths, hundhereds, etc...). +* to invert the ordering of versions with and without prelease (a version with prelease should be lower priority compared to the same version without prerelease, but being longer alphanumerically it naturally follows it). + +To give you an idea on how it works, the following table shows some examples of semver versions and their `SortableString` counter part: + +| semver | `SortableString()` | +| ------------------ | ------------------- | +| `1.2.4` | `;1.2.4;` | +| `1.3.0-rc` | `;1.3.0-;rc` | +| `1.3.0-rc.0` | `;1.3.0-;rc,:0` | +| `1.3.0-rc.5` | `;1.3.0-;rc,:5` | +| `1.3.0-rc.5+build` | `;1.3.0-;rc,:5` | +| `1.3.0-rc.20` | `;1.3.0-;rc,::20` | +| `1.3.0-rc-` | `;1.3.0-;rc-` | +| `1.3.0` | `;1.3.0;` | +| `1.20.0` | `;1.:20.0;` | +| `1.90.0` | `;1.:90.0;` | +| `1.300.0-6` | `;1.::300.0-:6` | +| `1.300.0-30` | `;1.::300.0-::30` | +| `1.300.0-1pre` | `;1.::300.0-;1pre` | +| `1.300.0-pre` | `;1.::300.0-;pre` | +| `1.300.0` | `;1.::300.0;` | + +The `SortableString()` can be used in SQL databases to simplify the ordering of a set of versions in a table. diff --git a/benchmark_test.go b/benchmark_test.go index 1dbfe87..1a7f748 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -70,7 +70,7 @@ func BenchmarkVersionParser(b *testing.B) { for _, v := range list { res.raw = v res.bytes = []byte(v) - parse(res) + _ = parse(res) } } diff --git a/binary.go b/binary.go index 141fb2d..37defd1 100644 --- a/binary.go +++ b/binary.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -62,7 +62,7 @@ func (v *Version) UnmarshalBinary(data []byte) error { return nil } -// MarshalBinary implements json.Marshaler +// MarshalBinary implements encoding.BinaryMarshaler func (v *RelaxedVersion) MarshalBinary() ([]byte, error) { res := new(bytes.Buffer) if len(v.customversion) > 0 { @@ -76,7 +76,7 @@ func (v *RelaxedVersion) MarshalBinary() ([]byte, error) { return res.Bytes(), nil } -// UnmarshalBinary implements json.Unmarshaler +// UnmarshalBinary implements encoding.BinaryUnmarshaler func (v *RelaxedVersion) UnmarshalBinary(data []byte) error { if data[0] == 0 { v.customversion, _ = decodeArray(data[1:]) diff --git a/binary_test.go b/binary_test.go index 666f964..2b68bf1 100644 --- a/binary_test.go +++ b/binary_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -74,7 +74,7 @@ func BenchmarkBinaryDecoding(b *testing.B) { data, _ := v.MarshalBinary() var u Version for i := 0; i < b.N; i++ { - u.UnmarshalBinary(data) + _ = u.UnmarshalBinary(data) } } @@ -85,6 +85,6 @@ func BenchmarkBinaryDecodingRelaxed(b *testing.B) { data, _ := v.MarshalBinary() var u RelaxedVersion for i := 0; i < b.N; i++ { - u.UnmarshalBinary(data) + _ = u.UnmarshalBinary(data) } } diff --git a/charsets.go b/charsets.go index 9a3d134..8717667 100644 --- a/charsets.go +++ b/charsets.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/charsets_test.go b/charsets_test.go index e31d7d9..f869521 100644 --- a/charsets_test.go +++ b/charsets_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/constraints.go b/constraints.go index ce882ae..12a29d3 100644 --- a/constraints.go +++ b/constraints.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/constraints_test.go b/constraints_test.go index cf6adab..a7dea99 100644 --- a/constraints_test.go +++ b/constraints_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/debug.go b/debug.go index 91d60b9..4801951 100644 --- a/debug.go +++ b/debug.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/debug_test.go b/debug_test.go index 2378ea1..dbb394f 100644 --- a/debug_test.go +++ b/debug_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/doc.go b/doc.go index 2e67f9a..6848e26 100644 --- a/doc.go +++ b/doc.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/fuzzer-data/corpus/046ea6e92945727581cc0d3550754bf545fbcce3-5 b/fuzzer-data/corpus/046ea6e92945727581cc0d3550754bf545fbcce3-5 deleted file mode 100644 index eb5c2db..0000000 --- a/fuzzer-data/corpus/046ea6e92945727581cc0d3550754bf545fbcce3-5 +++ /dev/null @@ -1 +0,0 @@ -0- \ No newline at end of file diff --git a/fuzzer-data/corpus/068382db090cc2156c484b9dde197338e891033e b/fuzzer-data/corpus/068382db090cc2156c484b9dde197338e891033e deleted file mode 100644 index 4317f1a..0000000 --- a/fuzzer-data/corpus/068382db090cc2156c484b9dde197338e891033e +++ /dev/null @@ -1 +0,0 @@ -9+V.1.3.1.1.1.1.1.9.1.3.1.1.1.1.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/08a9aa391b51b3f77b9ce25e09f7e4312d53ab71-3 b/fuzzer-data/corpus/08a9aa391b51b3f77b9ce25e09f7e4312d53ab71-3 deleted file mode 100644 index ba334aa..0000000 --- a/fuzzer-data/corpus/08a9aa391b51b3f77b9ce25e09f7e4312d53ab71-3 +++ /dev/null @@ -1 +0,0 @@ -757202302126572447535523755625377572023021265724475355237556000065. \ No newline at end of file diff --git a/fuzzer-data/corpus/0ad79654b5be6c827ded02b60dc2696916c8d0a4-1 b/fuzzer-data/corpus/0ad79654b5be6c827ded02b60dc2696916c8d0a4-1 deleted file mode 100644 index fd66bb9..0000000 Binary files a/fuzzer-data/corpus/0ad79654b5be6c827ded02b60dc2696916c8d0a4-1 and /dev/null differ diff --git a/fuzzer-data/corpus/0bfc438e047d27c863f3d5cc96dbf58028b91c3f b/fuzzer-data/corpus/0bfc438e047d27c863f3d5cc96dbf58028b91c3f deleted file mode 100644 index 4f90bfe..0000000 --- a/fuzzer-data/corpus/0bfc438e047d27c863f3d5cc96dbf58028b91c3f +++ /dev/null @@ -1 +0,0 @@ -0--xAbbbbeAcAcCECaBaAAaAfeAdEBe-xfCCfBBfAEdcfFebeDxfCCfBBfAEdcfFebeD \ No newline at end of file diff --git a/fuzzer-data/corpus/0c980d3a6e75672e60aa6e7547c723a3f68196a5-7 b/fuzzer-data/corpus/0c980d3a6e75672e60aa6e7547c723a3f68196a5-7 deleted file mode 100644 index dd0943e..0000000 --- a/fuzzer-data/corpus/0c980d3a6e75672e60aa6e7547c723a3f68196a5-7 +++ /dev/null @@ -1 +0,0 @@ -9-V.1.3.1.1.1.1.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/0f766def7495524760bb6627fe20754b1b42201b-3 b/fuzzer-data/corpus/0f766def7495524760bb6627fe20754b1b42201b-3 deleted file mode 100644 index ffbbb67..0000000 --- a/fuzzer-data/corpus/0f766def7495524760bb6627fe20754b1b42201b-3 +++ /dev/null @@ -1 +0,0 @@ -3.1.12 \ No newline at end of file diff --git a/fuzzer-data/corpus/109ed142810589f18b1d40ed971b8cee512544db-1 b/fuzzer-data/corpus/109ed142810589f18b1d40ed971b8cee512544db-1 deleted file mode 100644 index 96f67c7..0000000 --- a/fuzzer-data/corpus/109ed142810589f18b1d40ed971b8cee512544db-1 +++ /dev/null @@ -1 +0,0 @@ -4.474368202171 \ No newline at end of file diff --git a/fuzzer-data/corpus/11a210e269394a23fcaa6d97de1801c9cd5f5e56-8 b/fuzzer-data/corpus/11a210e269394a23fcaa6d97de1801c9cd5f5e56-8 deleted file mode 100644 index d19e646..0000000 --- a/fuzzer-data/corpus/11a210e269394a23fcaa6d97de1801c9cd5f5e56-8 +++ /dev/null @@ -1 +0,0 @@ -2-V.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/12d63df675a2fc4ef16cf54b944e9e580d0b14fe-2 b/fuzzer-data/corpus/12d63df675a2fc4ef16cf54b944e9e580d0b14fe-2 deleted file mode 100644 index 34f6aa9..0000000 --- a/fuzzer-data/corpus/12d63df675a2fc4ef16cf54b944e9e580d0b14fe-2 +++ /dev/null @@ -1 +0,0 @@ -4.02 \ No newline at end of file diff --git a/fuzzer-data/corpus/173215a7274edaaef1e934109c48ebb37c52db13-1 b/fuzzer-data/corpus/173215a7274edaaef1e934109c48ebb37c52db13-1 deleted file mode 100644 index 5b52054..0000000 --- a/fuzzer-data/corpus/173215a7274edaaef1e934109c48ebb37c52db13-1 +++ /dev/null @@ -1 +0,0 @@ -0-057e-33304e-91094BfAEd6cf6379282317958222700xfCCfB5BfAEd6cfFebe7D \ No newline at end of file diff --git a/fuzzer-data/corpus/18c42203590f36ef6f08a9585fa415d7b0240b02-2 b/fuzzer-data/corpus/18c42203590f36ef6f08a9585fa415d7b0240b02-2 deleted file mode 100644 index 68b290f..0000000 --- a/fuzzer-data/corpus/18c42203590f36ef6f08a9585fa415d7b0240b02-2 +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/fuzzer-data/corpus/1fbb5b14fbd62348c4e251810fbfdf3b0754974d-9 b/fuzzer-data/corpus/1fbb5b14fbd62348c4e251810fbfdf3b0754974d-9 deleted file mode 100644 index 0267880..0000000 --- a/fuzzer-data/corpus/1fbb5b14fbd62348c4e251810fbfdf3b0754974d-9 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.4.0.1.-.1.R.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/20bb5a63faab0f108cd914d9ea003a544484a3f1-3 b/fuzzer-data/corpus/20bb5a63faab0f108cd914d9ea003a544484a3f1-3 deleted file mode 100644 index 6503b81..0000000 --- a/fuzzer-data/corpus/20bb5a63faab0f108cd914d9ea003a544484a3f1-3 +++ /dev/null @@ -1 +0,0 @@ -1.1.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/21ae937d726a0cf94c661e9e4526fe41ebaeb2a1-13 b/fuzzer-data/corpus/21ae937d726a0cf94c661e9e4526fe41ebaeb2a1-13 deleted file mode 100644 index 3cee618..0000000 --- a/fuzzer-data/corpus/21ae937d726a0cf94c661e9e4526fe41ebaeb2a1-13 +++ /dev/null @@ -1 +0,0 @@ -4-V.t.t.t.e.e.V.t.e.V.t.e.e.V.t.e.V \ No newline at end of file diff --git a/fuzzer-data/corpus/23911cf0c0e063e33f94016212137d8b028b22dc b/fuzzer-data/corpus/23911cf0c0e063e33f94016212137d8b028b22dc deleted file mode 100644 index 79d9440..0000000 --- a/fuzzer-data/corpus/23911cf0c0e063e33f94016212137d8b028b22dc +++ /dev/null @@ -1 +0,0 @@ -1.0x \ No newline at end of file diff --git a/fuzzer-data/corpus/247bb175f9e774d6bfb0ca3d937ab82412f88bb7-7 b/fuzzer-data/corpus/247bb175f9e774d6bfb0ca3d937ab82412f88bb7-7 deleted file mode 100644 index cf400e7..0000000 --- a/fuzzer-data/corpus/247bb175f9e774d6bfb0ca3d937ab82412f88bb7-7 +++ /dev/null @@ -1 +0,0 @@ -1+1.1.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/27ee178d1d9ed4a1e21ccce3ace0a41b83d36abf-3 b/fuzzer-data/corpus/27ee178d1d9ed4a1e21ccce3ace0a41b83d36abf-3 deleted file mode 100644 index 9ebc1e9..0000000 --- a/fuzzer-data/corpus/27ee178d1d9ed4a1e21ccce3ace0a41b83d36abf-3 +++ /dev/null @@ -1 +0,0 @@ -0-0-.0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/28a429b1b5513602ecb8ea6075a5b84d1f7f844c b/fuzzer-data/corpus/28a429b1b5513602ecb8ea6075a5b84d1f7f844c deleted file mode 100644 index c52f28a..0000000 --- a/fuzzer-data/corpus/28a429b1b5513602ecb8ea6075a5b84d1f7f844c +++ /dev/null @@ -1 +0,0 @@ -4.4.4740683-m \ No newline at end of file diff --git a/fuzzer-data/corpus/2997cd15363376481469b7005532847bf9065801-8 b/fuzzer-data/corpus/2997cd15363376481469b7005532847bf9065801-8 deleted file mode 100644 index 4295aed..0000000 --- a/fuzzer-data/corpus/2997cd15363376481469b7005532847bf9065801-8 +++ /dev/null @@ -1 +0,0 @@ -0-0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/2d1949a8d4c481f21ec2a8aa8fa10e73b3990f2a-2 b/fuzzer-data/corpus/2d1949a8d4c481f21ec2a8aa8fa10e73b3990f2a-2 deleted file mode 100644 index 7b79e55..0000000 --- a/fuzzer-data/corpus/2d1949a8d4c481f21ec2a8aa8fa10e73b3990f2a-2 +++ /dev/null @@ -1 +0,0 @@ -0-57e-33304e-910946379282317068958222700xfC792823CfB5BfAEd6cfFebe7D \ No newline at end of file diff --git a/fuzzer-data/corpus/2d8e9d468659a78d3778e246da382462eb258b54-2 b/fuzzer-data/corpus/2d8e9d468659a78d3778e246da382462eb258b54-2 deleted file mode 100644 index 71b3c5d..0000000 --- a/fuzzer-data/corpus/2d8e9d468659a78d3778e246da382462eb258b54-2 +++ /dev/null @@ -1 +0,0 @@ -9298023223876953125 \ No newline at end of file diff --git a/fuzzer-data/corpus/31e23a09a1cf2d5c34457bef7ff05d8d8a268cfd-2 b/fuzzer-data/corpus/31e23a09a1cf2d5c34457bef7ff05d8d8a268cfd-2 deleted file mode 100644 index d1a4820..0000000 --- a/fuzzer-data/corpus/31e23a09a1cf2d5c34457bef7ff05d8d8a268cfd-2 +++ /dev/null @@ -1 +0,0 @@ -4.4.474068 \ No newline at end of file diff --git a/fuzzer-data/corpus/330bdbbf97f02d581da5e24983c08db1e172c49e-7 b/fuzzer-data/corpus/330bdbbf97f02d581da5e24983c08db1e172c49e-7 deleted file mode 100644 index 10b536a..0000000 --- a/fuzzer-data/corpus/330bdbbf97f02d581da5e24983c08db1e172c49e-7 +++ /dev/null @@ -1 +0,0 @@ -1+1.1.1.3 \ No newline at end of file diff --git a/fuzzer-data/corpus/36d5ed8e5b39742cf246fc96d6881ab27f256b72-1 b/fuzzer-data/corpus/36d5ed8e5b39742cf246fc96d6881ab27f256b72-1 deleted file mode 100644 index 6460f3a..0000000 --- a/fuzzer-data/corpus/36d5ed8e5b39742cf246fc96d6881ab27f256b72-1 +++ /dev/null @@ -1 +0,0 @@ -1.1.13682021700570577572023021265724475355237556253000065. \ No newline at end of file diff --git a/fuzzer-data/corpus/37251be083d7f99af9e1c7a4f11936f2935f0b17-3 b/fuzzer-data/corpus/37251be083d7f99af9e1c7a4f11936f2935f0b17-3 deleted file mode 100644 index 3d1eb31..0000000 --- a/fuzzer-data/corpus/37251be083d7f99af9e1c7a4f11936f2935f0b17-3 +++ /dev/null @@ -1 +0,0 @@ -0.0. \ No newline at end of file diff --git a/fuzzer-data/corpus/391dba546a4ceef4536faaa5e875d74e8a9030a0-1 b/fuzzer-data/corpus/391dba546a4ceef4536faaa5e875d74e8a9030a0-1 deleted file mode 100644 index c3c541a..0000000 --- a/fuzzer-data/corpus/391dba546a4ceef4536faaa5e875d74e8a9030a0-1 +++ /dev/null @@ -1 +0,0 @@ -0-9+0 \ No newline at end of file diff --git a/fuzzer-data/corpus/3c2743894725d1bd1aad998b62fe189775d98144-2 b/fuzzer-data/corpus/3c2743894725d1bd1aad998b62fe189775d98144-2 deleted file mode 100644 index 0d02908..0000000 --- a/fuzzer-data/corpus/3c2743894725d1bd1aad998b62fe189775d98144-2 +++ /dev/null @@ -1 +0,0 @@ -9-3.1.9.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/3caff6eaef78c897079f0b0fd42d8541fda816cd-2 b/fuzzer-data/corpus/3caff6eaef78c897079f0b0fd42d8541fda816cd-2 deleted file mode 100644 index 2b6fe11..0000000 --- a/fuzzer-data/corpus/3caff6eaef78c897079f0b0fd42d8541fda816cd-2 +++ /dev/null @@ -1 +0,0 @@ -3-9625 \ No newline at end of file diff --git a/fuzzer-data/corpus/3f102db031d5a3c4fbdad8c282e2bf8fb8481659-1 b/fuzzer-data/corpus/3f102db031d5a3c4fbdad8c282e2bf8fb8481659-1 deleted file mode 100644 index aba0891..0000000 --- a/fuzzer-data/corpus/3f102db031d5a3c4fbdad8c282e2bf8fb8481659-1 +++ /dev/null @@ -1 +0,0 @@ -4.0-0 \ No newline at end of file diff --git a/fuzzer-data/corpus/3f5651c4c9a7b65dc4d6bb11e2d6fee7348979d7-3 b/fuzzer-data/corpus/3f5651c4c9a7b65dc4d6bb11e2d6fee7348979d7-3 deleted file mode 100644 index 07d91dc..0000000 --- a/fuzzer-data/corpus/3f5651c4c9a7b65dc4d6bb11e2d6fee7348979d7-3 +++ /dev/null @@ -1 +0,0 @@ -1+1 \ No newline at end of file diff --git a/fuzzer-data/corpus/40fafb398d6afd1118e23783ab54b0e5e3ee524f-5 b/fuzzer-data/corpus/40fafb398d6afd1118e23783ab54b0e5e3ee524f-5 deleted file mode 100644 index 34ebf2d..0000000 --- a/fuzzer-data/corpus/40fafb398d6afd1118e23783ab54b0e5e3ee524f-5 +++ /dev/null @@ -1 +0,0 @@ -1+1.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/417eead3d7461ef6f180ae34e5098ee820af9937-1 b/fuzzer-data/corpus/417eead3d7461ef6f180ae34e5098ee820af9937-1 deleted file mode 100644 index 3c28765..0000000 --- a/fuzzer-data/corpus/417eead3d7461ef6f180ae34e5098ee820af9937-1 +++ /dev/null @@ -1 +0,0 @@ -390625 \ No newline at end of file diff --git a/fuzzer-data/corpus/433c02bb04cd0b7863d94a187b928844877566a1-3 b/fuzzer-data/corpus/433c02bb04cd0b7863d94a187b928844877566a1-3 deleted file mode 100644 index 18befc3..0000000 --- a/fuzzer-data/corpus/433c02bb04cd0b7863d94a187b928844877566a1-3 +++ /dev/null @@ -1 +0,0 @@ -1.98023223876953125 \ No newline at end of file diff --git a/fuzzer-data/corpus/43d738f549254236406186c8793957c8013dcd2b-5 b/fuzzer-data/corpus/43d738f549254236406186c8793957c8013dcd2b-5 deleted file mode 100644 index b4c1ad2..0000000 --- a/fuzzer-data/corpus/43d738f549254236406186c8793957c8013dcd2b-5 +++ /dev/null @@ -1 +0,0 @@ -1+1.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/44a95e175eede0bc4d4a8401e3c74dc87d86b870-1 b/fuzzer-data/corpus/44a95e175eede0bc4d4a8401e3c74dc87d86b870-1 deleted file mode 100644 index bcd3d81..0000000 --- a/fuzzer-data/corpus/44a95e175eede0bc4d4a8401e3c74dc87d86b870-1 +++ /dev/null @@ -1 +0,0 @@ -1.1.- \ No newline at end of file diff --git a/fuzzer-data/corpus/47a7d59899ea104bb3a25be394f68e99e75aac83 b/fuzzer-data/corpus/47a7d59899ea104bb3a25be394f68e99e75aac83 deleted file mode 100644 index 1043767..0000000 --- a/fuzzer-data/corpus/47a7d59899ea104bb3a25be394f68e99e75aac83 +++ /dev/null @@ -1 +0,0 @@ -1.1.0-0 \ No newline at end of file diff --git a/fuzzer-data/corpus/49b2833e472e89fbb407749e375bbe2067a2918c-1 b/fuzzer-data/corpus/49b2833e472e89fbb407749e375bbe2067a2918c-1 deleted file mode 100644 index 0cc9827..0000000 --- a/fuzzer-data/corpus/49b2833e472e89fbb407749e375bbe2067a2918c-1 +++ /dev/null @@ -1 +0,0 @@ -3-02 \ No newline at end of file diff --git a/fuzzer-data/corpus/4c9a4d983a7d6fbc12138f6aa65427c909cde53b-4 b/fuzzer-data/corpus/4c9a4d983a7d6fbc12138f6aa65427c909cde53b-4 deleted file mode 100644 index 33fa7c9..0000000 --- a/fuzzer-data/corpus/4c9a4d983a7d6fbc12138f6aa65427c909cde53b-4 +++ /dev/null @@ -1 +0,0 @@ -1+1.1ˆ \ No newline at end of file diff --git a/fuzzer-data/corpus/4cce5069a59e0dd0fbe6e0ad40c2ff462af15169-5 b/fuzzer-data/corpus/4cce5069a59e0dd0fbe6e0ad40c2ff462af15169-5 deleted file mode 100644 index c8a1205..0000000 --- a/fuzzer-data/corpus/4cce5069a59e0dd0fbe6e0ad40c2ff462af15169-5 +++ /dev/null @@ -1 +0,0 @@ -0-0.0.0.0.0.0.0.0.00 \ No newline at end of file diff --git a/fuzzer-data/corpus/4cd2110b46a0e24fc55b80b3e8f36e6cae6e1fc7-2 b/fuzzer-data/corpus/4cd2110b46a0e24fc55b80b3e8f36e6cae6e1fc7-2 deleted file mode 100644 index 6ebcdcd..0000000 --- a/fuzzer-data/corpus/4cd2110b46a0e24fc55b80b3e8f36e6cae6e1fc7-2 +++ /dev/null @@ -1 +0,0 @@ -0« \ No newline at end of file diff --git a/fuzzer-data/corpus/4de65a8c61f6c737c34af6d628d7e99773261a9e b/fuzzer-data/corpus/4de65a8c61f6c737c34af6d628d7e99773261a9e deleted file mode 100644 index efafc0c..0000000 --- a/fuzzer-data/corpus/4de65a8c61f6c737c34af6d628d7e99773261a9e +++ /dev/null @@ -1 +0,0 @@ -5.- \ No newline at end of file diff --git a/fuzzer-data/corpus/4ec7857e77487a034373fd58c0cb91b809a2c2bb-2 b/fuzzer-data/corpus/4ec7857e77487a034373fd58c0cb91b809a2c2bb-2 deleted file mode 100644 index 1cb22d6..0000000 --- a/fuzzer-data/corpus/4ec7857e77487a034373fd58c0cb91b809a2c2bb-2 +++ /dev/null @@ -1 +0,0 @@ -0-0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/528cf42af97409ff91db4e7793a81bc5f447d215-2 b/fuzzer-data/corpus/528cf42af97409ff91db4e7793a81bc5f447d215-2 deleted file mode 100644 index 1cc5f65..0000000 --- a/fuzzer-data/corpus/528cf42af97409ff91db4e7793a81bc5f447d215-2 +++ /dev/null @@ -1 +0,0 @@ -1.1.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/57c5c9743273a83505451f99a5c697e17a5ff3a9-8 b/fuzzer-data/corpus/57c5c9743273a83505451f99a5c697e17a5ff3a9-8 deleted file mode 100644 index e2dfe6d..0000000 --- a/fuzzer-data/corpus/57c5c9743273a83505451f99a5c697e17a5ff3a9-8 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.1.1.-.1.R.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/57fbc017f5b1563505634b8076274cdfd5a7561a-8 b/fuzzer-data/corpus/57fbc017f5b1563505634b8076274cdfd5a7561a-8 deleted file mode 100644 index 3c44fc8..0000000 --- a/fuzzer-data/corpus/57fbc017f5b1563505634b8076274cdfd5a7561a-8 +++ /dev/null @@ -1 +0,0 @@ -1.1.9+3 \ No newline at end of file diff --git a/fuzzer-data/corpus/59111e052d0b325e00b3417054f77bb064da46ca-3 b/fuzzer-data/corpus/59111e052d0b325e00b3417054f77bb064da46ca-3 deleted file mode 100644 index a0d0ed0..0000000 --- a/fuzzer-data/corpus/59111e052d0b325e00b3417054f77bb064da46ca-3 +++ /dev/null @@ -1 +0,0 @@ -1.1368202170057057757202302126572447535523755625377572023021265724475355237556000065. \ No newline at end of file diff --git a/fuzzer-data/corpus/5e8f8ea63a1be25c2d5d9c03ce5fdf4443037a04-5 b/fuzzer-data/corpus/5e8f8ea63a1be25c2d5d9c03ce5fdf4443037a04-5 deleted file mode 100644 index 09805e0..0000000 --- a/fuzzer-data/corpus/5e8f8ea63a1be25c2d5d9c03ce5fdf4443037a04-5 +++ /dev/null @@ -1 +0,0 @@ -3-a-after \ No newline at end of file diff --git a/fuzzer-data/corpus/60097df2e174d8fa10685e68f8311a2f0d0178f5-4 b/fuzzer-data/corpus/60097df2e174d8fa10685e68f8311a2f0d0178f5-4 deleted file mode 100644 index 32cd30c..0000000 --- a/fuzzer-data/corpus/60097df2e174d8fa10685e68f8311a2f0d0178f5-4 +++ /dev/null @@ -1 +0,0 @@ -9-3.3.1.9.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/6239644c6cf451d75133d78988467ece51ce4734-4 b/fuzzer-data/corpus/6239644c6cf451d75133d78988467ece51ce4734-4 deleted file mode 100644 index 790ecc4..0000000 Binary files a/fuzzer-data/corpus/6239644c6cf451d75133d78988467ece51ce4734-4 and /dev/null differ diff --git a/fuzzer-data/corpus/658484f978118fcffcbd5dd045a0837ac46a3bdf-2 b/fuzzer-data/corpus/658484f978118fcffcbd5dd045a0837ac46a3bdf-2 deleted file mode 100644 index 63b166a..0000000 --- a/fuzzer-data/corpus/658484f978118fcffcbd5dd045a0837ac46a3bdf-2 +++ /dev/null @@ -1 +0,0 @@ -1+ \ No newline at end of file diff --git a/fuzzer-data/corpus/66790faae3201811ae7a53c50a61e31159a727c7-2 b/fuzzer-data/corpus/66790faae3201811ae7a53c50a61e31159a727c7-2 deleted file mode 100644 index 1b8f9e5..0000000 --- a/fuzzer-data/corpus/66790faae3201811ae7a53c50a61e31159a727c7-2 +++ /dev/null @@ -1 +0,0 @@ -1.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/69a460874456d0ad2329b418e944a74e4090579f-1 b/fuzzer-data/corpus/69a460874456d0ad2329b418e944a74e4090579f-1 deleted file mode 100644 index 9063bf3..0000000 --- a/fuzzer-data/corpus/69a460874456d0ad2329b418e944a74e4090579f-1 +++ /dev/null @@ -1 +0,0 @@ -0-0x.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/6ddd299887caeaedf1b83563d67f0aaa65afe680-10 b/fuzzer-data/corpus/6ddd299887caeaedf1b83563d67f0aaa65afe680-10 deleted file mode 100644 index e2cd656..0000000 --- a/fuzzer-data/corpus/6ddd299887caeaedf1b83563d67f0aaa65afe680-10 +++ /dev/null @@ -1 +0,0 @@ -2-V.V.t.e.V \ No newline at end of file diff --git a/fuzzer-data/corpus/6e0be32f6c086c546c02252c2e87386485177919-5 b/fuzzer-data/corpus/6e0be32f6c086c546c02252c2e87386485177919-5 deleted file mode 100644 index 8719bd8..0000000 --- a/fuzzer-data/corpus/6e0be32f6c086c546c02252c2e87386485177919-5 +++ /dev/null @@ -1 +0,0 @@ -0-0.0.0.0.0.00 \ No newline at end of file diff --git a/fuzzer-data/corpus/6ea9b16837561e11c08a902bb1e91e89818b8500-7 b/fuzzer-data/corpus/6ea9b16837561e11c08a902bb1e91e89818b8500-7 deleted file mode 100644 index 96228fe..0000000 --- a/fuzzer-data/corpus/6ea9b16837561e11c08a902bb1e91e89818b8500-7 +++ /dev/null @@ -1 +0,0 @@ -1+1.fterafter \ No newline at end of file diff --git a/fuzzer-data/corpus/708da5940ff731344140577e29f53dd8d55c5ba1-3 b/fuzzer-data/corpus/708da5940ff731344140577e29f53dd8d55c5ba1-3 deleted file mode 100644 index 1c8af92..0000000 --- a/fuzzer-data/corpus/708da5940ff731344140577e29f53dd8d55c5ba1-3 +++ /dev/null @@ -1 +0,0 @@ -1++ \ No newline at end of file diff --git a/fuzzer-data/corpus/70f5225fdcca42b0f422a5dbc27663bba9f722c8-1 b/fuzzer-data/corpus/70f5225fdcca42b0f422a5dbc27663bba9f722c8-1 deleted file mode 100644 index 0a167c1..0000000 --- a/fuzzer-data/corpus/70f5225fdcca42b0f422a5dbc27663bba9f722c8-1 +++ /dev/null @@ -1 +0,0 @@ -0-9+ \ No newline at end of file diff --git a/fuzzer-data/corpus/71580937775dde0eb72c1dc6be2866cf68ab4641-3 b/fuzzer-data/corpus/71580937775dde0eb72c1dc6be2866cf68ab4641-3 deleted file mode 100644 index a612e30..0000000 --- a/fuzzer-data/corpus/71580937775dde0eb72c1dc6be2866cf68ab4641-3 +++ /dev/null @@ -1 +0,0 @@ -1.1.11. \ No newline at end of file diff --git a/fuzzer-data/corpus/7b52009b64fd0a2a49e6d8a939753077792b0554-1 b/fuzzer-data/corpus/7b52009b64fd0a2a49e6d8a939753077792b0554-1 deleted file mode 100644 index 3cacc0b..0000000 --- a/fuzzer-data/corpus/7b52009b64fd0a2a49e6d8a939753077792b0554-1 +++ /dev/null @@ -1 +0,0 @@ -12 \ No newline at end of file diff --git a/fuzzer-data/corpus/7f91399116ffff045d77b94bf735f7ee27e3a98c b/fuzzer-data/corpus/7f91399116ffff045d77b94bf735f7ee27e3a98c deleted file mode 100644 index 51fd4c0..0000000 --- a/fuzzer-data/corpus/7f91399116ffff045d77b94bf735f7ee27e3a98c +++ /dev/null @@ -1 +0,0 @@ -0-57e-33304e-910946379282317958222700xfC792823CfB5BfAEd6cfFebe7D910946379282317958222700xfC792823CfB5BfAEd6cfFebe7D \ No newline at end of file diff --git a/fuzzer-data/corpus/832669bf34509f1e061c99388cb04579e43060e0-6 b/fuzzer-data/corpus/832669bf34509f1e061c99388cb04579e43060e0-6 deleted file mode 100644 index 301792e..0000000 --- a/fuzzer-data/corpus/832669bf34509f1e061c99388cb04579e43060e0-6 +++ /dev/null @@ -1 +0,0 @@ -3-a-fterafter \ No newline at end of file diff --git a/fuzzer-data/corpus/83c701b0fa86278fc7b62ce4a22f5dfb41d47b59-3 b/fuzzer-data/corpus/83c701b0fa86278fc7b62ce4a22f5dfb41d47b59-3 deleted file mode 100644 index 9dabd5e..0000000 --- a/fuzzer-data/corpus/83c701b0fa86278fc7b62ce4a22f5dfb41d47b59-3 +++ /dev/null @@ -1 +0,0 @@ -3- \ No newline at end of file diff --git a/fuzzer-data/corpus/8dc053e65af805df5b03402b2fc4a22f60c7a2d5-3 b/fuzzer-data/corpus/8dc053e65af805df5b03402b2fc4a22f60c7a2d5-3 deleted file mode 100644 index 1a35742..0000000 --- a/fuzzer-data/corpus/8dc053e65af805df5b03402b2fc4a22f60c7a2d5-3 +++ /dev/null @@ -1 +0,0 @@ -3-< \ No newline at end of file diff --git a/fuzzer-data/corpus/8e73d92eff074ea0e8f1353709e61309b3784cec-1 b/fuzzer-data/corpus/8e73d92eff074ea0e8f1353709e61309b3784cec-1 deleted file mode 100644 index e196196..0000000 --- a/fuzzer-data/corpus/8e73d92eff074ea0e8f1353709e61309b3784cec-1 +++ /dev/null @@ -1 +0,0 @@ -3-4.9.4 \ No newline at end of file diff --git a/fuzzer-data/corpus/8f78cdd8faec4af85ac945d956ec963ffe7c1543-3 b/fuzzer-data/corpus/8f78cdd8faec4af85ac945d956ec963ffe7c1543-3 deleted file mode 100644 index 2902e46..0000000 --- a/fuzzer-data/corpus/8f78cdd8faec4af85ac945d956ec963ffe7c1543-3 +++ /dev/null @@ -1 +0,0 @@ -1+57e-3330-57e-3346379282317068958222700xfC792823CfB5BfAEd6cfFebe7D \ No newline at end of file diff --git a/fuzzer-data/corpus/915fe6eb01c4a4178fd52685252889380eb2a505 b/fuzzer-data/corpus/915fe6eb01c4a4178fd52685252889380eb2a505 deleted file mode 100644 index 7ce179c..0000000 --- a/fuzzer-data/corpus/915fe6eb01c4a4178fd52685252889380eb2a505 +++ /dev/null @@ -1 +0,0 @@ -0-1690993073057962936658730400845563-0xacC.-0xFe34b9 \ No newline at end of file diff --git a/fuzzer-data/corpus/96c17719bf4d5d4690644a5bbb9c84162cc0cdcd b/fuzzer-data/corpus/96c17719bf4d5d4690644a5bbb9c84162cc0cdcd deleted file mode 100644 index 843fb75..0000000 --- a/fuzzer-data/corpus/96c17719bf4d5d4690644a5bbb9c84162cc0cdcd +++ /dev/null @@ -1 +0,0 @@ -0-057e-33304e-910946379282317958222700xfCCfB5BfAEd6cfFebe7D \ No newline at end of file diff --git a/fuzzer-data/corpus/99b46950daf0e04a42d8b6afcd89e90bf813baa5-14 b/fuzzer-data/corpus/99b46950daf0e04a42d8b6afcd89e90bf813baa5-14 deleted file mode 100644 index ec3fb2a..0000000 --- a/fuzzer-data/corpus/99b46950daf0e04a42d8b6afcd89e90bf813baa5-14 +++ /dev/null @@ -1 +0,0 @@ -4-V.t.t.V.t.t.t.e.e.V.t.e.V.t.e.e.V.t.e.t.e.e.V.t.e.V.t.e.e.V.t.e.V \ No newline at end of file diff --git a/fuzzer-data/corpus/9a78211436f6d425ec38f5c4e02270801f3524f8-1 b/fuzzer-data/corpus/9a78211436f6d425ec38f5c4e02270801f3524f8-1 deleted file mode 100644 index b516b2c..0000000 --- a/fuzzer-data/corpus/9a78211436f6d425ec38f5c4e02270801f3524f8-1 +++ /dev/null @@ -1 +0,0 @@ -@ \ No newline at end of file diff --git a/fuzzer-data/corpus/9e6cf7f00f4930d04975d8052130879355d2bfb8-3 b/fuzzer-data/corpus/9e6cf7f00f4930d04975d8052130879355d2bfb8-3 deleted file mode 100644 index d429d70..0000000 --- a/fuzzer-data/corpus/9e6cf7f00f4930d04975d8052130879355d2bfb8-3 +++ /dev/null @@ -1 +0,0 @@ -9-3.1.9.1.n \ No newline at end of file diff --git a/fuzzer-data/corpus/a070d54a0529bd858d37b645c436be5be30bbd5b-6 b/fuzzer-data/corpus/a070d54a0529bd858d37b645c436be5be30bbd5b-6 deleted file mode 100644 index 1c08ef7..0000000 --- a/fuzzer-data/corpus/a070d54a0529bd858d37b645c436be5be30bbd5b-6 +++ /dev/null @@ -1 +0,0 @@ -0-0.0-.0.0.0.0.0.0.0.0.0.0.0.0.0.0.00 \ No newline at end of file diff --git a/fuzzer-data/corpus/a2f2489d26fedaa937e9967308860e68760e17be-7 b/fuzzer-data/corpus/a2f2489d26fedaa937e9967308860e68760e17be-7 deleted file mode 100644 index 64e2f68..0000000 --- a/fuzzer-data/corpus/a2f2489d26fedaa937e9967308860e68760e17be-7 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.1.1.R.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/a421cd480d84191a29fd027834cdd8560a82e70c-5 b/fuzzer-data/corpus/a421cd480d84191a29fd027834cdd8560a82e70c-5 deleted file mode 100644 index 44d3b7f..0000000 --- a/fuzzer-data/corpus/a421cd480d84191a29fd027834cdd8560a82e70c-5 +++ /dev/null @@ -1 +0,0 @@ -9-3.1.1.1.9.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/a5761de3b3dc2bd93e42ee844a168d79881cea52-10 b/fuzzer-data/corpus/a5761de3b3dc2bd93e42ee844a168d79881cea52-10 deleted file mode 100644 index 41702b2..0000000 --- a/fuzzer-data/corpus/a5761de3b3dc2bd93e42ee844a168d79881cea52-10 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.9.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/a741a7ed1705bcdabb09f873fde1fa3fa252a057-2 b/fuzzer-data/corpus/a741a7ed1705bcdabb09f873fde1fa3fa252a057-2 deleted file mode 100644 index 5ef0578..0000000 --- a/fuzzer-data/corpus/a741a7ed1705bcdabb09f873fde1fa3fa252a057-2 +++ /dev/null @@ -1 +0,0 @@ -3.1.1-2 \ No newline at end of file diff --git a/fuzzer-data/corpus/a7b9bec886f32f8a8b9e10d4a9014482eebda31e-11 b/fuzzer-data/corpus/a7b9bec886f32f8a8b9e10d4a9014482eebda31e-11 deleted file mode 100644 index f4a80ea..0000000 --- a/fuzzer-data/corpus/a7b9bec886f32f8a8b9e10d4a9014482eebda31e-11 +++ /dev/null @@ -1 +0,0 @@ -2-V.t.e.V.t.e.V \ No newline at end of file diff --git a/fuzzer-data/corpus/ae6b5ef7f732cb259e777864ba1027620a36f95a b/fuzzer-data/corpus/ae6b5ef7f732cb259e777864ba1027620a36f95a deleted file mode 100644 index ea4012b..0000000 --- a/fuzzer-data/corpus/ae6b5ef7f732cb259e777864ba1027620a36f95a +++ /dev/null @@ -1 +0,0 @@ -3-9402004353104906.474368202171 \ No newline at end of file diff --git a/fuzzer-data/corpus/b279a2c6ab8901f6d26140ff29ebe4aa58e68f9b-3 b/fuzzer-data/corpus/b279a2c6ab8901f6d26140ff29ebe4aa58e68f9b-3 deleted file mode 100644 index 552260b..0000000 --- a/fuzzer-data/corpus/b279a2c6ab8901f6d26140ff29ebe4aa58e68f9b-3 +++ /dev/null @@ -1 +0,0 @@ -3.1.8081828384858687888912 \ No newline at end of file diff --git a/fuzzer-data/corpus/b3e9d18c005d9b8e3e73378c26b6ff1c34df10ec-8 b/fuzzer-data/corpus/b3e9d18c005d9b8e3e73378c26b6ff1c34df10ec-8 deleted file mode 100644 index b997b79..0000000 --- a/fuzzer-data/corpus/b3e9d18c005d9b8e3e73378c26b6ff1c34df10ec-8 +++ /dev/null @@ -1 +0,0 @@ -1+1.1.1.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/b491ba55e44ab692aa0b3bac4ea9d0712bd72fed-8 b/fuzzer-data/corpus/b491ba55e44ab692aa0b3bac4ea9d0712bd72fed-8 deleted file mode 100644 index ee0bf15..0000000 --- a/fuzzer-data/corpus/b491ba55e44ab692aa0b3bac4ea9d0712bd72fed-8 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.4.0.1.-.1.R.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/b5aa00da2b94397e69cccf4bb3c4d23670ce14b6-6 b/fuzzer-data/corpus/b5aa00da2b94397e69cccf4bb3c4d23670ce14b6-6 deleted file mode 100644 index 9ae4e72..0000000 --- a/fuzzer-data/corpus/b5aa00da2b94397e69cccf4bb3c4d23670ce14b6-6 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.1.1.R.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/b64bc125e87e97dc11adff19df174855594962a1 b/fuzzer-data/corpus/b64bc125e87e97dc11adff19df174855594962a1 deleted file mode 100644 index b24b2f0..0000000 --- a/fuzzer-data/corpus/b64bc125e87e97dc11adff19df174855594962a1 +++ /dev/null @@ -1 +0,0 @@ -0-0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0-.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c-2 b/fuzzer-data/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c-2 deleted file mode 100644 index c227083..0000000 --- a/fuzzer-data/corpus/b6589fc6ab0dc82cf12099d1c2d40ab994e8410c-2 +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file diff --git a/fuzzer-data/corpus/b8d6a0e0a2496d8dbe324d28c70ec37c40432c6c-1 b/fuzzer-data/corpus/b8d6a0e0a2496d8dbe324d28c70ec37c40432c6c-1 deleted file mode 100644 index 5993394..0000000 --- a/fuzzer-data/corpus/b8d6a0e0a2496d8dbe324d28c70ec37c40432c6c-1 +++ /dev/null @@ -1 +0,0 @@ -0-057e-33304e-910946379282317958222700xfC792823CfB5BfAEd6cfFebe7D \ No newline at end of file diff --git a/fuzzer-data/corpus/bbfe606ff41ca9ef93ee464bc3cc2932d4dc1872-3 b/fuzzer-data/corpus/bbfe606ff41ca9ef93ee464bc3cc2932d4dc1872-3 deleted file mode 100644 index 1496171..0000000 Binary files a/fuzzer-data/corpus/bbfe606ff41ca9ef93ee464bc3cc2932d4dc1872-3 and /dev/null differ diff --git a/fuzzer-data/corpus/bd952513ae9dce3e914b4918eae08e1eddd37faa-4 b/fuzzer-data/corpus/bd952513ae9dce3e914b4918eae08e1eddd37faa-4 deleted file mode 100644 index 8cfbc90..0000000 --- a/fuzzer-data/corpus/bd952513ae9dce3e914b4918eae08e1eddd37faa-4 +++ /dev/null @@ -1 +0,0 @@ -1.1.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/bde27e278dd0c88d6ae7270ce0a0216561eda4b3-4 b/fuzzer-data/corpus/bde27e278dd0c88d6ae7270ce0a0216561eda4b3-4 deleted file mode 100644 index dc99f6b..0000000 --- a/fuzzer-data/corpus/bde27e278dd0c88d6ae7270ce0a0216561eda4b3-4 +++ /dev/null @@ -1 +0,0 @@ -0-0.0.0.0.0.0.00 \ No newline at end of file diff --git a/fuzzer-data/corpus/c4db7026aff01c30b1daa8fe44e4da9f0eb887df-6 b/fuzzer-data/corpus/c4db7026aff01c30b1daa8fe44e4da9f0eb887df-6 deleted file mode 100644 index 65389e7..0000000 --- a/fuzzer-data/corpus/c4db7026aff01c30b1daa8fe44e4da9f0eb887df-6 +++ /dev/null @@ -1 +0,0 @@ -1+1.1.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/c5b02b148a05c761e2649ddb6bf4079affe5c7ed-7 b/fuzzer-data/corpus/c5b02b148a05c761e2649ddb6bf4079affe5c7ed-7 deleted file mode 100644 index 202f7e4..0000000 --- a/fuzzer-data/corpus/c5b02b148a05c761e2649ddb6bf4079affe5c7ed-7 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.1.1.-.1.R.1. \ No newline at end of file diff --git a/fuzzer-data/corpus/c883a800931625ff2db152d40747f7de516e8d15-5 b/fuzzer-data/corpus/c883a800931625ff2db152d40747f7de516e8d15-5 deleted file mode 100644 index 26e4530..0000000 --- a/fuzzer-data/corpus/c883a800931625ff2db152d40747f7de516e8d15-5 +++ /dev/null @@ -1 +0,0 @@ -0.0.0. \ No newline at end of file diff --git a/fuzzer-data/corpus/cec3bb934dfa51b7cb4de3b3d5b8778a5ade50ac-6 b/fuzzer-data/corpus/cec3bb934dfa51b7cb4de3b3d5b8778a5ade50ac-6 deleted file mode 100644 index e22c729..0000000 --- a/fuzzer-data/corpus/cec3bb934dfa51b7cb4de3b3d5b8778a5ade50ac-6 +++ /dev/null @@ -1 +0,0 @@ -9-3.1.1.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/d1c88556c34d3cd263b2d6e45f4de5427f24708c-1 b/fuzzer-data/corpus/d1c88556c34d3cd263b2d6e45f4de5427f24708c-1 deleted file mode 100644 index b1eed35..0000000 --- a/fuzzer-data/corpus/d1c88556c34d3cd263b2d6e45f4de5427f24708c-1 +++ /dev/null @@ -1 +0,0 @@ -9+3.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.-.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/d3740f336a92d2fe7f04e026c5ef8e717b22f45e-4 b/fuzzer-data/corpus/d3740f336a92d2fe7f04e026c5ef8e717b22f45e-4 deleted file mode 100644 index d6969b1..0000000 --- a/fuzzer-data/corpus/d3740f336a92d2fe7f04e026c5ef8e717b22f45e-4 +++ /dev/null @@ -1 +0,0 @@ -3-after \ No newline at end of file diff --git a/fuzzer-data/corpus/d47478fa527dfa548da03533f947a403a31b24a3-12 b/fuzzer-data/corpus/d47478fa527dfa548da03533f947a403a31b24a3-12 deleted file mode 100644 index 32d5265..0000000 --- a/fuzzer-data/corpus/d47478fa527dfa548da03533f947a403a31b24a3-12 +++ /dev/null @@ -1 +0,0 @@ -2-V.t.t.e.e.V.t.e.V \ No newline at end of file diff --git a/fuzzer-data/corpus/d4946b0341549157431d1f70027ea88460088742-7 b/fuzzer-data/corpus/d4946b0341549157431d1f70027ea88460088742-7 deleted file mode 100644 index 807829b..0000000 --- a/fuzzer-data/corpus/d4946b0341549157431d1f70027ea88460088742-7 +++ /dev/null @@ -1 +0,0 @@ -0-0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/d58163643f1fa44bd85fc30742b81586929933ae-2 b/fuzzer-data/corpus/d58163643f1fa44bd85fc30742b81586929933ae-2 deleted file mode 100644 index 24f80c2..0000000 --- a/fuzzer-data/corpus/d58163643f1fa44bd85fc30742b81586929933ae-2 +++ /dev/null @@ -1 +0,0 @@ -1.1.1368202170057057757202302126572447535523755625377572023021265724475355237556000065. \ No newline at end of file diff --git a/fuzzer-data/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 b/fuzzer-data/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709 deleted file mode 100644 index e69de29..0000000 diff --git a/fuzzer-data/corpus/db9c44d9c07a786320eb625fbb784bcd97e3b2f9-4 b/fuzzer-data/corpus/db9c44d9c07a786320eb625fbb784bcd97e3b2f9-4 deleted file mode 100644 index 7947169..0000000 --- a/fuzzer-data/corpus/db9c44d9c07a786320eb625fbb784bcd97e3b2f9-4 +++ /dev/null @@ -1 +0,0 @@ -1.1.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/dc056232160501f459f40d83179268b7c525e68c b/fuzzer-data/corpus/dc056232160501f459f40d83179268b7c525e68c deleted file mode 100644 index e45c210..0000000 --- a/fuzzer-data/corpus/dc056232160501f459f40d83179268b7c525e68c +++ /dev/null @@ -1 +0,0 @@ -4.4743682021710570577572023021265724475355237556253000065.02 \ No newline at end of file diff --git a/fuzzer-data/corpus/ddfe163345d338193ac2bdc183f8e9dcff904b43-1 b/fuzzer-data/corpus/ddfe163345d338193ac2bdc183f8e9dcff904b43-1 deleted file mode 100644 index a616ad4..0000000 --- a/fuzzer-data/corpus/ddfe163345d338193ac2bdc183f8e9dcff904b43-1 +++ /dev/null @@ -1 +0,0 @@ -01 \ No newline at end of file diff --git a/fuzzer-data/corpus/de4fef8ccbee3bdd20c445c83a12fa00dd60038a b/fuzzer-data/corpus/de4fef8ccbee3bdd20c445c83a12fa00dd60038a deleted file mode 100644 index cc781bd..0000000 --- a/fuzzer-data/corpus/de4fef8ccbee3bdd20c445c83a12fa00dd60038a +++ /dev/null @@ -1 +0,0 @@ -9+V.1.3.1.1.1.1.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/e562f69ec36e625116376f376d991e41613e9bf3 b/fuzzer-data/corpus/e562f69ec36e625116376f376d991e41613e9bf3 deleted file mode 100644 index 1f2c8da..0000000 --- a/fuzzer-data/corpus/e562f69ec36e625116376f376d991e41613e9bf3 +++ /dev/null @@ -1 +0,0 @@ -0.0.0.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/e8dc057d3346e56aed7cf252185dbe1fa6454411-1 b/fuzzer-data/corpus/e8dc057d3346e56aed7cf252185dbe1fa6454411-1 deleted file mode 100644 index 9f8e9b6..0000000 --- a/fuzzer-data/corpus/e8dc057d3346e56aed7cf252185dbe1fa6454411-1 +++ /dev/null @@ -1 +0,0 @@ -1.0 \ No newline at end of file diff --git a/fuzzer-data/corpus/ebf55cf4cfc92240cc9524a5cea022ba997b8b63-9 b/fuzzer-data/corpus/ebf55cf4cfc92240cc9524a5cea022ba997b8b63-9 deleted file mode 100644 index ccf7b95..0000000 --- a/fuzzer-data/corpus/ebf55cf4cfc92240cc9524a5cea022ba997b8b63-9 +++ /dev/null @@ -1 +0,0 @@ -2-V.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.9.1.9.1 \ No newline at end of file diff --git a/fuzzer-data/corpus/edb0d51418b0825a56ea53891f828451d97615eb-3 b/fuzzer-data/corpus/edb0d51418b0825a56ea53891f828451d97615eb-3 deleted file mode 100644 index 9965b4c..0000000 --- a/fuzzer-data/corpus/edb0d51418b0825a56ea53891f828451d97615eb-3 +++ /dev/null @@ -1 +0,0 @@ -3-m \ No newline at end of file diff --git a/fuzzer-data/corpus/ee9a9bd546ed81c8a1999a053a120822cd84c9db-1 b/fuzzer-data/corpus/ee9a9bd546ed81c8a1999a053a120822cd84c9db-1 deleted file mode 100644 index 1beffa8..0000000 --- a/fuzzer-data/corpus/ee9a9bd546ed81c8a1999a053a120822cd84c9db-1 +++ /dev/null @@ -1 +0,0 @@ -9 \ No newline at end of file diff --git a/fuzzer-data/corpus/f173d05d53079267a49d1c92d5a5721b0eee370f-10 b/fuzzer-data/corpus/f173d05d53079267a49d1c92d5a5721b0eee370f-10 deleted file mode 100644 index 4a56600..0000000 --- a/fuzzer-data/corpus/f173d05d53079267a49d1c92d5a5721b0eee370f-10 +++ /dev/null @@ -1 +0,0 @@ -2-V.V.e.V \ No newline at end of file diff --git a/fuzzer-data/suppressions/378d2b300598b60b1d63f2c7e21f54ee643fa3cf b/fuzzer-data/suppressions/378d2b300598b60b1d63f2c7e21f54ee643fa3cf deleted file mode 100644 index 426b5f1..0000000 --- a/fuzzer-data/suppressions/378d2b300598b60b1d63f2c7e21f54ee643fa3cf +++ /dev/null @@ -1,4 +0,0 @@ -panic: reserialized string != deserialized string -go.bug.st/relaxed-semver/fuzzer.Fuzz -go-fuzz-dep.Main -main.main diff --git a/fuzzer.go b/fuzzer.go deleted file mode 100644 index eac8027..0000000 --- a/fuzzer.go +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright 2018-2023 Cristian Maglie. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// - -// +build gofuzz - -package semver - -// Fuzz is used for fuzzy testing the project -func Fuzz(data []byte) int { - v, err := Parse(string(data)) - if err != nil { - if v != nil { - panic("v != nil on error") - } - return 0 - } - if v.String() != string(data) { - panic("reserialized string != deserialized string") - } - v.Normalize() - if v.CompareTo(v) != 0 { - panic("compare != 0 while comparing with self") - } - r := ParseRelaxed(string(data)) - if r.String() != string(data) { - panic("reserialized relaxed string != deserialized string") - } - return 1 -} diff --git a/fuzzer_test.go b/fuzzer_test.go new file mode 100644 index 0000000..81717e5 --- /dev/null +++ b/fuzzer_test.go @@ -0,0 +1,221 @@ +// +// Copyright 2018-2025 Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +package semver + +import ( + "cmp" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func FuzzParser(f *testing.F) { + f.Add("0-") + f.Add("9+V.1.3.1.1.1.1.1.9.1.3.1.1.1.1.1.9.1") + f.Add("757202302126572447535523755625377572023021265724475355237556000065.") + f.Add("4+57023021265724475355237556253000065.\x00") + f.Add("0--xAbbbbeAcAcCECaBaAAaAfeAdEBe-xfCCfBBfAEdcfFebeDxfCCfBBfAEdcfFebeD") + f.Add("9-V.1.3.1.1.1.1.1.9.1") + f.Add("3.1.12") + f.Add("4.474368202171") + f.Add("2-V.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.9.1") + f.Add("4.02") + f.Add("0-057e-33304e-91094BfAEd6cf6379282317958222700xfCCfB5BfAEd6cfFebe7D") + f.Add("0\x01") + f.Add("9+3.1.4.0.1.-.1.R.1") + f.Add("1.1.1\x0e") + f.Add("4-V.t.t.t.e.e.V.t.e.V.t.e.e.V.t.e.V") + f.Add("1.0x") + f.Add("1+1.1.1") + f.Add("0-0-.0.0") + f.Add("4.4.4740683-m") + f.Add("0-0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0") + f.Add("0-57e-33304e-910946379282317068958222700xfC792823CfB5BfAEd6cfFebe7D") + f.Add("9298023223876953125\v") + f.Add("4.4.474068") + f.Add("1+1.1.1.3") + f.Add("1.1.13682021700570577572023021265724475355237556253000065.") + f.Add("0.0.") + f.Add("0-9+0") + f.Add("9-3.1.9.1.\x81") + f.Add("3-9625") + f.Add("4.0-0") + f.Add("1+1") + f.Add("1+1.1") + f.Add("390625") + f.Add("1.98023223876953125\v") + f.Add("1+1.1.") + f.Add("1.1.-") + f.Add("1.1.0-0") + f.Add("3-02") + f.Add("1+1.1\x88") + f.Add("0-0.0.0.0.0.0.0.0.00") + f.Add("0\xab") + f.Add("5.-") + f.Add("0-0.0") + f.Add("1.1.0") + f.Add("9+3.1.1.1.-.1.R.1") + f.Add("1.1.9+3") + f.Add("1.1368202170057057757202302126572447535523755625377572023021265724475355237556000065.") + f.Add("3-a-after ") + f.Add("9-3.3.1.9.1.") + f.Add("1+19446951953614188\x00") + f.Add("1+") + f.Add("1.1\x0e") + f.Add("0-0x.0") + f.Add("2-V.V.t.e.V") + f.Add("0-0.0.0.0.0.00") + f.Add("1+1.fterafter ") + f.Add("1++") + f.Add("0-9+") + f.Add("1.1.11.") + f.Add("12") + f.Add("0-57e-33304e-910946379282317958222700xfC792823CfB5BfAEd6cfFebe7D910946379282317958222700xfC792823CfB5BfAEd6cfFebe7D") + f.Add("3-a-fterafter ") + f.Add("3-") + f.Add("3-<") + f.Add("3-4.9.4") + f.Add("1+57e-3330-57e-3346379282317068958222700xfC792823CfB5BfAEd6cfFebe7D") + f.Add("0-1690993073057962936658730400845563-0xacC.-0xFe34b9") + f.Add("0-057e-33304e-910946379282317958222700xfCCfB5BfAEd6cfFebe7D") + f.Add("4-V.t.t.V.t.t.t.e.e.V.t.e.V.t.e.e.V.t.e.t.e.e.V.t.e.V.t.e.e.V.t.e.V") + f.Add("@") + f.Add("9-3.1.9.1.n") + f.Add("0-0.0-.0.0.0.0.0.0.0.0.0.0.0.0.0.0.00") + f.Add("9+3.1.1.1.R.1") + f.Add("9-3.1.1.1.9.1.") + f.Add("9+3.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.9.1.9.1") + f.Add("3.1.1-2") + f.Add("2-V.t.e.V.t.e.V") + f.Add("3-9402004353104906.474368202171") + f.Add("3.1.8081828384858687888912") + f.Add("1+1.1.1.1.") + f.Add("9+3.1.4.0.1.-.1.R.1.") + f.Add("9+3.1.1.1.R.1.") + f.Add("0-0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0-.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0") + f.Add("0") + f.Add("0-057e-33304e-910946379282317958222700xfC792823CfB5BfAEd6cfFebe7D") + f.Add("34694469519536141888238489627838134765\x00") + f.Add("1.1.1") + f.Add("0-0.0.0.0.0.0.00") + f.Add("1+1.1.1.") + f.Add("9+3.1.1.1.-.1.R.1.") + f.Add("0.0.0.") + f.Add("9-3.1.1.1.9.1") + f.Add("9+3.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.-.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0") + f.Add("3-after ") + f.Add("2-V.t.t.e.e.V.t.e.V") + f.Add("0-0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0") + f.Add("1.1.1368202170057057757202302126572447535523755625377572023021265724475355237556000065.") + f.Add("") + f.Add("1.1.0\x0e") + f.Add("4.4743682021710570577572023021265724475355237556253000065.02") + f.Add("01") + f.Add("9+V.1.3.1.1.1.1.1.9.1") + f.Add("0.0.0.0") + f.Add("1.0") + f.Add("2-V.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.3.1.1.1.1.1.V.1.3.1.1.1.1.1.9.1.9.1") + f.Add("3-m") + f.Add("9\v") + f.Add("2-V.V.e.V") + f.Fuzz(func(t *testing.T, in string) { + // ParseRelaxed should always succeed + r := ParseRelaxed(in) + if r.String() != in { + t.Fatalf("reserialized relaxed string != deserialized string (in=%v)", in) + } + if r.CompareTo(r) != 0 { + t.Fatalf("compare != 0 while comparing with self (in=%v)", in) + } + + // Parse should succeed only if the input is a valid semver + v, err := Parse(in) + if err != nil { + if v != nil { + t.Fatalf("v != nil on error (in=%v)", in) + } + return + } + if v.String() != in { + t.Fatalf("reserialized string != deserialized string (in=%v)", in) + } + if v.CompareTo(v) != 0 { + t.Fatalf("compare != 0 while comparing with self (in=%v)", in) + } + v.Normalize() + if v.CompareTo(v) != 0 { + t.Fatalf("compare != 0 while comparing with self (in=%v)", in) + } + }) +} + +func FuzzComparators(f *testing.F) { + f.Add("1.2.4", "0.0.1-rc.0") + f.Add("1.3.0-rc.0+build", "0.0.1-rc.0+build") + f.Add("1.3.0", "0.0.1-rc.1") + f.Add("1.3.0+build", "0.0.1") + f.Add("0.0.1+build", "0.0.1-rc.0") + f.Add("0.0.2-rc.1", "0.0.1-rc.0+build") + f.Add("0.0.2-rc.1+build", "0.0.1-rc.1") + f.Add("0.0.2", "0.0.1") + f.Add("0.0.2+build", "0.0.1+build") + f.Add("0.0.3-rc.1", "0.0.2-rc.1") + f.Add("0.0.3-rc.2", "0.0.2-rc.1+build") + f.Add("0.0.3", "0.0.2") + f.Add("0.1.0", "0.0.2+build") + f.Add("0.3.3-rc.0", "0.0.3-rc.1") + f.Add("0.3.3-rc.1", "0.0.3-rc.2") + f.Add("0.3.3", "0.0.3") + f.Add("0.3.3+build", "0.1.0") + f.Add("0.3.4-rc.1", "0.3.3-rc.0") + f.Add("0.3.4", "0.3.3-rc.1") + f.Add("0.4.0", "0.3.3") + f.Add("1.0.0-rc", "0.3.3+build") + f.Add("1.0.0", "0.3.4-rc.1") + f.Add("1.0.0+build", "0.3.4") + f.Add("1.2.1-rc", "0.4.0") + f.Add("1.2.1", "1.0.0-rc") + f.Add("1.2.1+build", "1.0.0") + f.Add("1.2.3-rc.2", "1.0.0+build") + f.Add("1.2.3-rc.2+build", "1.2.1-rc") + f.Add("1.2.3", "1.2.1") + f.Add("1.2.3+build", "1.2.1+build") + f.Add("1.2.4", "1.2.3-rc.2") + f.Add("1.3.0-rc.0+build", "1.2.3-rc.2+build") + f.Add("1.3.0", "1.2.3") + f.Add("1.3.0+build", "1.2.3+build") + f.Add("1.3.1-rc.0", "1.2.4") + f.Add("1.3.1-rc.1", "1.3.0-rc.0+build") + f.Add("1.3.1", "1.3.0") + f.Add("1.3.5", "1.3.0+build") + f.Add("2.0.0-rc", "1.3.1-rc.0") + f.Add("2.0.0-rc+build", "1.3.1-rc.1") + f.Add("2.0.0", "1.3.1") + f.Add("2.0.0+build", "1.3.5") + f.Add("2.1.0-rc", "2.0.0-rc") + f.Add("2.1.0-rc+build", "2.0.0-rc+build") + f.Add("2.1.0", "2.0.0") + f.Add("2.1.0+build", "2.0.0+build") + f.Add("2.1.3-rc", "2.1.0-rc") + f.Add("2.1.3", "2.1.0-rc+build") + f.Add("2.3.0", "2.1.0") + f.Add("2.3.1", "2.1.0+build") + f.Add("3.0.0", "2.1.3-rc") + f.Fuzz(func(t *testing.T, a, b string) { + va, err := Parse(a) + if err != nil { + return + } + vb, err := Parse(b) + if err != nil { + return + } + fmt.Println(va.SortableString(), vb.SortableString()) + require.Equal(t, va.CompareTo(vb), cmp.Compare(va.SortableString(), vb.SortableString()), "Comparing: %s and %s", a, b) + }) +} diff --git a/go.mod b/go.mod index 1ad277c..f2495ce 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module go.bug.st/relaxed-semver -go 1.21 +go 1.24 require ( - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.10.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 2922c94..713a0b4 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,10 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/json.go b/json.go index c72e4b1..7bd08fe 100644 --- a/json.go +++ b/json.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/json_test.go b/json_test.go index 0c4a4fb..b148559 100644 --- a/json_test.go +++ b/json_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -69,7 +69,7 @@ func BenchmarkJSONDecoding(b *testing.B) { data, _ := json.Marshal(v) var u Version for i := 0; i < b.N; i++ { - json.Unmarshal(data, &u) + _ = json.Unmarshal(data, &u) } } @@ -79,6 +79,6 @@ func BenchmarkJSONDecodingRelaxed(b *testing.B) { data, _ := json.Marshal(v) var u RelaxedVersion for i := 0; i < b.N; i++ { - json.Unmarshal(data, &u) + _ = json.Unmarshal(data, &u) } } diff --git a/list.go b/list.go index 8f0adea..952e4fe 100644 --- a/list.go +++ b/list.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/list_test.go b/list_test.go index b67256d..64f6c5e 100644 --- a/list_test.go +++ b/list_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/parser.go b/parser.go index 17eaba3..cdb1db2 100644 --- a/parser.go +++ b/parser.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -279,35 +279,3 @@ func parse(result *Version) error { } return fmt.Errorf("invalid separator: '%c'", curr) } - -func (v *Version) majorString() string { - return v.raw[:v.major] -} - -func (v *Version) minorString() string { - if v.minor > v.major { - return v.raw[v.major+1 : v.minor] - } - return "" -} - -func (v *Version) patchString() string { - if v.patch > v.minor { - return v.raw[v.minor+1 : v.patch] - } - return "" -} - -func (v *Version) prereleaseString() string { - if v.prerelease > v.patch { - return v.raw[v.patch+1 : v.prerelease] - } - return "" -} - -func (v *Version) buildString() string { - if v.build > v.prerelease { - return v.raw[v.prerelease+1 : v.build] - } - return "" -} diff --git a/parser_test.go b/parser_test.go index f55936b..69eca1f 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -13,6 +13,38 @@ import ( "github.com/stretchr/testify/require" ) +func (v *Version) majorString() string { + return v.raw[:v.major] +} + +func (v *Version) minorString() string { + if v.minor > v.major { + return v.raw[v.major+1 : v.minor] + } + return "" +} + +func (v *Version) patchString() string { + if v.patch > v.minor { + return v.raw[v.minor+1 : v.patch] + } + return "" +} + +func (v *Version) prereleaseString() string { + if v.prerelease > v.patch { + return v.raw[v.patch+1 : v.prerelease] + } + return "" +} + +func (v *Version) buildString() string { + if v.build > v.prerelease { + return v.raw[v.prerelease+1 : v.build] + } + return "" +} + func TestParser(t *testing.T) { MustParse("").CompareTo(MustParse("0+aaa")) valid := func(in, normalized, expectedDump string) { diff --git a/relaxed_version.go b/relaxed_version.go index 0884ec7..b439134 100644 --- a/relaxed_version.go +++ b/relaxed_version.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -103,3 +103,54 @@ func (v *RelaxedVersion) CompatibleWith(u *RelaxedVersion) bool { } return v.Equal(u) } + +// SortableString returns the version encoded as a string that when compared +// with alphanumeric ordering it respects the original semver ordering: +// +// (v1.SortableString() < v2.SortableString()) == v1.LessThan(v2) +// cmp.Compare[string](v1.SortableString(), v2.SortableString()) == v1.CompareTo(v2) +// +// This may turn out useful when the version is saved in a database or is +// introduced in a system that doesn't support semver ordering. +func (v *RelaxedVersion) SortableString() string { + if v.version != nil { + return v.version.SortableString() + } + return ":" + string(v.customversion) +} + +// IsPrerelease returns true if the version is valid semver and has a pre-release part +// otherwise it returns false. +func (v *RelaxedVersion) IsPrerelease() bool { + if v.version == nil { + return false + } + return v.version.IsPrerelease() +} + +// Prerelease returns the pre-release part of the version if the version is valid semver +// otherwise it returns an empty string. +func (v *RelaxedVersion) Prerelease() string { + if v.version == nil { + return "" + } + return v.version.Prerelease() +} + +// HasBuildMetadata returns true if the version is valid semver and has a build metadata part +// otherwise it returns false. +func (v *RelaxedVersion) HasBuildMetadata() bool { + if v.version == nil { + return false + } + return v.version.HasBuildMetadata() +} + +// BuildMetadata returns the build metadata part of the version if the version is valid semver +// otherwise it returns an empty string. +func (v *RelaxedVersion) BuildMetadata() string { + if v.version == nil { + return "" + } + return v.version.BuildMetadata() +} diff --git a/relaxed_version_test.go b/relaxed_version_test.go index eccc717..dab22f1 100644 --- a/relaxed_version_test.go +++ b/relaxed_version_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -7,6 +7,7 @@ package semver import ( + "cmp" "fmt" "testing" @@ -17,47 +18,93 @@ func TestRelaxedVersionComparator(t *testing.T) { sign := map[int]string{1: ">", 0: "=", -1: "<"} ascending := func(list ...*RelaxedVersion) { for i := range list[0 : len(list)-1] { - a := list[i] - b := list[i+1] - comp := a.CompareTo(b) - fmt.Printf("%s %s %s\n", a, sign[comp], b) - require.Equal(t, comp, -1) - require.True(t, a.LessThan(b)) - require.True(t, a.LessThanOrEqual(b)) - require.False(t, a.Equal(b)) - require.False(t, a.GreaterThanOrEqual(b)) - require.False(t, a.GreaterThan(b)) - - comp = b.CompareTo(a) - fmt.Printf("%s %s %s\n", b, sign[comp], a) - require.Equal(t, comp, 1) - require.False(t, b.LessThan(a)) - require.False(t, b.LessThanOrEqual(a)) - require.False(t, b.Equal(a)) - require.True(t, b.GreaterThanOrEqual(a)) - require.True(t, b.GreaterThan(a)) - } - } - equal := func(list ...*RelaxedVersion) { - for _, a := range list { - for _, b := range list { + { + a := list[i] + b := list[i+1] comp := a.CompareTo(b) fmt.Printf("%s %s %s\n", a, sign[comp], b) - require.Equal(t, comp, 0) - require.False(t, a.LessThan(b)) + require.Equal(t, comp, -1) + require.True(t, a.LessThan(b)) require.True(t, a.LessThanOrEqual(b)) - require.True(t, a.Equal(b)) - require.True(t, a.GreaterThanOrEqual(b)) + require.False(t, a.Equal(b)) + require.False(t, a.GreaterThanOrEqual(b)) require.False(t, a.GreaterThan(b)) comp = b.CompareTo(a) fmt.Printf("%s %s %s\n", b, sign[comp], a) - require.Equal(t, comp, 0) + require.Equal(t, comp, 1) require.False(t, b.LessThan(a)) - require.True(t, b.LessThanOrEqual(a)) - require.True(t, b.Equal(a)) + require.False(t, b.LessThanOrEqual(a)) + require.False(t, b.Equal(a)) require.True(t, b.GreaterThanOrEqual(a)) - require.False(t, b.GreaterThan(a)) + require.True(t, b.GreaterThan(a)) + } + { + a := list[i].SortableString() + b := list[i+1].SortableString() + comp := cmp.Compare(a, b) + fmt.Printf("%s %s %s\n", a, sign[comp], b) + require.Equal(t, comp, -1) + require.True(t, a < b) + require.True(t, a <= b) + require.False(t, a == b) + require.False(t, a >= b) + require.False(t, a > b) + + comp = cmp.Compare(b, a) + fmt.Printf("%s %s %s\n", b, sign[comp], a) + require.Equal(t, comp, 1) + require.False(t, b < a) + require.False(t, b <= a) + require.False(t, b == a) + require.True(t, b >= a) + require.True(t, b > a) + } + } + } + equal := func(list ...*RelaxedVersion) { + for _, a := range list { + for _, b := range list { + { + comp := a.CompareTo(b) + fmt.Printf("%s %s %s\n", a, sign[comp], b) + require.Equal(t, comp, 0) + require.False(t, a.LessThan(b)) + require.True(t, a.LessThanOrEqual(b)) + require.True(t, a.Equal(b)) + require.True(t, a.GreaterThanOrEqual(b)) + require.False(t, a.GreaterThan(b)) + + comp = b.CompareTo(a) + fmt.Printf("%s %s %s\n", b, sign[comp], a) + require.Equal(t, comp, 0) + require.False(t, b.LessThan(a)) + require.True(t, b.LessThanOrEqual(a)) + require.True(t, b.Equal(a)) + require.True(t, b.GreaterThanOrEqual(a)) + require.False(t, b.GreaterThan(a)) + } + { + a := a.SortableString() + b := b.SortableString() + comp := cmp.Compare(a, b) + fmt.Printf("%s %s %s\n", a, sign[comp], b) + require.Equal(t, comp, 0) + require.False(t, a < b) + require.True(t, a <= b) + require.True(t, a == b) + require.True(t, a >= b) + require.False(t, a > b) + + comp = cmp.Compare(b, a) + fmt.Printf("%s %s %s\n", b, sign[comp], a) + require.Equal(t, comp, 0) + require.False(t, b < a) + require.True(t, b <= a) + require.True(t, b == a) + require.True(t, b >= a) + require.False(t, b > a) + } } } } diff --git a/resolver.go b/resolver.go index 4344075..439e32d 100644 --- a/resolver.go +++ b/resolver.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/resolver_test.go b/resolver_test.go index e59ef36..778f55c 100644 --- a/resolver_test.go +++ b/resolver_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/sql.go b/sql.go new file mode 100644 index 0000000..bd9343e --- /dev/null +++ b/sql.go @@ -0,0 +1,52 @@ +// +// Copyright 2018-2025 Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +package semver + +import ( + "database/sql/driver" + "fmt" +) + +// Scan implements the sql.Scanner interface +func (v *Version) Scan(value interface{}) error { + raw, ok := value.(string) + if !ok { + return fmt.Errorf("incompatible type %T for Version", value) + } + + v.raw = raw + v.bytes = []byte(v.raw) + if err := parse(v); err != nil { + return err + } + return nil +} + +// Value implements the driver.Valuer interface +func (v *Version) Value() (driver.Value, error) { + return v.raw, nil +} + +// Scan implements the sql.Scanner interface +func (v *RelaxedVersion) Scan(value interface{}) error { + raw, ok := value.(string) + if !ok { + return fmt.Errorf("incompatible type %T for Version", value) + } + + res := ParseRelaxed(raw) + *v = *res + return nil +} + +// Value implements the driver.Valuer interface +func (v *RelaxedVersion) Value() (driver.Value, error) { + if v.version != nil { + return v.version.raw, nil + } + return string(v.customversion), nil +} diff --git a/sql_test.go b/sql_test.go new file mode 100644 index 0000000..eeeec57 --- /dev/null +++ b/sql_test.go @@ -0,0 +1,64 @@ +// +// Copyright 2018-2025 Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +package semver + +import ( + "database/sql/driver" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSQLDriverInterfaces(t *testing.T) { + + t.Run("Version", func(t *testing.T) { + // Test Version Scan/Value + v := &Version{} + if _, ok := interface{}(v).(driver.Valuer); !ok { + t.Error("Version does not implement driver.Valuer") + } + if _, ok := interface{}(v).(driver.Valuer); !ok { + t.Error("Version does not implement driver.Valuer") + } + require.Error(t, v.Scan(1)) + require.Error(t, v.Scan(nil)) + require.Error(t, v.Scan("123asdf")) + require.NoError(t, v.Scan("1.2.3-rc.1+build.2")) + require.Equal(t, "1.2.3-rc.1+build.2", v.String()) + d, err := v.Value() + require.NoError(t, err) + require.Equal(t, "1.2.3-rc.1+build.2", d) + }) + + t.Run("RelaxedVersion", func(t *testing.T) { + // Test RelaxedVersion Scan/Value + rv := &RelaxedVersion{} + if _, ok := interface{}(rv).(driver.Valuer); !ok { + t.Error("RelaxedVersion does not implement driver.Valuer") + } + if _, ok := interface{}(rv).(driver.Valuer); !ok { + t.Error("RelaxedVersion does not implement driver.Valuer") + } + require.Error(t, rv.Scan(1)) + require.Error(t, rv.Scan(nil)) + require.NoError(t, rv.Scan("4.5.6-rc.1+build.2")) + require.Empty(t, rv.customversion) + require.NotNil(t, rv.version) + require.Equal(t, "4.5.6-rc.1+build.2", rv.String()) + rd, err := rv.Value() + require.NoError(t, err) + require.Equal(t, "4.5.6-rc.1+build.2", rd) + + require.NoError(t, rv.Scan("a1-2.2-3.3")) + require.NotEmpty(t, rv.customversion) + require.Nil(t, rv.version) + require.Equal(t, "a1-2.2-3.3", rv.String()) + rd2, err := rv.Value() + require.NoError(t, err) + require.Equal(t, "a1-2.2-3.3", rd2) + }) +} diff --git a/testdata/fuzz/FuzzComparators/175b79ab7e360ad6 b/testdata/fuzz/FuzzComparators/175b79ab7e360ad6 new file mode 100644 index 0000000..54e1196 --- /dev/null +++ b/testdata/fuzz/FuzzComparators/175b79ab7e360ad6 @@ -0,0 +1,3 @@ +go test fuzz v1 +string("0.0.2-rc-") +string("0.0.2-rc.0") diff --git a/testdata/fuzz/FuzzComparators/9b49ee68467ea2f3 b/testdata/fuzz/FuzzComparators/9b49ee68467ea2f3 new file mode 100644 index 0000000..458f3d2 --- /dev/null +++ b/testdata/fuzz/FuzzComparators/9b49ee68467ea2f3 @@ -0,0 +1,3 @@ +go test fuzz v1 +string("1-10") +string("1.0.0") diff --git a/testdata/fuzz/FuzzParser/771e938e4458e983 b/testdata/fuzz/FuzzParser/771e938e4458e983 new file mode 100644 index 0000000..ee3f339 --- /dev/null +++ b/testdata/fuzz/FuzzParser/771e938e4458e983 @@ -0,0 +1,2 @@ +go test fuzz v1 +string("0") diff --git a/version.go b/version.go index b4ee5c6..48b6f79 100644 --- a/version.go +++ b/version.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -69,6 +69,7 @@ func (v *Version) Normalize() { v.prerelease += 2 v.build += 2 } + v.bytes = []byte(v.raw) } func compareNumber(a, b []byte) int { @@ -133,9 +134,9 @@ func (v *Version) CompareTo(u *Version) int { return -1 } } else if vMajor == 0 && u.bytes[uIdx] == '0' { - return 0 + // continue } else if uMajor == 0 && v.bytes[vIdx] == '0' { - return 0 + // continue } else if vMajor > uMajor { return 1 } else { @@ -162,9 +163,9 @@ func (v *Version) CompareTo(u *Version) int { return -1 } } else if vMinor == vMajor && u.bytes[uIdx] == '0' { - return 0 + // continue } else if uMinor == uMajor && v.bytes[vIdx] == '0' { - return 0 + // continue } else if la > lb { return 1 } else { @@ -191,9 +192,9 @@ func (v *Version) CompareTo(u *Version) int { return -1 } } else if vPatch == vMinor && u.bytes[uIdx] == '0' { - return 0 + // continue } else if uPatch == uMinor && v.bytes[vIdx] == '0' { - return 0 + // continue } else if la > lb { return 1 } else { @@ -416,3 +417,106 @@ func (v *Version) CompatibleWith(u *Version) bool { } return compareNumber(vPatch, uPatch) == 0 } + +// SortableString returns the version encoded as a string that when compared +// with alphanumeric ordering it respects the original semver ordering: +// +// (v1.SortableString() < v2.SortableString()) == v1.LessThan(v2) +// cmp.Compare[string](v1.SortableString(), v2.SortableString()) == v1.CompareTo(v2) +// +// This may turn out useful when the version is saved in a database or is +// introduced in a system that doesn't support semver ordering. +func (v *Version) SortableString() string { + // Encode a number in a string that when compared as string it respects + // the original numeric order. + // To allow longer numbers to be compared correctly, a prefix of ":"s + // with the length of the number is added minus 1. + // For example: 123 -> "::123" + // 45 -> ":45" + // The number written as string compare as ("123" < "99") but the encoded + // version keeps the original integer ordering ("::123" > ":99"). + encodeNumber := func(in []byte) string { + if len(in) == 0 { + return "0" + } + p := "" + for range in { + p += ":" + } + return p[:len(p)-1] + string(in) + } + + var vMajor, vMinor, vPatch []byte + vMajor = v.bytes[:v.major] + if v.minor > v.major { + vMinor = v.bytes[v.major+1 : v.minor] + } + if v.patch > v.minor { + vPatch = v.bytes[v.minor+1 : v.patch] + } + + res := ";" + encodeNumber(vMajor) + "." + encodeNumber(vMinor) + "." + encodeNumber(vPatch) + // If there is no pre-release, add a ";" to the end, otherwise add a "-" followed by the pre-release. + // This ensure the correct ordering of the pre-release versions (that are always lower than the normal versions). + if v.prerelease == v.patch { + return res + ";" + } + res += "-" + + isAlpha := false + add := func(in []byte) { + // if the pre-release piece is alphanumeric, add a ";" before the piece + // otherwise add an ":" before the piece. This ensure the correct ordering + // of the pre-release piece (numeric are lower than alphanumeric). + if isAlpha { + res += ";" + string(in) + } else { + res += ":" + encodeNumber(in) + } + isAlpha = false + } + prerelease := v.bytes[v.patch+1 : v.prerelease] + start := 0 + for curr, c := range prerelease { + if c == '.' { + add(prerelease[start:curr]) + // separate the pre-release pieces with a "," to ensure the correct ordering + // of the pre-release pieces (the separator must be lower than any other allowed + // character [a-zA-Z0-9-]). + res += "," + start = curr + 1 + continue + } + if !isNumeric(c) { + isAlpha = true + } + } + add(prerelease[start:]) + return res +} + +// IsPrerelease returns true if the version has a pre-release part +func (v *Version) IsPrerelease() bool { + return v.prerelease != v.patch +} + +// Prerelease returns the pre-release part of the version +func (v *Version) Prerelease() string { + if !v.IsPrerelease() { + return "" + } + return v.raw[v.patch+1 : v.prerelease] +} + +// HasBuildMetadata returns true if the version has a build metadata part +func (v *Version) HasBuildMetadata() bool { + return v.build != v.prerelease +} + +// BuildMetadata returns the build metadata part of the version +func (v *Version) BuildMetadata() string { + if !v.HasBuildMetadata() { + return "" + } + return v.raw[v.prerelease+1 : v.build] +} diff --git a/version_test.go b/version_test.go index 6c54e3a..cd0ce62 100644 --- a/version_test.go +++ b/version_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -7,6 +7,7 @@ package semver import ( + "cmp" "fmt" "testing" @@ -54,6 +55,41 @@ func ascending(t *testing.T, allowEqual bool, list ...string) { require.True(t, b.GreaterThan(a)) } } + + for i := range list[0 : len(list)-1] { + a := MustParse(list[i]).SortableString() + b := MustParse(list[i+1]).SortableString() + comp := cmp.Compare(a, b) + if allowEqual { + fmt.Printf("%s %s= %s\n", list[i], sign[comp], list[i+1]) + require.LessOrEqual(t, comp, 0) + require.True(t, a <= b) + require.False(t, a > b) + } else { + fmt.Printf("%s %s %s\n", list[i], sign[comp], list[i+1]) + require.Equal(t, comp, -1, "cmp(%s, %s) (%s, %s) must return '<', but returned '%s'", list[i], list[i+1], a, b, sign[comp]) + require.True(t, a < b) + require.True(t, a <= b) + require.False(t, a == b) + require.False(t, a >= b) + require.False(t, a > b) + } + + comp = cmp.Compare(b, a) + fmt.Printf("%s %s %s\n", b, sign[comp], a) + if allowEqual { + require.GreaterOrEqual(t, comp, 0, "cmp(%s, %s) must return '>=', but returned '%s'", b, a, sign[comp]) + require.False(t, b < a) + require.True(t, b >= a) + } else { + require.Equal(t, comp, 1) + require.False(t, b < a) + require.False(t, b <= a) + require.False(t, b == a) + require.True(t, b >= a) + require.True(t, b > a) + } + } } func TestVersionComparator(t *testing.T) { @@ -80,7 +116,19 @@ func TestVersionComparator(t *testing.T) { } } } + ascending(t, false, "", "0.0.1") + ascending(t, false, "", "0.1") + ascending(t, false, "", "1") + ascending(t, false, "0", "0.0.1") + ascending(t, false, "0", "0.1") + ascending(t, false, "0", "1") + ascending(t, false, "0.0", "0.0.1") + ascending(t, false, "0.0", "0.1") + ascending(t, false, "0.0", "1") ascending(t, false, + "", + "0.0.1", + "0.1", "1.0.0-2", "1.0.0-11", "1.0.0-11a", @@ -112,6 +160,10 @@ func TestVersionComparator(t *testing.T) { "17.3.0-atmel3a.16.1-arduino7", "17.3.0-atmel3a.16.12-arduino7", "17.3.0-atmel3a.16.2-arduino7", + "34.0.0", + "51.0.0", + "99.0.0", + "123.0.0", ) equal( MustParse(""), @@ -253,3 +305,59 @@ func TestCompareNumbers(t *testing.T) { testGreater("10", "1") testGreater("10", "2") } + +func TestVersionGetters(t *testing.T) { + type test struct { + version string + prerelease string + build string + } + tests := []test{ + {"", "", ""}, + {"0", "", ""}, + {"1", "", ""}, + {"0.1", "", ""}, + {"1.1", "", ""}, + {"0.2.3", "", ""}, + {"1.2.3-aaa", "aaa", ""}, + {"0.2-aaa", "aaa", ""}, + {"1-aaa", "aaa", ""}, + {"0.2.3+bbb", "", "bbb"}, + {"1.3+bbb", "", "bbb"}, + {"0+bbb", "", "bbb"}, + {"1.2.3-aaa+bbb", "aaa", "bbb"}, + {"0.2-aaa+bbb", "aaa", "bbb"}, + {"1-aaa+bbb", "aaa", "bbb"}, + {"0.2.3-aaa.4.5.6+bbb.7.8.9", "aaa.4.5.6", "bbb.7.8.9"}, + } + for _, tt := range tests { + v := MustParse(tt.version) + require.Equal(t, tt.version, v.String()) + require.Equal(t, tt.prerelease != "", v.IsPrerelease()) + require.Equal(t, tt.prerelease, v.Prerelease()) + require.Equal(t, tt.build != "", v.HasBuildMetadata()) + require.Equal(t, tt.build, v.BuildMetadata()) + r := ParseRelaxed(tt.version) + require.Equal(t, tt.version, r.String()) + require.Equal(t, tt.prerelease != "", r.IsPrerelease()) + require.Equal(t, tt.prerelease, r.Prerelease()) + require.Equal(t, tt.build != "", r.HasBuildMetadata()) + require.Equal(t, tt.build, r.BuildMetadata()) + } + relaxedTests := []test{ + {"asd", "", ""}, + {"123.123.123.123-123", "", ""}, + {"1.2.3-a@very@fancy@version", "", ""}, + } + for _, tt := range relaxedTests { + v, err := Parse(tt.version) + require.Error(t, err, "should not parse %s", tt.version) + require.Nil(t, v) + r := ParseRelaxed(tt.version) + require.Equal(t, tt.version, r.String()) + require.Equal(t, tt.prerelease != "", r.IsPrerelease()) + require.Equal(t, tt.prerelease, r.Prerelease()) + require.Equal(t, tt.build != "", r.HasBuildMetadata()) + require.Equal(t, tt.build, r.BuildMetadata()) + } +} diff --git a/yaml.go b/yaml.go index fc8e942..43a2df6 100644 --- a/yaml.go +++ b/yaml.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/yaml_test.go b/yaml_test.go index 255c617..ada4b94 100644 --- a/yaml_test.go +++ b/yaml_test.go @@ -1,5 +1,5 @@ // -// Copyright 2018-2023 Cristian Maglie. All rights reserved. +// Copyright 2018-2025 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // @@ -82,7 +82,7 @@ func BenchmarkYAMLDecoding(b *testing.B) { data, _ := yaml.Marshal(v) var u Version for i := 0; i < b.N; i++ { - yaml.Unmarshal(data, &u) + _ = yaml.Unmarshal(data, &u) } } @@ -92,6 +92,6 @@ func BenchmarkYAMLDecodingRelaxed(b *testing.B) { data, _ := yaml.Marshal(v) var u RelaxedVersion for i := 0; i < b.N; i++ { - yaml.Unmarshal(data, &u) + _ = yaml.Unmarshal(data, &u) } }