github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/cgroups/systemd/systemd_test.go (about) 1 package systemd 2 3 import ( 4 "os" 5 "reflect" 6 "testing" 7 8 systemdDbus "github.com/coreos/go-systemd/v22/dbus" 9 "github.com/opencontainers/runc/libcontainer/cgroups" 10 "github.com/opencontainers/runc/libcontainer/configs" 11 ) 12 13 func newManager(t *testing.T, config *configs.Cgroup) (m cgroups.Manager) { 14 t.Helper() 15 var err error 16 17 if cgroups.IsCgroup2UnifiedMode() { 18 m, err = NewUnifiedManager(config, "") 19 } else { 20 m, err = NewLegacyManager(config, nil) 21 } 22 if err != nil { 23 t.Fatal(err) 24 } 25 t.Cleanup(func() { _ = m.Destroy() }) 26 27 return m 28 } 29 30 func TestSystemdVersion(t *testing.T) { 31 systemdVersionTests := []struct { 32 verStr string 33 expectedVer int 34 expectErr bool 35 }{ 36 {`"219"`, 219, false}, 37 {`"v245.4-1.fc32"`, 245, false}, 38 {`"241-1"`, 241, false}, 39 {`"v241-1"`, 241, false}, 40 {`333.45"`, 333, false}, 41 {`v321-0`, 321, false}, 42 {"NaN", -1, true}, 43 {"", -1, true}, 44 {"v", -1, true}, 45 } 46 for _, sdTest := range systemdVersionTests { 47 ver, err := systemdVersionAtoi(sdTest.verStr) 48 if !sdTest.expectErr && err != nil { 49 t.Errorf("systemdVersionAtoi(%s); want nil; got %v", sdTest.verStr, err) 50 } 51 if sdTest.expectErr && err == nil { 52 t.Errorf("systemdVersionAtoi(%s); wanted failure; got nil", sdTest.verStr) 53 } 54 if ver != sdTest.expectedVer { 55 t.Errorf("systemdVersionAtoi(%s); want %d; got %d", sdTest.verStr, sdTest.expectedVer, ver) 56 } 57 } 58 } 59 60 func TestValidUnitTypes(t *testing.T) { 61 testCases := []struct { 62 unitName string 63 expectedUnitType string 64 }{ 65 {"system.slice", "Slice"}, 66 {"kubepods.slice", "Slice"}, 67 {"testing-container:ab.scope", "Scope"}, 68 } 69 for _, sdTest := range testCases { 70 unitType := getUnitType(sdTest.unitName) 71 if unitType != sdTest.expectedUnitType { 72 t.Errorf("getUnitType(%s); want %q; got %q", sdTest.unitName, sdTest.expectedUnitType, unitType) 73 } 74 } 75 } 76 77 func TestUnitExistsIgnored(t *testing.T) { 78 if !IsRunningSystemd() { 79 t.Skip("Test requires systemd.") 80 } 81 if os.Geteuid() != 0 { 82 t.Skip("Test requires root.") 83 } 84 85 podConfig := &configs.Cgroup{ 86 Parent: "system.slice", 87 Name: "system-runc_test_exists.slice", 88 Resources: &configs.Resources{}, 89 } 90 // Create "pods" cgroup (a systemd slice to hold containers). 91 pm := newManager(t, podConfig) 92 93 // create twice to make sure "UnitExists" error is ignored. 94 for i := 0; i < 2; i++ { 95 if err := pm.Apply(-1); err != nil { 96 t.Fatal(err) 97 } 98 } 99 } 100 101 func TestUnifiedResToSystemdProps(t *testing.T) { 102 if !IsRunningSystemd() { 103 t.Skip("Test requires systemd.") 104 } 105 if !cgroups.IsCgroup2UnifiedMode() { 106 t.Skip("cgroup v2 is required") 107 } 108 109 cm := newDbusConnManager(os.Geteuid() != 0) 110 111 testCases := []struct { 112 name string 113 minVer int 114 res map[string]string 115 expError bool 116 expProps []systemdDbus.Property 117 }{ 118 { 119 name: "empty map", 120 res: map[string]string{}, 121 }, 122 { 123 name: "only cpu.idle=1", 124 minVer: cpuIdleSupportedVersion, 125 res: map[string]string{ 126 "cpu.idle": "1", 127 }, 128 expProps: []systemdDbus.Property{ 129 newProp("CPUWeight", uint64(0)), 130 }, 131 }, 132 { 133 name: "only cpu.idle=0", 134 minVer: cpuIdleSupportedVersion, 135 res: map[string]string{ 136 "cpu.idle": "0", 137 }, 138 }, 139 { 140 name: "cpu.idle=1 and cpu.weight=1000", 141 minVer: cpuIdleSupportedVersion, 142 res: map[string]string{ 143 "cpu.idle": "1", 144 "cpu.weight": "1000", 145 }, 146 expProps: []systemdDbus.Property{ 147 newProp("CPUWeight", uint64(0)), 148 }, 149 }, 150 { 151 name: "cpu.idle=0 and cpu.weight=1000", 152 minVer: cpuIdleSupportedVersion, 153 res: map[string]string{ 154 "cpu.idle": "0", 155 "cpu.weight": "1000", 156 }, 157 expProps: []systemdDbus.Property{ 158 newProp("CPUWeight", uint64(1000)), 159 }, 160 }, 161 } 162 163 for _, tc := range testCases { 164 tc := tc 165 t.Run(tc.name, func(t *testing.T) { 166 if tc.minVer != 0 && systemdVersion(cm) < tc.minVer { 167 t.Skipf("requires systemd >= %d", tc.minVer) 168 } 169 props, err := unifiedResToSystemdProps(cm, tc.res) 170 if err != nil && !tc.expError { 171 t.Fatalf("expected no error, got: %v", err) 172 } 173 if err == nil && tc.expError { 174 t.Fatal("expected error, got nil") 175 } 176 if !reflect.DeepEqual(tc.expProps, props) { 177 t.Errorf("wrong properties (exp %+v, got %+v)", tc.expProps, props) 178 } 179 }) 180 } 181 }