1
0
mirror of https://github.com/clearml/go-nvlib synced 2025-04-28 01:41:47 +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:
Kevin Klues 2023-03-27 14:14:13 +00:00
commit bdc2553e78
3 changed files with 95 additions and 40 deletions

View File

@ -22,6 +22,7 @@ import (
// Interface provides the API to the 'device' package
type Interface interface {
AssertValidMigProfileFormat(profile string) error
GetDevices() ([]Device, error)
GetMigDevices() ([]MigDevice, error)
GetMigProfiles() ([]MigProfile, error)

View File

@ -119,6 +119,12 @@ func (d *devicelib) NewMigProfile(giProfileID, ciProfileID, ciEngProfileID int,
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
func (d *devicelib) ParseMigProfile(profile string) (MigProfile, error) {
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
func (p *MigProfileInfo) Matches(profile string) bool {
// If we are handed the empty string, there is nothing to check
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])
c, g, gb, attrs, err := parseMigProfile(profile)
if err != nil {
return false
}
@ -203,17 +200,6 @@ func (p *MigProfileInfo) Matches(profile string) bool {
if gb != p.GB {
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) {
return false
}
@ -224,10 +210,38 @@ func (p *MigProfileInfo) Matches(profile string) bool {
return false
}
}
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) {
if strings.TrimSpace(s) != s {
return -1, fmt.Errorf("leading or trailing spaces on '%%d%s'", field)

View File

@ -28,232 +28,266 @@ func TestParseMigProfile(t *testing.T) {
testCases := []struct {
description string
device string
valid bool
validFormat bool
validDevice bool
}{
{
"Empty device type",
"",
false,
false,
},
{
"Valid 1g.5gb",
"1g.5gb",
true,
true,
},
{
"Valid 1c.1g.5gb",
"1c.1g.5gb",
true,
true,
},
{
"Valid 1g.5gb+me",
"1g.5gb+me",
true,
true,
},
{
"Valid 1c.1g.5gb+me",
"1c.1g.5gb+me",
true,
true,
},
{
"Invalid 0g.0gb",
"0g.0gb",
true,
false,
},
{
"Invalid 0c.0g.0gb",
"0c.0g.0gb",
true,
false,
},
{
"Invalid 10000g.500000gb",
"10000g.500000gb",
true,
false,
},
{
"Invalid 10000c.10000g.500000gb",
"10000c.10000g.500000gb",
true,
false,
},
{
"Invalid ' 1c.1g.5gb'",
" 1c.1g.5gb",
false,
false,
},
{
"Invalid '1 c.1g.5gb'",
"1 c.1g.5gb",
false,
false,
},
{
"Invalid '1c .1g.5gb'",
"1c .1g.5gb",
false,
false,
},
{
"Invalid '1c. 1g.5gb'",
"1c. 1g.5gb",
false,
false,
},
{
"Invalid '1c.1 g.5gb'",
"1c.1 g.5gb",
false,
false,
},
{
"Invalid '1c.1g .5gb'",
"1c.1g .5gb",
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",
"1c.f1g.5gb",
false,
false,
},
{
"Invalid 1r.1g.5gb",
"1r.1g.5gb",
false,
false,
},
{
"Invalid 1g.5gbk",
"1g.5gbk",
false,
false,
},
{
"Invalid 1g.5",
"1g.5",
false,
},
{
"Invalid g.5gb",
"1g.5",
false,
},
{
"Invalid g.5gb",
"g.5gb",
false,
false,
},
{
"Invalid 1g.gb",
"1g.gb",
false,
false,
},
{
"Invalid 1g.5gb+me,me",
"1g.5gb+me,me",
false,
false,
},
{
"Invalid 1g.5gb+me,you,them",
"1g.5gb+me,you,them",
true,
false,
},
{
"Invalid 1c.1g.5gb+me,you,them",
"1c.1g.5gb+me,you,them",
true,
false,
},
{
"Invalid 1g.5gb+",
"1g.5gb+",
false,
false,
},
{
"Invalid 1g.5gb +",
"1g.5gb+",
"1g.5gb +",
false,
false,
},
{
"Invalid 1g.5gb+ ",
"1g.5gb+",
"1g.5gb+ ",
false,
false,
},
{
"Invalid 1g.5gb+ ,",
"1g.5gb+",
"1g.5gb+ ,",
false,
},
{
"Invalid 1g.5gb+,",
"1g.5gb+",
false,
},
{
"Invalid 1g.5gb+,,",
"1g.5gb+",
"1g.5gb+,,",
false,
false,
},
{
"Invalid 1g.5gb+me,",
"1g.5gb+",
"1g.5gb+me,",
false,
false,
},
{
"Invalid 1g.5gb+me,,",
"1g.5gb+",
"1g.5gb+me,,",
false,
false,
},
{
"Invalid 1g.5gb+me, ",
"1g.5gb+",
"1g.5gb+me, ",
false,
false,
},
{
"Invalid 1g.5gb+2me",
"1g.5gb+2me",
false,
false,
},
{
"Inavlid 1g.5gb*me",
"1g.5gb*me",
false,
false,
},
{
"Invalid 1c.1g.5gb*me",
"1c.1g.5gb*me",
false,
false,
},
{
"Invalid 1g.5gb*me,you,them",
"1g.5gb*me,you,them",
false,
false,
},
{
"Invalid 1c.1g.5gb*me,you,them",
"1c.1g.5gb*me,you,them",
false,
false,
},
{
"Invalid bogus",
"bogus",
false,
false,
},
}
@ -308,8 +342,14 @@ func TestParseMigProfile(t *testing.T) {
d := New(WithNvml(mockNvml), WithVerifySymbols(false))
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
_, err := d.ParseMigProfile(tc.device)
if tc.valid {
err := d.AssertValidMigProfileFormat(tc.device)
if tc.validFormat {
require.Nil(t, err)
} else {
require.Error(t, err)
}
_, err = d.ParseMigProfile(tc.device)
if tc.validDevice {
require.Nil(t, err)
} else {
require.Error(t, err)