174 lines
5.1 KiB
Go
174 lines
5.1 KiB
Go
package database
|
|
|
|
import "testing"
|
|
|
|
func TestRecommendPostgresOLTPSettings(t *testing.T) {
|
|
opts := PostgresTuneOptions{
|
|
Enabled: true,
|
|
Profile: postgresTuneProfileOLTP,
|
|
MemoryBudgetBytes: 16 * sizeGB,
|
|
CPUs: 8,
|
|
Connections: 100,
|
|
Storage: postgresTuneStorageNVMe,
|
|
DBSize: postgresTuneDBSizeMidRAM,
|
|
OSType: "linux",
|
|
}
|
|
|
|
settings := RecommendPostgresOLTPSettings(opts, 18)
|
|
byName := map[string]string{}
|
|
for _, setting := range settings {
|
|
byName[setting.Name] = setting.Value
|
|
}
|
|
|
|
expected := map[string]string{
|
|
"max_connections": "100",
|
|
"shared_buffers": "4GB",
|
|
"effective_cache_size": "12GB",
|
|
"maintenance_work_mem": "1GB",
|
|
"wal_buffers": "16MB",
|
|
"min_wal_size": "2GB",
|
|
"max_wal_size": "8GB",
|
|
"random_page_cost": "1.1",
|
|
"effective_io_concurrency": "1000",
|
|
"work_mem": "38836kB",
|
|
"huge_pages": "try",
|
|
"jit": "off",
|
|
"wal_compression": "lz4",
|
|
"max_worker_processes": "8",
|
|
"max_parallel_workers_per_gather": "4",
|
|
"max_parallel_workers": "8",
|
|
"max_parallel_maintenance_workers": "4",
|
|
}
|
|
|
|
for key, value := range expected {
|
|
if byName[key] != value {
|
|
t.Fatalf("%s = %q, want %q", key, byName[key], value)
|
|
}
|
|
}
|
|
|
|
if _, ok := byName["io_method"]; ok {
|
|
t.Fatal("io_method should only be emitted when explicitly configured")
|
|
}
|
|
}
|
|
|
|
func TestLoadPostgresTuneOptionsFromEnv(t *testing.T) {
|
|
t.Setenv("POSTGRES_TUNE", "auto")
|
|
t.Setenv("POSTGRES_TUNE_MEMORY", "8GB")
|
|
t.Setenv("POSTGRES_TUNE_CPUS", "4")
|
|
t.Setenv("POSTGRES_TUNE_STORAGE", "hdd")
|
|
t.Setenv("POSTGRES_TUNE_DB_SIZE", "greater_ram")
|
|
|
|
opts, err := LoadPostgresTuneOptionsFromEnv(20)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !opts.Enabled {
|
|
t.Fatal("expected tuning to be enabled")
|
|
}
|
|
if opts.MemoryBudgetBytes != 8*sizeGB {
|
|
t.Fatalf("MemoryBudgetBytes = %d, want %d", opts.MemoryBudgetBytes, 8*sizeGB)
|
|
}
|
|
if opts.DetectedMemoryBytes != 8*sizeGB {
|
|
t.Fatalf("DetectedMemoryBytes = %d, want %d", opts.DetectedMemoryBytes, 8*sizeGB)
|
|
}
|
|
if opts.MemorySource != "env" {
|
|
t.Fatalf("MemorySource = %q, want env", opts.MemorySource)
|
|
}
|
|
if opts.MemoryBudgetPercent != 100 {
|
|
t.Fatalf("MemoryBudgetPercent = %d, want 100", opts.MemoryBudgetPercent)
|
|
}
|
|
if opts.CPUs != 4 {
|
|
t.Fatalf("CPUs = %d, want 4", opts.CPUs)
|
|
}
|
|
if opts.Connections != 100 {
|
|
t.Fatalf("Connections = %d, want 100", opts.Connections)
|
|
}
|
|
if opts.Storage != postgresTuneStorageHDD {
|
|
t.Fatalf("Storage = %q, want %q", opts.Storage, postgresTuneStorageHDD)
|
|
}
|
|
if opts.DBSize != postgresTuneDBSizeGreaterRAM {
|
|
t.Fatalf("DBSize = %q, want %q", opts.DBSize, postgresTuneDBSizeGreaterRAM)
|
|
}
|
|
}
|
|
|
|
func TestLoadPostgresTuneOptionsUsesApplicationPoolForHighConnectionCounts(t *testing.T) {
|
|
t.Setenv("POSTGRES_TUNE", "oltp")
|
|
t.Setenv("POSTGRES_TUNE_MEMORY", "8GB")
|
|
t.Setenv("POSTGRES_TUNE_CPUS", "4")
|
|
|
|
opts, err := LoadPostgresTuneOptionsFromEnv(120)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if opts.Connections != 140 {
|
|
t.Fatalf("Connections = %d, want 140", opts.Connections)
|
|
}
|
|
}
|
|
|
|
func TestLoadPostgresTuneOptionsFloorsExplicitConnectionsAtApplicationPoolHeadroom(t *testing.T) {
|
|
t.Setenv("POSTGRES_TUNE", "oltp")
|
|
t.Setenv("POSTGRES_TUNE_MEMORY", "8GB")
|
|
t.Setenv("POSTGRES_TUNE_CPUS", "4")
|
|
t.Setenv("POSTGRES_TUNE_CONNECTIONS", "80")
|
|
|
|
opts, err := LoadPostgresTuneOptionsFromEnv(90)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if opts.Connections != 110 {
|
|
t.Fatalf("Connections = %d, want 110", opts.Connections)
|
|
}
|
|
}
|
|
|
|
func TestPostgresTuneDisabledByDefault(t *testing.T) {
|
|
opts, err := LoadPostgresTuneOptionsFromEnv(20)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if opts.Enabled {
|
|
t.Fatal("expected tuning to be disabled by default")
|
|
}
|
|
}
|
|
|
|
func TestPostgresTuneDBSizeDefaultsToAuto(t *testing.T) {
|
|
t.Setenv("POSTGRES_TUNE", "oltp")
|
|
t.Setenv("POSTGRES_TUNE_MEMORY", "8GB")
|
|
t.Setenv("POSTGRES_TUNE_CPUS", "4")
|
|
|
|
opts, err := LoadPostgresTuneOptionsFromEnv(20)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if opts.DBSize != postgresTuneDBSizeAuto {
|
|
t.Fatalf("DBSize = %q, want %q", opts.DBSize, postgresTuneDBSizeAuto)
|
|
}
|
|
}
|
|
|
|
func TestClassifyPostgresTuneDBSize(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dbSize int64
|
|
memBudget int64
|
|
wantDBSize string
|
|
}{
|
|
{name: "comfortably fits", dbSize: 8 * sizeGB, memBudget: 24 * sizeGB, wantDBSize: postgresTuneDBSizeLessRAM},
|
|
{name: "fits without headroom", dbSize: 18 * sizeGB, memBudget: 24 * sizeGB, wantDBSize: postgresTuneDBSizeMidRAM},
|
|
{name: "larger than budget", dbSize: 35 * sizeGB, memBudget: 24 * sizeGB, wantDBSize: postgresTuneDBSizeGreaterRAM},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := classifyPostgresTuneDBSize(tt.dbSize, tt.memBudget); got != tt.wantDBSize {
|
|
t.Fatalf("classifyPostgresTuneDBSize() = %q, want %q", got, tt.wantDBSize)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParsePostgresTuneByteSizeRequiresUnit(t *testing.T) {
|
|
if _, err := parsePostgresTuneByteSize("16"); err == nil {
|
|
t.Fatal("expected bare memory value to be rejected")
|
|
}
|
|
}
|