|
17 | 17 | package cgroup2
|
18 | 18 |
|
19 | 19 | import (
|
| 20 | + "context" |
20 | 21 | "fmt"
|
21 | 22 | "os"
|
22 | 23 | "os/exec"
|
23 | 24 | "syscall"
|
24 | 25 | "testing"
|
25 | 26 | "time"
|
26 | 27 |
|
| 28 | + systemdDbus "github.com/coreos/go-systemd/v22/dbus" |
27 | 29 | "github.com/opencontainers/runtime-spec/specs-go"
|
28 | 30 | "github.com/stretchr/testify/assert"
|
29 | 31 | "github.com/stretchr/testify/require"
|
@@ -343,6 +345,83 @@ func TestSystemdCgroupPSIController(t *testing.T) {
|
343 | 345 | }
|
344 | 346 | }
|
345 | 347 |
|
| 348 | +func TestCPUQuotaPeriodUSec(t *testing.T) { |
| 349 | + checkCgroupMode(t) |
| 350 | + |
| 351 | + // Create a unique group name using the current process ID |
| 352 | + group := fmt.Sprintf("testing-cpu-period-%d.scope", os.Getpid()) |
| 353 | + |
| 354 | + tests := []struct { |
| 355 | + name string |
| 356 | + quota int64 |
| 357 | + period uint64 |
| 358 | + }{ |
| 359 | + { |
| 360 | + name: "quota 100000, default period", |
| 361 | + quota: 100000, |
| 362 | + }, |
| 363 | + { |
| 364 | + name: "quota 10000, period 8000", |
| 365 | + quota: 10000, |
| 366 | + period: 8000, |
| 367 | + }, |
| 368 | + } |
| 369 | + |
| 370 | + for _, test := range tests { |
| 371 | + t.Run(test.name, func(t *testing.T) { |
| 372 | + var ( |
| 373 | + cpuMax CPUMax |
| 374 | + expectedCPUMax string |
| 375 | + ) |
| 376 | + if test.period == 0 { |
| 377 | + cpuMax = NewCPUMax(&test.quota, nil) |
| 378 | + expectedCPUMax = fmt.Sprintf("%d", test.quota) |
| 379 | + } else { |
| 380 | + cpuMax = NewCPUMax(&test.quota, &test.period) |
| 381 | + expectedCPUMax = fmt.Sprintf("%d %d", test.quota, test.period) |
| 382 | + } |
| 383 | + |
| 384 | + c, err := NewSystemd("", group, os.Getpid(), &Resources{ |
| 385 | + CPU: &CPU{ |
| 386 | + Max: cpuMax, |
| 387 | + }, |
| 388 | + }) |
| 389 | + require.NoError(t, err, "failed to init new cgroup systemd manager") |
| 390 | + |
| 391 | + checkFileContent(t, c.path, "cpu.max", expectedCPUMax) |
| 392 | + |
| 393 | + conn, err := systemdDbus.NewWithContext(context.TODO()) |
| 394 | + require.NoError(t, err, "failed to connect to systemd") |
| 395 | + defer conn.Close() |
| 396 | + |
| 397 | + sdVer := systemdVersion(conn) |
| 398 | + if sdVer >= 242 { |
| 399 | + unitName := systemdUnitFromPath(c.path) |
| 400 | + props, err := conn.GetAllPropertiesContext(context.TODO(), unitName) |
| 401 | + require.NoError(t, err, "failed to get unit properties") |
| 402 | + |
| 403 | + periodUSec, ok := props["CPUQuotaPeriodUSec"] |
| 404 | + require.True(t, ok, "CPUQuotaPeriodUSec property not found") |
| 405 | + require.Equal(t, test.period, periodUSec.(uint64), "CPUQuotaPeriodUSec value doesn't match expected period") |
| 406 | + } else { |
| 407 | + t.Logf("Skipping CPUQuotaPeriodUSec test for systemd version %d", sdVer) |
| 408 | + } |
| 409 | + }) |
| 410 | + } |
| 411 | + |
| 412 | + // // Also verify CPUQuotaPerSecUSec is set correctly |
| 413 | + // quotaPerSecUSec, ok := props["CPUQuotaPerSecUSec"] |
| 414 | + // require.True(t, ok, "CPUQuotaPerSecUSec property not found") |
| 415 | + |
| 416 | + // // Calculate expected value: quota*1000000/period |
| 417 | + // expectedQuotaPerSecUSec := uint64(quota*1000000) / period |
| 418 | + // // Round up to nearest 10000 if needed |
| 419 | + // if expectedQuotaPerSecUSec%10000 != 0 { |
| 420 | + // expectedQuotaPerSecUSec = ((expectedQuotaPerSecUSec / 10000) + 1) * 10000 |
| 421 | + // } |
| 422 | + // require.Equal(t, expectedQuotaPerSecUSec, quotaPerSecUSec.(uint64), "CPUQuotaPerSecUSec value doesn't match expected value") |
| 423 | +} |
| 424 | + |
346 | 425 | func BenchmarkStat(b *testing.B) {
|
347 | 426 | checkCgroupMode(b)
|
348 | 427 | group := "/stat-test-cg"
|
|
0 commit comments