Merge pull request #1541 from nspcc-dev/core/fix_nef_getversion

smartcontract: fix nef.GetVersion
This commit is contained in:
Roman Khimov 2020-11-12 17:56:12 +03:00 committed by GitHub
commit 543871fb2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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: // GetVersion returns Version from the given string. It accepts the following formats:
// `major.minor.build-[...]` // `major[-...].minor[-...].build[-...]` and `major[-...].minor[-...].build[-...].revision[-...]`
// `major.minor.build.revision-[...]`
// where `major`, `minor`, `build` and `revision` are 32-bit integers with base=10 // where `major`, `minor`, `build` and `revision` are 32-bit integers with base=10
func GetVersion(version string) (Version, error) { func GetVersion(version string) (Version, error) {
var ( var (
result Version result Version
err error
) )
versions := strings.SplitN(version, ".", 4) versions := strings.SplitN(version, ".", 4)
if len(versions) < 3 { if len(versions) < 3 {
return result, errors.New("invalid version format") return result, errors.New("invalid version format")
} }
major, err := strconv.ParseInt(versions[0], 10, 32) result.Major, err = parseDashedVersion(versions[0])
if err != nil { if err != nil {
return result, fmt.Errorf("failed to parse major version: %w", err) return result, fmt.Errorf("failed to parse major version: %w", err)
} }
result.Major = int32(major) result.Minor, err = parseDashedVersion(versions[1])
minor, err := strconv.ParseInt(versions[1], 10, 32)
if err != nil { if err != nil {
return result, fmt.Errorf("failed to parse minor version: %w", err) return result, fmt.Errorf("failed to parse minor version: %w", err)
} }
result.Minor = int32(minor) result.Build, err = parseDashedVersion(versions[2])
b := versions[2]
if len(versions) == 3 {
b = strings.SplitN(b, "-", 2)[0]
}
build, err := strconv.ParseInt(b, 10, 32)
if err != nil { if err != nil {
return result, fmt.Errorf("failed to parse build version: %w", err) return result, fmt.Errorf("failed to parse build version: %w", err)
} }
result.Build = int32(build)
if len(versions) == 4 { if len(versions) == 4 {
r := strings.SplitN(versions[3], "-", 2)[0] result.Revision, err = parseDashedVersion(versions[3])
revision, err := strconv.ParseInt(r, 10, 32)
if err != nil { if err != nil {
return result, fmt.Errorf("failed to parse revision version: %w", err) return result, fmt.Errorf("failed to parse revision version: %w", err)
} }
result.Revision = int32(revision)
} }
return result, nil 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. // EncodeBinary implements io.Serializable interface.
func (v *Version) EncodeBinary(w *io.BinWriter) { func (v *Version) EncodeBinary(w *io.BinWriter) {
w.WriteU32LE(uint32(v.Major)) w.WriteU32LE(uint32(v.Major))

View file

@ -93,48 +93,77 @@ func TestBytesFromBytes(t *testing.T) {
} }
func TestGetVersion(t *testing.T) { func TestGetVersion(t *testing.T) {
_, err := GetVersion("qwerty") testCases := map[string]struct {
require.Error(t, err) input string
fails bool
_, err = GetVersion("1.pre") expected Version
require.Error(t, err) }{
"major only": {
_, err = GetVersion("1.1.pre") input: "1",
require.Error(t, err) fails: true,
},
_, err = GetVersion("1.1.1.pre") "major and minor only": {
require.Error(t, err) input: "1.1",
fails: true,
actual, err := GetVersion("1.1.1-pre") },
require.NoError(t, err) "major, minor and revision only": {
expected := Version{ input: "1.1.1",
Major: 1, expected: Version{
Minor: 1, Major: 1,
Build: 1, Minor: 1,
Revision: 0, 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) for name, test := range testCases {
t.Run(name, func(t *testing.T) {
actual, err = GetVersion("0.90.0-pre") actual, err := GetVersion(test.input)
require.NoError(t, err) if test.fails {
expected = Version{ require.NotNil(t, err)
Major: 0, } else {
Minor: 90, require.Equal(t, test.expected, actual)
Build: 0, }
Revision: 0, })
} }
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)
} }