2
0

cache_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package currency
  2. import (
  3. "testing"
  4. "time"
  5. )
  6. func TestMemoryCache_SetAndGet(t *testing.T) {
  7. cache := newMemoryCache(1 * time.Hour)
  8. defer cache.stop()
  9. // Test setting and getting rates
  10. rates := &cachedRates{
  11. rates: map[string]float64{
  12. "EUR": 0.85,
  13. "GBP": 0.73,
  14. },
  15. baseCode: "USD",
  16. fetchedAt: time.Now(),
  17. }
  18. cache.set("USD", rates)
  19. // Test successful get
  20. retrieved, found := cache.get("USD")
  21. if !found {
  22. t.Error("expected to find cached rates")
  23. }
  24. if retrieved.baseCode != "USD" {
  25. t.Errorf("expected base code USD, got %s", retrieved.baseCode)
  26. }
  27. if len(retrieved.rates) != 2 {
  28. t.Errorf("expected 2 rates, got %d", len(retrieved.rates))
  29. }
  30. // Test non-existent key
  31. _, found = cache.get("EUR")
  32. if found {
  33. t.Error("expected not to find rates for EUR")
  34. }
  35. }
  36. func TestMemoryCache_Expiration(t *testing.T) {
  37. // Use short TTL for testing
  38. cache := newMemoryCache(100 * time.Millisecond)
  39. defer cache.stop()
  40. rates := &cachedRates{
  41. rates: map[string]float64{
  42. "EUR": 0.85,
  43. },
  44. baseCode: "USD",
  45. fetchedAt: time.Now(),
  46. }
  47. cache.set("USD", rates)
  48. // Should find it immediately
  49. _, found := cache.get("USD")
  50. if !found {
  51. t.Error("expected to find cached rates immediately")
  52. }
  53. // Wait for expiration
  54. time.Sleep(150 * time.Millisecond)
  55. // Should not find it after expiration
  56. _, found = cache.get("USD")
  57. if found {
  58. t.Error("expected rates to be expired")
  59. }
  60. }
  61. func TestMemoryCache_Clear(t *testing.T) {
  62. cache := newMemoryCache(1 * time.Hour)
  63. defer cache.stop()
  64. // Add multiple entries
  65. for _, base := range []string{"USD", "EUR", "GBP"} {
  66. rates := &cachedRates{
  67. rates: map[string]float64{"TEST": 1.0},
  68. baseCode: base,
  69. fetchedAt: time.Now(),
  70. }
  71. cache.set(base, rates)
  72. }
  73. // Verify all entries exist
  74. for _, base := range []string{"USD", "EUR", "GBP"} {
  75. _, found := cache.get(base)
  76. if !found {
  77. t.Errorf("expected to find rates for %s", base)
  78. }
  79. }
  80. // Clear cache
  81. cache.clear()
  82. // Verify all entries are gone
  83. for _, base := range []string{"USD", "EUR", "GBP"} {
  84. _, found := cache.get(base)
  85. if found {
  86. t.Errorf("expected not to find rates for %s after clear", base)
  87. }
  88. }
  89. }
  90. func TestMemoryCache_Stats(t *testing.T) {
  91. cache := newMemoryCache(1 * time.Hour)
  92. defer cache.stop()
  93. // Initially empty
  94. entries, _ := cache.stats()
  95. if entries != 0 {
  96. t.Errorf("expected 0 entries, got %d", entries)
  97. }
  98. // Add entries
  99. now := time.Now()
  100. for i, base := range []string{"USD", "EUR", "GBP"} {
  101. rates := &cachedRates{
  102. rates: map[string]float64{"TEST": 1.0},
  103. baseCode: base,
  104. fetchedAt: now.Add(time.Duration(i) * time.Minute),
  105. }
  106. cache.set(base, rates)
  107. }
  108. entries, oldest := cache.stats()
  109. if entries != 3 {
  110. t.Errorf("expected 3 entries, got %d", entries)
  111. }
  112. // The oldest should be the first one we added (USD)
  113. if !oldest.Equal(now) {
  114. t.Errorf("expected oldest entry to be %v, got %v", now, oldest)
  115. }
  116. }
  117. func TestMemoryCache_Cleanup(t *testing.T) {
  118. // Use very short TTL for testing
  119. cache := newMemoryCache(50 * time.Millisecond)
  120. defer cache.stop()
  121. // Add entry
  122. rates := &cachedRates{
  123. rates: map[string]float64{"EUR": 0.85},
  124. baseCode: "USD",
  125. fetchedAt: time.Now(),
  126. }
  127. cache.set("USD", rates)
  128. // Verify it exists
  129. entries, _ := cache.stats()
  130. if entries != 1 {
  131. t.Errorf("expected 1 entry, got %d", entries)
  132. }
  133. // Wait for cleanup cycle (janitor runs every TTL/2 = 25ms)
  134. // Wait a bit longer to ensure cleanup has run
  135. time.Sleep(100 * time.Millisecond)
  136. // Verify it's been cleaned up
  137. entries, _ = cache.stats()
  138. if entries != 0 {
  139. t.Errorf("expected 0 entries after cleanup, got %d", entries)
  140. }
  141. }