smartcontract: fix nef.GetVersion

It should be able to parse versions like `1.1.1-rc.1`.

Close #1540.
This commit is contained in:
Anna Shaleva 2020-11-12 17:08:54 +03:00
parent e664657c8c
commit 9c3d8cd398
2 changed files with 88 additions and 60 deletions

View file

@ -82,52 +82,51 @@ func NewFile(script []byte) (File, error) {
}
// GetVersion returns Version from the given string. It accepts the following formats:
// `major.minor.build-[...]`
// `major.minor.build.revision-[...]`
// `major[-...].minor[-...].build[-...]` and `major[-...].minor[-...].build[-...].revision[-...]`
// where `major`, `minor`, `build` and `revision` are 32-bit integers with base=10
func GetVersion(version string) (Version, error) {
var (
result Version
err error
)
versions := strings.SplitN(version, ".", 4)
if len(versions) < 3 {
return result, errors.New("invalid version format")
}
major, err := strconv.ParseInt(versions[0], 10, 32)
result.Major, err = parseDashedVersion(versions[0])
if err != nil {
return result, fmt.Errorf("failed to parse major version: %w", err)
}
result.Major = int32(major)
minor, err := strconv.ParseInt(versions[1], 10, 32)
result.Minor, err = parseDashedVersion(versions[1])
if err != nil {
return result, fmt.Errorf("failed to parse minor version: %w", err)
}
result.Minor = int32(minor)
b := versions[2]
if len(versions) == 3 {
b = strings.SplitN(b, "-", 2)[0]
}
build, err := strconv.ParseInt(b, 10, 32)
result.Build, err = parseDashedVersion(versions[2])
if err != nil {
return result, fmt.Errorf("failed to parse build version: %w", err)
}
result.Build = int32(build)
if len(versions) == 4 {
r := strings.SplitN(versions[3], "-", 2)[0]
revision, err := strconv.ParseInt(r, 10, 32)
result.Revision, err = parseDashedVersion(versions[3])
if err != nil {
return result, fmt.Errorf("failed to parse revision version: %w", err)
}
result.Revision = int32(revision)
}
return result, nil
}
// parseDashedVersion extracts int from string of the format `int[-...]` where `int` is
// a 32-bit integer with base=10.
func parseDashedVersion(version string) (int32, error) {
version = strings.SplitN(version, "-", 2)[0]
result, err := strconv.ParseInt(version, 10, 32)
if err != nil {
return 0, err
}
return int32(result), nil
}
// EncodeBinary implements io.Serializable interface.
func (v *Version) EncodeBinary(w *io.BinWriter) {
w.WriteU32LE(uint32(v.Major))

View file

@ -93,48 +93,77 @@ func TestBytesFromBytes(t *testing.T) {
}
func TestGetVersion(t *testing.T) {
_, err := GetVersion("qwerty")
require.Error(t, err)
_, err = GetVersion("1.pre")
require.Error(t, err)
_, err = GetVersion("1.1.pre")
require.Error(t, err)
_, err = GetVersion("1.1.1.pre")
require.Error(t, err)
actual, err := GetVersion("1.1.1-pre")
require.NoError(t, err)
expected := Version{
Major: 1,
Minor: 1,
Build: 1,
Revision: 0,
testCases := map[string]struct {
input string
fails bool
expected Version
}{
"major only": {
input: "1",
fails: true,
},
"major and minor only": {
input: "1.1",
fails: true,
},
"major, minor and revision only": {
input: "1.1.1",
expected: Version{
Major: 1,
Minor: 1,
Build: 1,
Revision: 0,
},
},
"full version": {
input: "1.1.1.1",
expected: Version{
Major: 1,
Minor: 1,
Build: 1,
Revision: 1,
},
},
"dashed, without revision": {
input: "1-pre.2-pre.3-pre",
expected: Version{
Major: 1,
Minor: 2,
Build: 3,
Revision: 0,
},
},
"dashed, full version": {
input: "1-pre.2-pre.3-pre.4-pre",
expected: Version{
Major: 1,
Minor: 2,
Build: 3,
Revision: 4,
},
},
"dashed build": {
input: "1.2.3-pre.4",
expected: Version{
Major: 1,
Minor: 2,
Build: 3,
Revision: 4,
},
},
"extra versions": {
input: "1.2.3.4.5",
fails: true,
},
}
require.Equal(t, expected, actual)
actual, err = GetVersion("0.90.0-pre")
require.NoError(t, err)
expected = Version{
Major: 0,
Minor: 90,
Build: 0,
Revision: 0,
for name, test := range testCases {
t.Run(name, func(t *testing.T) {
actual, err := GetVersion(test.input)
if test.fails {
require.NotNil(t, err)
} else {
require.Equal(t, test.expected, actual)
}
})
}
require.Equal(t, expected, actual)
actual, err = GetVersion("1.1.1.1-pre")
require.NoError(t, err)
expected = Version{
Major: 1,
Minor: 1,
Build: 1,
Revision: 1,
}
require.Equal(t, expected, actual)
_, err = GetVersion("1.1.1.1.1")
require.Error(t, err)
}