blob: 8e333a00649b0a79d2445dc0f6c7cfb7ae67a6fd [file] [edit]
package systemd
import (
"os"
"reflect"
"testing"
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
)
func newManager(t *testing.T, config *configs.Cgroup) (m cgroups.Manager) {
t.Helper()
var err error
if cgroups.IsCgroup2UnifiedMode() {
m, err = NewUnifiedManager(config, "")
} else {
m, err = NewLegacyManager(config, nil)
}
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = m.Destroy() })
return m
}
func TestSystemdVersion(t *testing.T) {
systemdVersionTests := []struct {
verStr string
expectedVer int
expectErr bool
}{
{`"219"`, 219, false},
{`"v245.4-1.fc32"`, 245, false},
{`"241-1"`, 241, false},
{`"v241-1"`, 241, false},
{`333.45"`, 333, false},
{`v321-0`, 321, false},
{"NaN", -1, true},
{"", -1, true},
{"v", -1, true},
}
for _, sdTest := range systemdVersionTests {
ver, err := systemdVersionAtoi(sdTest.verStr)
if !sdTest.expectErr && err != nil {
t.Errorf("systemdVersionAtoi(%s); want nil; got %v", sdTest.verStr, err)
}
if sdTest.expectErr && err == nil {
t.Errorf("systemdVersionAtoi(%s); wanted failure; got nil", sdTest.verStr)
}
if ver != sdTest.expectedVer {
t.Errorf("systemdVersionAtoi(%s); want %d; got %d", sdTest.verStr, sdTest.expectedVer, ver)
}
}
}
func TestValidUnitTypes(t *testing.T) {
testCases := []struct {
unitName string
expectedUnitType string
}{
{"system.slice", "Slice"},
{"kubepods.slice", "Slice"},
{"testing-container:ab.scope", "Scope"},
}
for _, sdTest := range testCases {
unitType := getUnitType(sdTest.unitName)
if unitType != sdTest.expectedUnitType {
t.Errorf("getUnitType(%s); want %q; got %q", sdTest.unitName, sdTest.expectedUnitType, unitType)
}
}
}
func TestUnitExistsIgnored(t *testing.T) {
if !IsRunningSystemd() {
t.Skip("Test requires systemd.")
}
if os.Geteuid() != 0 {
t.Skip("Test requires root.")
}
podConfig := &configs.Cgroup{
Parent: "system.slice",
Name: "system-runc_test_exists.slice",
Resources: &configs.Resources{},
}
// Create "pods" cgroup (a systemd slice to hold containers).
pm := newManager(t, podConfig)
// create twice to make sure "UnitExists" error is ignored.
for i := 0; i < 2; i++ {
if err := pm.Apply(-1); err != nil {
t.Fatal(err)
}
}
}
func TestUnifiedResToSystemdProps(t *testing.T) {
if !IsRunningSystemd() {
t.Skip("Test requires systemd.")
}
if !cgroups.IsCgroup2UnifiedMode() {
t.Skip("cgroup v2 is required")
}
cm := newDbusConnManager(os.Geteuid() != 0)
testCases := []struct {
name string
minVer int
res map[string]string
expError bool
expProps []systemdDbus.Property
}{
{
name: "empty map",
res: map[string]string{},
},
{
name: "only cpu.idle=1",
minVer: cpuIdleSupportedVersion,
res: map[string]string{
"cpu.idle": "1",
},
expProps: []systemdDbus.Property{
newProp("CPUWeight", uint64(0)),
},
},
{
name: "only cpu.idle=0",
minVer: cpuIdleSupportedVersion,
res: map[string]string{
"cpu.idle": "0",
},
},
{
name: "cpu.idle=1 and cpu.weight=1000",
minVer: cpuIdleSupportedVersion,
res: map[string]string{
"cpu.idle": "1",
"cpu.weight": "1000",
},
expProps: []systemdDbus.Property{
newProp("CPUWeight", uint64(0)),
},
},
{
name: "cpu.idle=0 and cpu.weight=1000",
minVer: cpuIdleSupportedVersion,
res: map[string]string{
"cpu.idle": "0",
"cpu.weight": "1000",
},
expProps: []systemdDbus.Property{
newProp("CPUWeight", uint64(1000)),
},
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if tc.minVer != 0 && systemdVersion(cm) < tc.minVer {
t.Skipf("requires systemd >= %d", tc.minVer)
}
props, err := unifiedResToSystemdProps(cm, tc.res)
if err != nil && !tc.expError {
t.Fatalf("expected no error, got: %v", err)
}
if err == nil && tc.expError {
t.Fatal("expected error, got nil")
}
if !reflect.DeepEqual(tc.expProps, props) {
t.Errorf("wrong properties (exp %+v, got %+v)", tc.expProps, props)
}
})
}
}