diff --git a/opts/ulimit.go b/opts/ulimit.go index 5adfe30851..4667cc2544 100644 --- a/opts/ulimit.go +++ b/opts/ulimit.go @@ -2,6 +2,7 @@ package opts import ( "fmt" + "sort" "github.com/docker/go-units" ) @@ -11,7 +12,7 @@ type UlimitOpt struct { values *map[string]*units.Ulimit } -// NewUlimitOpt creates a new UlimitOpt +// NewUlimitOpt creates a new UlimitOpt. Ulimits are not validated. func NewUlimitOpt(ref *map[string]*units.Ulimit) *UlimitOpt { if ref == nil { ref = &map[string]*units.Ulimit{} @@ -31,23 +32,25 @@ func (o *UlimitOpt) Set(val string) error { return nil } -// String returns Ulimit values as a string. +// String returns Ulimit values as a string. Values are sorted by name. func (o *UlimitOpt) String() string { var out []string for _, v := range *o.values { out = append(out, v.String()) } - + sort.Strings(out) return fmt.Sprintf("%v", out) } -// GetList returns a slice of pointers to Ulimits. +// GetList returns a slice of pointers to Ulimits. Values are sorted by name. func (o *UlimitOpt) GetList() []*units.Ulimit { var ulimits []*units.Ulimit for _, v := range *o.values { ulimits = append(ulimits, v) } - + sort.SliceStable(ulimits, func(i, j int) bool { + return ulimits[i].Name < ulimits[j].Name + }) return ulimits } diff --git a/opts/ulimit_test.go b/opts/ulimit_test.go index 8fc4d5c555..e3e7f64b72 100644 --- a/opts/ulimit_test.go +++ b/opts/ulimit_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/docker/go-units" + "gotest.tools/v3/assert" ) func TestUlimitOpt(t *testing.T) { @@ -14,29 +15,40 @@ func TestUlimitOpt(t *testing.T) { ulimitOpt := NewUlimitOpt(&ulimitMap) expected := "[nofile=512:1024]" - if ulimitOpt.String() != expected { - t.Fatalf("Expected %v, got %v", expected, ulimitOpt) - } + assert.Equal(t, ulimitOpt.String(), expected) // Valid ulimit append to opts - if err := ulimitOpt.Set("core=1024:1024"); err != nil { - t.Fatal(err) - } + err := ulimitOpt.Set("core=1024:1024") + assert.NilError(t, err) + + err = ulimitOpt.Set("nofile") + assert.ErrorContains(t, err, "invalid ulimit argument") // Invalid ulimit type returns an error and do not append to opts - if err := ulimitOpt.Set("notavalidtype=1024:1024"); err == nil { - t.Fatalf("Expected error on invalid ulimit type") - } - expected = "[nofile=512:1024 core=1024:1024]" - expected2 := "[core=1024:1024 nofile=512:1024]" - result := ulimitOpt.String() - if result != expected && result != expected2 { - t.Fatalf("Expected %v or %v, got %v", expected, expected2, ulimitOpt) - } + err = ulimitOpt.Set("notavalidtype=1024:1024") + assert.ErrorContains(t, err, "invalid ulimit type") + + expected = "[core=1024:1024 nofile=512:1024]" + assert.Equal(t, ulimitOpt.String(), expected) // And test GetList ulimits := ulimitOpt.GetList() - if len(ulimits) != 2 { - t.Fatalf("Expected a ulimit list of 2, got %v", ulimits) - } + assert.Equal(t, len(ulimits), 2) +} + +func TestUlimitOptSorting(t *testing.T) { + ulimitOpt := NewUlimitOpt(&map[string]*units.Ulimit{ + "nofile": {Name: "nofile", Hard: 1024, Soft: 512}, + "core": {Name: "core", Hard: 1024, Soft: 1024}, + }) + + expected := []*units.Ulimit{ + {Name: "core", Hard: 1024, Soft: 1024}, + {Name: "nofile", Hard: 1024, Soft: 512}, + } + + ulimits := ulimitOpt.GetList() + assert.DeepEqual(t, ulimits, expected) + + assert.Equal(t, ulimitOpt.String(), "[core=1024:1024 nofile=512:1024]") }