Skip to content

Commit a24cef3

Browse files
committed
Add new error when int parsing fails
It's hard to reason with errors when `strconv.ParseUint` fails as the returned error is untyped. This change introduces a new error that is returned if the int parsing fails. Signed-off-by: crozzy <joseph.crosland@gmail.com>
1 parent 2f39fdc commit a24cef3

2 files changed

Lines changed: 37 additions & 3 deletions

File tree

version.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ var (
3636

3737
// ErrInvalidPrerelease is returned when the pre-release is an invalid format
3838
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
39+
40+
// ErrSegmentUnparsable is returned if a version segment cannot be parsed as
41+
// an int.
42+
ErrSegmentUnparsable = errors.New("Version segment unparsable")
3943
)
4044

4145
// semVerRegex is the regular expression used to parse a semantic version.
@@ -170,13 +174,13 @@ func NewVersion(v string) (*Version, error) {
170174
var err error
171175
sv.major, err = strconv.ParseUint(m[1], 10, 64)
172176
if err != nil {
173-
return nil, fmt.Errorf("Error parsing version segment: %s", err)
177+
return nil, ErrSegmentUnparsable
174178
}
175179

176180
if m[2] != "" {
177181
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
178182
if err != nil {
179-
return nil, fmt.Errorf("Error parsing version segment: %s", err)
183+
return nil, ErrSegmentUnparsable
180184
}
181185
} else {
182186
sv.minor = 0
@@ -185,7 +189,7 @@ func NewVersion(v string) (*Version, error) {
185189
if m[3] != "" {
186190
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
187191
if err != nil {
188-
return nil, fmt.Errorf("Error parsing version segment: %s", err)
192+
return nil, ErrSegmentUnparsable
189193
}
190194
} else {
191195
sv.patch = 0

version_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package semver
33
import (
44
"database/sql"
55
"encoding/json"
6+
"errors"
67
"fmt"
8+
"strconv"
79
"testing"
810
)
911

@@ -162,6 +164,34 @@ func TestOriginal(t *testing.T) {
162164
}
163165
}
164166

167+
func TestErrors(t *testing.T) {
168+
tests := map[string]error{
169+
"1.3.2023080721291691443750": ErrSegmentUnparsable,
170+
"1.2.3.4.5": ErrInvalidSemVer,
171+
"": ErrInvalidSemVer,
172+
"1.2.0+invalid_metadata": ErrInvalidSemVer,
173+
}
174+
for v, e := range tests {
175+
_, err := NewVersion(v)
176+
if !errors.Is(err, e) {
177+
t.Errorf("Expecting error: %s but got: %s, version %s", e, err, v)
178+
}
179+
}
180+
181+
strictTests := map[string]error{
182+
"1.3.2023080721291691443750": strconv.ErrRange,
183+
"1.2.3.4.5": ErrInvalidCharacters,
184+
"": ErrEmptyString,
185+
"1.2.0+invalid$metadata": ErrInvalidMetadata,
186+
}
187+
for v, e := range strictTests {
188+
_, err := StrictNewVersion(v)
189+
if !errors.Is(err, e) {
190+
t.Errorf("Expecting error: %s but got: %s, version: %s", e, err, v)
191+
}
192+
}
193+
}
194+
165195
func TestParts(t *testing.T) {
166196
v, err := NewVersion("1.2.3-beta.1+build.123")
167197
if err != nil {

0 commit comments

Comments
 (0)