106 lines
3.3 KiB
Go
106 lines
3.3 KiB
Go
package sys
|
|
|
|
import (
|
|
"os"
|
|
"runtime/debug"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// lookupGOGC reports whether a GOGC env is present at all: presence
|
|
// (even empty handling aside) makes the tuning defer to the runtime,
|
|
// which the default-profile tests cannot exercise.
|
|
func lookupGOGC() (string, bool) {
|
|
return os.LookupEnv("GOGC")
|
|
}
|
|
|
|
// The agent tuning profile (ITEM-P3 A1): GOGC default 50 and a
|
|
// 24 MiB default soft budget, with explicit env budgets still
|
|
// winning. The runtime knobs are process-global, so each test
|
|
// restores whatever GC percent / memory limit it found.
|
|
|
|
func preserveRuntimeKnobs(t *testing.T) {
|
|
t.Helper()
|
|
prevGC := debug.SetGCPercent(-1)
|
|
prevLimit := debug.SetMemoryLimit(-1)
|
|
t.Cleanup(func() {
|
|
debug.SetGCPercent(prevGC)
|
|
debug.SetMemoryLimit(prevLimit)
|
|
})
|
|
}
|
|
|
|
func unsetenv(t *testing.T, keys ...string) {
|
|
t.Helper()
|
|
for _, k := range keys {
|
|
t.Setenv(k, "")
|
|
// t.Setenv cannot unset; an empty value is what the tuning
|
|
// code treats as absent (it trims before checking), except
|
|
// for GOGC where LookupEnv counts presence — see the GOGC
|
|
// case below, which is exercised only via XUI_GOGC instead.
|
|
}
|
|
}
|
|
|
|
func TestApplyAgentMemoryTuningDefaults(t *testing.T) {
|
|
preserveRuntimeKnobs(t)
|
|
unsetenv(t, "GOMEMLIMIT", "XUI_MEMORY_LIMIT", "XUI_GOGC")
|
|
if _, present := lookupGOGC(); present {
|
|
t.Skip("GOGC is set in the test environment")
|
|
}
|
|
|
|
lines := ApplyAgentMemoryTuning()
|
|
joined := strings.Join(lines, "\n")
|
|
if !strings.Contains(joined, "GC percent set to 50") {
|
|
t.Fatalf("lines = %v, want GC percent 50", lines)
|
|
}
|
|
if !strings.Contains(joined, "Go memory soft limit set to 24 MiB (agent default budget)") {
|
|
t.Fatalf("lines = %v, want 24 MiB agent default budget", lines)
|
|
}
|
|
if got := debug.SetMemoryLimit(-1); got != int64(24)<<20 {
|
|
t.Fatalf("memory limit = %d, want %d", got, int64(24)<<20)
|
|
}
|
|
if got := debug.SetGCPercent(-1); got != 50 {
|
|
t.Fatalf("GC percent = %d, want 50", got)
|
|
}
|
|
}
|
|
|
|
func TestApplyAgentMemoryTuningExplicitLimitWins(t *testing.T) {
|
|
preserveRuntimeKnobs(t)
|
|
unsetenv(t, "GOMEMLIMIT")
|
|
t.Setenv("XUI_MEMORY_LIMIT", "40")
|
|
|
|
lines := ApplyAgentMemoryTuning()
|
|
if !strings.Contains(strings.Join(lines, "\n"), "Go memory soft limit set to 40 MiB (XUI_MEMORY_LIMIT=40MiB)") {
|
|
t.Fatalf("lines = %v, want XUI_MEMORY_LIMIT budget", lines)
|
|
}
|
|
if got := debug.SetMemoryLimit(-1); got != int64(40)<<20 {
|
|
t.Fatalf("memory limit = %d, want %d", got, int64(40)<<20)
|
|
}
|
|
}
|
|
|
|
func TestApplyAgentMemoryTuningGOMEMLIMITEnvWins(t *testing.T) {
|
|
preserveRuntimeKnobs(t)
|
|
before := debug.SetMemoryLimit(-1)
|
|
t.Setenv("GOMEMLIMIT", "32MiB")
|
|
|
|
lines := ApplyAgentMemoryTuning()
|
|
if !strings.Contains(strings.Join(lines, "\n"), "Go memory soft limit not enforced: GOMEMLIMIT env") {
|
|
t.Fatalf("lines = %v, want GOMEMLIMIT left to the runtime", lines)
|
|
}
|
|
if got := debug.SetMemoryLimit(-1); got != before {
|
|
t.Fatalf("memory limit changed to %d, want untouched %d", got, before)
|
|
}
|
|
}
|
|
|
|
func TestApplyAgentMemoryTuningXUIGOGCOverride(t *testing.T) {
|
|
preserveRuntimeKnobs(t)
|
|
if _, present := lookupGOGC(); present {
|
|
t.Skip("GOGC is set in the test environment")
|
|
}
|
|
t.Setenv("XUI_GOGC", "80")
|
|
|
|
lines := ApplyAgentMemoryTuning()
|
|
if !strings.Contains(strings.Join(lines, "\n"), "GC percent set to 80") {
|
|
t.Fatalf("lines = %v, want XUI_GOGC override", lines)
|
|
}
|
|
}
|