Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
memory_test.go7.27 kB
package config import ( "os" "testing" "time" ) // ============================================================================= // parseMemorySize Tests // ============================================================================= func TestParseMemorySize(t *testing.T) { tests := []struct { name string input string want int64 }{ // Bytes {"bytes numeric", "1024", 1024}, {"bytes with B suffix", "1024B", 1024}, {"bytes lowercase", "1024b", 1024}, // Kilobytes {"kilobytes K", "1K", 1024}, {"kilobytes KB", "1KB", 1024}, {"kilobytes lowercase", "1kb", 1024}, {"kilobytes large", "512K", 512 * 1024}, // Megabytes {"megabytes M", "1M", 1024 * 1024}, {"megabytes MB", "1MB", 1024 * 1024}, {"megabytes lowercase", "512mb", 512 * 1024 * 1024}, {"megabytes large", "256M", 256 * 1024 * 1024}, // Gigabytes {"gigabytes G", "1G", 1024 * 1024 * 1024}, {"gigabytes GB", "1GB", 1024 * 1024 * 1024}, {"gigabytes lowercase", "2gb", 2 * 1024 * 1024 * 1024}, {"gigabytes large", "4G", 4 * 1024 * 1024 * 1024}, // Terabytes {"terabytes T", "1T", 1024 * 1024 * 1024 * 1024}, {"terabytes TB", "1TB", 1024 * 1024 * 1024 * 1024}, // Unlimited/Zero {"zero", "0", 0}, {"unlimited", "unlimited", 0}, {"unlimited caps", "UNLIMITED", 0}, {"empty string", "", 0}, // Whitespace handling {"whitespace", " 2GB ", 2 * 1024 * 1024 * 1024}, // Invalid returns 0 {"invalid chars", "abc", 0}, // Negative values parse but result in negative (caller should validate) {"negative", "-1GB", -1 * 1024 * 1024 * 1024}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := parseMemorySize(tt.input) if got != tt.want { t.Errorf("parseMemorySize(%q) = %d, want %d", tt.input, got, tt.want) } }) } } // ============================================================================= // FormatMemorySize Tests // ============================================================================= func TestFormatMemorySize(t *testing.T) { tests := []struct { name string bytes int64 want string }{ {"zero", 0, "0 B"}, {"bytes", 512, "512 B"}, {"kilobytes", 1024, "1.00 KB"}, {"kilobytes fractional", 1536, "1.50 KB"}, {"megabytes", 1024 * 1024, "1.00 MB"}, {"megabytes fractional", 512 * 1024 * 1024, "512.00 MB"}, {"gigabytes", 1024 * 1024 * 1024, "1.00 GB"}, {"gigabytes large", 4 * 1024 * 1024 * 1024, "4.00 GB"}, {"terabytes", 1024 * 1024 * 1024 * 1024, "1.00 TB"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := FormatMemorySize(tt.bytes) if got != tt.want { t.Errorf("FormatMemorySize(%d) = %q, want %q", tt.bytes, got, tt.want) } }) } } // ============================================================================= // LoadFromEnv Runtime Memory Tests // ============================================================================= func TestLoadFromEnv_RuntimeMemory(t *testing.T) { // Clear environment first envVars := []string{ "NORNICDB_MEMORY_LIMIT", "NORNICDB_GC_PERCENT", "NORNICDB_POOL_ENABLED", "NORNICDB_POOL_MAX_SIZE", "NORNICDB_QUERY_CACHE_ENABLED", "NORNICDB_QUERY_CACHE_SIZE", "NORNICDB_QUERY_CACHE_TTL", } for _, v := range envVars { os.Unsetenv(v) } t.Run("defaults", func(t *testing.T) { cfg := LoadFromEnv() if cfg.Memory.RuntimeLimit != 0 { t.Errorf("RuntimeLimit = %d, want 0 (unlimited)", cfg.Memory.RuntimeLimit) } if cfg.Memory.GCPercent != 100 { t.Errorf("GCPercent = %d, want 100", cfg.Memory.GCPercent) } if !cfg.Memory.PoolEnabled { t.Error("PoolEnabled should be true by default") } if cfg.Memory.PoolMaxSize != 1000 { t.Errorf("PoolMaxSize = %d, want 1000", cfg.Memory.PoolMaxSize) } if !cfg.Memory.QueryCacheEnabled { t.Error("QueryCacheEnabled should be true by default") } if cfg.Memory.QueryCacheSize != 1000 { t.Errorf("QueryCacheSize = %d, want 1000", cfg.Memory.QueryCacheSize) } if cfg.Memory.QueryCacheTTL != 5*time.Minute { t.Errorf("QueryCacheTTL = %v, want 5m", cfg.Memory.QueryCacheTTL) } }) t.Run("memory limit from env", func(t *testing.T) { os.Setenv("NORNICDB_MEMORY_LIMIT", "2GB") defer os.Unsetenv("NORNICDB_MEMORY_LIMIT") cfg := LoadFromEnv() want := int64(2 * 1024 * 1024 * 1024) if cfg.Memory.RuntimeLimit != want { t.Errorf("RuntimeLimit = %d, want %d", cfg.Memory.RuntimeLimit, want) } if cfg.Memory.RuntimeLimitStr != "2GB" { t.Errorf("RuntimeLimitStr = %q, want %q", cfg.Memory.RuntimeLimitStr, "2GB") } }) t.Run("gc percent from env", func(t *testing.T) { os.Setenv("NORNICDB_GC_PERCENT", "50") defer os.Unsetenv("NORNICDB_GC_PERCENT") cfg := LoadFromEnv() if cfg.Memory.GCPercent != 50 { t.Errorf("GCPercent = %d, want 50", cfg.Memory.GCPercent) } }) t.Run("pool enabled false", func(t *testing.T) { os.Setenv("NORNICDB_POOL_ENABLED", "false") defer os.Unsetenv("NORNICDB_POOL_ENABLED") cfg := LoadFromEnv() if cfg.Memory.PoolEnabled { t.Error("PoolEnabled should be false") } }) t.Run("pool max size from env", func(t *testing.T) { os.Setenv("NORNICDB_POOL_MAX_SIZE", "500") defer os.Unsetenv("NORNICDB_POOL_MAX_SIZE") cfg := LoadFromEnv() if cfg.Memory.PoolMaxSize != 500 { t.Errorf("PoolMaxSize = %d, want 500", cfg.Memory.PoolMaxSize) } }) t.Run("query cache size from env", func(t *testing.T) { os.Setenv("NORNICDB_QUERY_CACHE_SIZE", "2000") defer os.Unsetenv("NORNICDB_QUERY_CACHE_SIZE") cfg := LoadFromEnv() if cfg.Memory.QueryCacheSize != 2000 { t.Errorf("QueryCacheSize = %d, want 2000", cfg.Memory.QueryCacheSize) } }) t.Run("query cache ttl from env", func(t *testing.T) { os.Setenv("NORNICDB_QUERY_CACHE_TTL", "10m") defer os.Unsetenv("NORNICDB_QUERY_CACHE_TTL") cfg := LoadFromEnv() if cfg.Memory.QueryCacheTTL != 10*time.Minute { t.Errorf("QueryCacheTTL = %v, want 10m", cfg.Memory.QueryCacheTTL) } }) } // ============================================================================= // ApplyRuntimeMemory Tests // ============================================================================= func TestMemoryConfig_ApplyRuntimeMemory(t *testing.T) { // Apply should not panic with defaults cfg := &MemoryConfig{ RuntimeLimit: 0, GCPercent: 100, } cfg.ApplyRuntimeMemory() // Should be no-op for defaults cfg2 := &MemoryConfig{ RuntimeLimit: 1024 * 1024 * 1024, // 1GB GCPercent: 50, } cfg2.ApplyRuntimeMemory() // Should set memory limit and GC percent // Reset to defaults cfg.GCPercent = 100 cfg.ApplyRuntimeMemory() } // ============================================================================= // Benchmarks // ============================================================================= func BenchmarkParseMemorySize(b *testing.B) { inputs := []string{"2GB", "512MB", "1024", "unlimited", "1TB"} for _, input := range inputs { b.Run(input, func(b *testing.B) { for i := 0; i < b.N; i++ { parseMemorySize(input) } }) } } func BenchmarkFormatMemorySize(b *testing.B) { sizes := []int64{1024, 1024 * 1024, 1024 * 1024 * 1024} for _, size := range sizes { b.Run(FormatMemorySize(size), func(b *testing.B) { for i := 0; i < b.N; i++ { FormatMemorySize(size) } }) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server