|
|
|
|
| package agent
|
|
|
| import (
|
| "testing"
|
| "testing/synctest"
|
| "time"
|
|
|
| "github.com/henrygd/beszel/internal/entities/container"
|
| "github.com/henrygd/beszel/internal/entities/system"
|
| "github.com/stretchr/testify/assert"
|
| "github.com/stretchr/testify/require"
|
| )
|
|
|
| func createTestCacheData() *system.CombinedData {
|
| return &system.CombinedData{
|
| Stats: system.Stats{
|
| Cpu: 50.5,
|
| Mem: 8192,
|
| DiskTotal: 100000,
|
| },
|
| Info: system.Info{
|
| AgentVersion: "0.12.0",
|
| },
|
| Containers: []*container.Stats{
|
| {
|
| Name: "test-container",
|
| Cpu: 25.0,
|
| },
|
| },
|
| }
|
| }
|
|
|
| func TestNewSystemDataCache(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| require.NotNil(t, cache)
|
| assert.NotNil(t, cache.cache)
|
| assert.Empty(t, cache.cache)
|
| }
|
|
|
| func TestCacheGetSet(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| data := createTestCacheData()
|
|
|
|
|
| cache.Set(data, 1000)
|
|
|
|
|
| retrieved, isCached := cache.Get(1000)
|
| assert.True(t, isCached)
|
| assert.Equal(t, data, retrieved)
|
|
|
|
|
| _, isCached = cache.Get(2000)
|
| assert.False(t, isCached)
|
| }
|
|
|
| func TestCacheFreshness(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| data := createTestCacheData()
|
|
|
| testCases := []struct {
|
| name string
|
| cacheTimeMs uint16
|
| sleepMs time.Duration
|
| expectFresh bool
|
| }{
|
| {
|
| name: "fresh data - well within cache time",
|
| cacheTimeMs: 1000,
|
| sleepMs: 100,
|
| expectFresh: true,
|
| },
|
| {
|
| name: "fresh data - at 50% of cache time boundary",
|
| cacheTimeMs: 1000,
|
| sleepMs: 499,
|
| expectFresh: true,
|
| },
|
| {
|
| name: "stale data - exactly at 50% cache time",
|
| cacheTimeMs: 1000,
|
| sleepMs: 500,
|
| expectFresh: false,
|
| },
|
| {
|
| name: "stale data - well beyond cache time",
|
| cacheTimeMs: 1000,
|
| sleepMs: 800,
|
| expectFresh: false,
|
| },
|
| {
|
| name: "short cache time",
|
| cacheTimeMs: 200,
|
| sleepMs: 150,
|
| expectFresh: false,
|
| },
|
| }
|
|
|
| for _, tc := range testCases {
|
| t.Run(tc.name, func(t *testing.T) {
|
| synctest.Test(t, func(t *testing.T) {
|
|
|
| cache.Set(data, tc.cacheTimeMs)
|
|
|
|
|
| if tc.sleepMs > 0 {
|
| time.Sleep(tc.sleepMs * time.Millisecond)
|
| }
|
|
|
|
|
| _, isCached := cache.Get(tc.cacheTimeMs)
|
| assert.Equal(t, tc.expectFresh, isCached)
|
| })
|
| })
|
| }
|
| }
|
|
|
| func TestCacheMultipleIntervals(t *testing.T) {
|
| synctest.Test(t, func(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| data1 := createTestCacheData()
|
| data2 := &system.CombinedData{
|
| Stats: system.Stats{
|
| Cpu: 75.0,
|
| Mem: 16384,
|
| },
|
| Info: system.Info{
|
| AgentVersion: "0.12.0",
|
| },
|
| Containers: []*container.Stats{},
|
| }
|
|
|
|
|
| cache.Set(data1, 500)
|
| cache.Set(data2, 1000)
|
|
|
|
|
| retrieved1, isCached1 := cache.Get(500)
|
| assert.True(t, isCached1)
|
| assert.Equal(t, data1, retrieved1)
|
|
|
| retrieved2, isCached2 := cache.Get(1000)
|
| assert.True(t, isCached2)
|
| assert.Equal(t, data2, retrieved2)
|
|
|
|
|
| time.Sleep(300 * time.Millisecond)
|
|
|
| _, isCached1 = cache.Get(500)
|
| assert.False(t, isCached1)
|
|
|
| _, isCached2 = cache.Get(1000)
|
| assert.True(t, isCached2)
|
|
|
|
|
| time.Sleep(300 * time.Millisecond)
|
| _, isCached2 = cache.Get(1000)
|
| assert.False(t, isCached2)
|
| })
|
| }
|
|
|
| func TestCacheOverwrite(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| data1 := createTestCacheData()
|
| data2 := &system.CombinedData{
|
| Stats: system.Stats{
|
| Cpu: 90.0,
|
| Mem: 32768,
|
| },
|
| Info: system.Info{
|
| AgentVersion: "0.12.0",
|
| },
|
| Containers: []*container.Stats{},
|
| }
|
|
|
|
|
| cache.Set(data1, 1000)
|
| retrieved, isCached := cache.Get(1000)
|
| assert.True(t, isCached)
|
| assert.Equal(t, data1, retrieved)
|
|
|
|
|
| cache.Set(data2, 1000)
|
| retrieved, isCached = cache.Get(1000)
|
| assert.True(t, isCached)
|
| assert.Equal(t, data2, retrieved)
|
| assert.NotEqual(t, data1, retrieved)
|
| }
|
|
|
| func TestCacheMiss(t *testing.T) {
|
| synctest.Test(t, func(t *testing.T) {
|
| cache := NewSystemDataCache()
|
|
|
|
|
| _, isCached := cache.Get(1000)
|
| assert.False(t, isCached)
|
|
|
|
|
| data := createTestCacheData()
|
| cache.Set(data, 1000)
|
|
|
|
|
| _, isCached = cache.Get(2000)
|
| assert.False(t, isCached)
|
|
|
|
|
| time.Sleep(600 * time.Millisecond)
|
| _, isCached = cache.Get(1000)
|
| assert.False(t, isCached)
|
| })
|
| }
|
|
|
| func TestCacheZeroInterval(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| data := createTestCacheData()
|
|
|
|
|
| cache.Set(data, 0)
|
|
|
|
|
|
|
| _, isCached := cache.Get(0)
|
| assert.False(t, isCached)
|
| }
|
|
|
| func TestCacheLargeInterval(t *testing.T) {
|
| synctest.Test(t, func(t *testing.T) {
|
| cache := NewSystemDataCache()
|
| data := createTestCacheData()
|
|
|
|
|
| cache.Set(data, 65535)
|
|
|
|
|
| _, isCached := cache.Get(65535)
|
| assert.True(t, isCached)
|
|
|
|
|
| time.Sleep(100 * time.Millisecond)
|
| _, isCached = cache.Get(65535)
|
| assert.True(t, isCached)
|
| })
|
| }
|
|
|