mirror of
https://github.com/clearml/go-nvlib
synced 2025-06-16 19:29:16 +00:00
Merge branch 'add-assert-mig-profile-format' into 'main'
Add function for AssertValidMigProfileFormat See merge request nvidia/cloud-native/go-nvlib!38
This commit is contained in:
commit
bdc2553e78
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
// Interface provides the API to the 'device' package
|
// Interface provides the API to the 'device' package
|
||||||
type Interface interface {
|
type Interface interface {
|
||||||
|
AssertValidMigProfileFormat(profile string) error
|
||||||
GetDevices() ([]Device, error)
|
GetDevices() ([]Device, error)
|
||||||
GetMigDevices() ([]MigDevice, error)
|
GetMigDevices() ([]MigDevice, error)
|
||||||
GetMigProfiles() ([]MigProfile, error)
|
GetMigProfiles() ([]MigProfile, error)
|
||||||
|
@ -119,6 +119,12 @@ func (d *devicelib) NewMigProfile(giProfileID, ciProfileID, ciEngProfileID int,
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssertValidMigProfileFormat checks if the string is in the proper format to represent a MIG profile
|
||||||
|
func (d *devicelib) AssertValidMigProfileFormat(profile string) error {
|
||||||
|
_, _, _, _, err := parseMigProfile(profile)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// ParseMigProfile converts a string representation of a MigProfile into an object
|
// ParseMigProfile converts a string representation of a MigProfile into an object
|
||||||
func (d *devicelib) ParseMigProfile(profile string) (MigProfile, error) {
|
func (d *devicelib) ParseMigProfile(profile string) (MigProfile, error) {
|
||||||
profiles, err := d.GetMigProfiles()
|
profiles, err := d.GetMigProfiles()
|
||||||
@ -181,16 +187,7 @@ func (p *MigProfileInfo) Equals(other MigProfile) bool {
|
|||||||
|
|
||||||
// Matches checks if a MigProfile matches the string passed in
|
// Matches checks if a MigProfile matches the string passed in
|
||||||
func (p *MigProfileInfo) Matches(profile string) bool {
|
func (p *MigProfileInfo) Matches(profile string) bool {
|
||||||
// If we are handed the empty string, there is nothing to check
|
c, g, gb, attrs, err := parseMigProfile(profile)
|
||||||
if profile == "" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Split by + to separate out attributes
|
|
||||||
split := strings.SplitN(profile, "+", 2)
|
|
||||||
|
|
||||||
// Check to make sure the c, g, and gb values match
|
|
||||||
c, g, gb, err := parseMigProfileFields(split[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -203,17 +200,6 @@ func (p *MigProfileInfo) Matches(profile string) bool {
|
|||||||
if gb != p.GB {
|
if gb != p.GB {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have no attributes we are done
|
|
||||||
if len(split) == 1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have the same set of attributes
|
|
||||||
attrs, err := parseMigProfileAttributes(split[1])
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(attrs) != len(p.Attributes) {
|
if len(attrs) != len(p.Attributes) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -224,10 +210,38 @@ func (p *MigProfileInfo) Matches(profile string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseMigProfile(profile string) (int, int, int, []string, error) {
|
||||||
|
// If we are handed the empty string, we cannot parse it
|
||||||
|
if profile == "" {
|
||||||
|
return -1, -1, -1, nil, fmt.Errorf("profile is the empty string")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split by + to separate out attributes
|
||||||
|
split := strings.SplitN(profile, "+", 2)
|
||||||
|
|
||||||
|
// Check to make sure the c, g, and gb values match
|
||||||
|
c, g, gb, err := parseMigProfileFields(split[0])
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, -1, nil, fmt.Errorf("cannot parse fields of '%v': %v", profile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no attributes we are done
|
||||||
|
if len(split) == 1 {
|
||||||
|
return c, g, gb, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have the same set of attributes
|
||||||
|
attrs, err := parseMigProfileAttributes(split[1])
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, -1, nil, fmt.Errorf("cannot parse attributes of '%v': %v", profile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, g, gb, attrs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseMigProfileField(s string, field string) (int, error) {
|
func parseMigProfileField(s string, field string) (int, error) {
|
||||||
if strings.TrimSpace(s) != s {
|
if strings.TrimSpace(s) != s {
|
||||||
return -1, fmt.Errorf("leading or trailing spaces on '%%d%s'", field)
|
return -1, fmt.Errorf("leading or trailing spaces on '%%d%s'", field)
|
||||||
|
@ -28,232 +28,266 @@ func TestParseMigProfile(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
description string
|
description string
|
||||||
device string
|
device string
|
||||||
valid bool
|
validFormat bool
|
||||||
|
validDevice bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"Empty device type",
|
"Empty device type",
|
||||||
"",
|
"",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Valid 1g.5gb",
|
"Valid 1g.5gb",
|
||||||
"1g.5gb",
|
"1g.5gb",
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Valid 1c.1g.5gb",
|
"Valid 1c.1g.5gb",
|
||||||
"1c.1g.5gb",
|
"1c.1g.5gb",
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Valid 1g.5gb+me",
|
"Valid 1g.5gb+me",
|
||||||
"1g.5gb+me",
|
"1g.5gb+me",
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Valid 1c.1g.5gb+me",
|
"Valid 1c.1g.5gb+me",
|
||||||
"1c.1g.5gb+me",
|
"1c.1g.5gb+me",
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 0g.0gb",
|
"Invalid 0g.0gb",
|
||||||
"0g.0gb",
|
"0g.0gb",
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 0c.0g.0gb",
|
"Invalid 0c.0g.0gb",
|
||||||
"0c.0g.0gb",
|
"0c.0g.0gb",
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 10000g.500000gb",
|
"Invalid 10000g.500000gb",
|
||||||
"10000g.500000gb",
|
"10000g.500000gb",
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 10000c.10000g.500000gb",
|
"Invalid 10000c.10000g.500000gb",
|
||||||
"10000c.10000g.500000gb",
|
"10000c.10000g.500000gb",
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid ' 1c.1g.5gb'",
|
"Invalid ' 1c.1g.5gb'",
|
||||||
" 1c.1g.5gb",
|
" 1c.1g.5gb",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid '1 c.1g.5gb'",
|
|
||||||
"1 c.1g.5gb",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid '1 c.1g.5gb'",
|
"Invalid '1 c.1g.5gb'",
|
||||||
"1 c.1g.5gb",
|
"1 c.1g.5gb",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid '1c. 1g.5gb'",
|
|
||||||
"1c. 1g.5gb",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid '1c .1g.5gb'",
|
"Invalid '1c .1g.5gb'",
|
||||||
"1c .1g.5gb",
|
"1c .1g.5gb",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid '1c.1g .5gb'",
|
|
||||||
"1c.1g .5gb",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid '1c. 1g.5gb'",
|
"Invalid '1c. 1g.5gb'",
|
||||||
"1c. 1g.5gb",
|
"1c. 1g.5gb",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid '1c.1g.5 gb'",
|
|
||||||
"1c.1g.5 gb",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid '1c.1 g.5gb'",
|
"Invalid '1c.1 g.5gb'",
|
||||||
"1c.1 g.5gb",
|
"1c.1 g.5gb",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid '1c.1g.5gb '",
|
|
||||||
"1c.1g.5gb ",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid '1c.1g .5gb'",
|
"Invalid '1c.1g .5gb'",
|
||||||
"1c.1g .5gb",
|
"1c.1g .5gb",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid '1c.1g. 5gb'",
|
||||||
|
"1c.1g. 5gb",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid '1c.1g.5 gb'",
|
||||||
|
"1c.1g.5 gb",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid '1c.1g.5g b'",
|
||||||
|
"1c.1g.5g b",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid '1c.1g.5gb '",
|
||||||
|
"1c.1g.5gb ",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid '1c . 1g . 5gb'",
|
||||||
|
"1c . 1g . 5gb",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1c.f1g.5gb",
|
"Invalid 1c.f1g.5gb",
|
||||||
"1c.f1g.5gb",
|
"1c.f1g.5gb",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1r.1g.5gb",
|
"Invalid 1r.1g.5gb",
|
||||||
"1r.1g.5gb",
|
"1r.1g.5gb",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gbk",
|
"Invalid 1g.5gbk",
|
||||||
"1g.5gbk",
|
"1g.5gbk",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5",
|
"Invalid 1g.5",
|
||||||
"1g.5",
|
"1g.5",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid g.5gb",
|
|
||||||
"1g.5",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid g.5gb",
|
"Invalid g.5gb",
|
||||||
"g.5gb",
|
"g.5gb",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.gb",
|
"Invalid 1g.gb",
|
||||||
"1g.gb",
|
"1g.gb",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+me,me",
|
"Invalid 1g.5gb+me,me",
|
||||||
"1g.5gb+me,me",
|
"1g.5gb+me,me",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+me,you,them",
|
"Invalid 1g.5gb+me,you,them",
|
||||||
"1g.5gb+me,you,them",
|
"1g.5gb+me,you,them",
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1c.1g.5gb+me,you,them",
|
"Invalid 1c.1g.5gb+me,you,them",
|
||||||
"1c.1g.5gb+me,you,them",
|
"1c.1g.5gb+me,you,them",
|
||||||
|
true,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+",
|
"Invalid 1g.5gb+",
|
||||||
"1g.5gb+",
|
"1g.5gb+",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid 1g.5gb +",
|
|
||||||
"1g.5gb+",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb +",
|
"Invalid 1g.5gb +",
|
||||||
"1g.5gb +",
|
"1g.5gb +",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid 1g.5gb+ ",
|
||||||
|
"1g.5gb+ ",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+ ,",
|
"Invalid 1g.5gb+ ,",
|
||||||
"1g.5gb+",
|
"1g.5gb+ ,",
|
||||||
false,
|
false,
|
||||||
},
|
|
||||||
{
|
|
||||||
"Invalid 1g.5gb+,",
|
|
||||||
"1g.5gb+",
|
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+,,",
|
"Invalid 1g.5gb+,,",
|
||||||
"1g.5gb+",
|
"1g.5gb+,,",
|
||||||
|
false,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+me,",
|
"Invalid 1g.5gb+me,",
|
||||||
"1g.5gb+",
|
"1g.5gb+me,",
|
||||||
|
false,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+me,,",
|
"Invalid 1g.5gb+me,,",
|
||||||
"1g.5gb+",
|
"1g.5gb+me,,",
|
||||||
|
false,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+me, ",
|
"Invalid 1g.5gb+me, ",
|
||||||
"1g.5gb+",
|
"1g.5gb+me, ",
|
||||||
|
false,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb+2me",
|
"Invalid 1g.5gb+2me",
|
||||||
"1g.5gb+2me",
|
"1g.5gb+2me",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Inavlid 1g.5gb*me",
|
"Inavlid 1g.5gb*me",
|
||||||
"1g.5gb*me",
|
"1g.5gb*me",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1c.1g.5gb*me",
|
"Invalid 1c.1g.5gb*me",
|
||||||
"1c.1g.5gb*me",
|
"1c.1g.5gb*me",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1g.5gb*me,you,them",
|
"Invalid 1g.5gb*me,you,them",
|
||||||
"1g.5gb*me,you,them",
|
"1g.5gb*me,you,them",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid 1c.1g.5gb*me,you,them",
|
"Invalid 1c.1g.5gb*me,you,them",
|
||||||
"1c.1g.5gb*me,you,them",
|
"1c.1g.5gb*me,you,them",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Invalid bogus",
|
"Invalid bogus",
|
||||||
"bogus",
|
"bogus",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,8 +342,14 @@ func TestParseMigProfile(t *testing.T) {
|
|||||||
d := New(WithNvml(mockNvml), WithVerifySymbols(false))
|
d := New(WithNvml(mockNvml), WithVerifySymbols(false))
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.description, func(t *testing.T) {
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
_, err := d.ParseMigProfile(tc.device)
|
err := d.AssertValidMigProfileFormat(tc.device)
|
||||||
if tc.valid {
|
if tc.validFormat {
|
||||||
|
require.Nil(t, err)
|
||||||
|
} else {
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
_, err = d.ParseMigProfile(tc.device)
|
||||||
|
if tc.validDevice {
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
} else {
|
} else {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
Loading…
Reference in New Issue
Block a user