simple_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package searcher
  2. import (
  3. "testing"
  4. "time"
  5. )
  6. // TestCache tests the basic functionality of the optimized cache
  7. func TestCache(t *testing.T) {
  8. cache := NewCache(100)
  9. defer cache.Close()
  10. req := &SearchRequest{
  11. Query: "test",
  12. Limit: 10,
  13. Offset: 0,
  14. }
  15. result := &SearchResult{
  16. TotalHits: 5,
  17. Hits: []*SearchHit{
  18. {ID: "doc1", Score: 1.0},
  19. {ID: "doc2", Score: 0.9},
  20. },
  21. }
  22. // Test cache miss
  23. cached := cache.Get(req)
  24. if cached != nil {
  25. t.Error("expected cache miss")
  26. }
  27. // Test cache put
  28. cache.Put(req, result, 1*time.Minute)
  29. // Test cache hit
  30. cached = cache.Get(req)
  31. if cached == nil {
  32. t.Fatal("expected cache hit")
  33. }
  34. if !cached.FromCache {
  35. t.Error("result should be marked as from cache")
  36. }
  37. // Test stats
  38. stats := cache.GetStats()
  39. if stats == nil {
  40. t.Fatal("stats should not be nil")
  41. }
  42. t.Logf("Cache stats: Size=%d, HitRate=%.2f", stats.Size, stats.HitRate)
  43. }
  44. func BenchmarkCacheKeyGeneration(b *testing.B) {
  45. cache := NewCache(1000)
  46. defer cache.Close()
  47. req := &SearchRequest{
  48. Query: "benchmark test query",
  49. Limit: 100,
  50. Offset: 0,
  51. SortBy: "score",
  52. SortOrder: SortOrderDesc,
  53. IPAddresses: []string{"192.168.1.1", "10.0.0.1"},
  54. StatusCodes: []int{200, 404, 500},
  55. Methods: []string{"GET", "POST"},
  56. }
  57. b.ResetTimer()
  58. b.ReportAllocs()
  59. for i := 0; i < b.N; i++ {
  60. _ = cache.GenerateKey(req)
  61. }
  62. }
  63. // New tests to ensure cache key considers LogPaths and is order-insensitive
  64. func TestCacheKeyIncludesLogPathsAndOrderInsensitive(t *testing.T) {
  65. cache := NewCache(100)
  66. defer cache.Close()
  67. st := int64(1000)
  68. et := int64(2000)
  69. reqA := &SearchRequest{
  70. Query: "q",
  71. Limit: 10,
  72. Offset: 0,
  73. StartTime: &st,
  74. EndTime: &et,
  75. UseMainLogPath: true,
  76. LogPaths: []string{"/var/log/nginx/a.log", "/var/log/nginx/b.log"},
  77. Methods: []string{"GET"},
  78. StatusCodes: []int{200, 404},
  79. }
  80. reqB := &SearchRequest{
  81. Query: "q",
  82. Limit: 10,
  83. Offset: 0,
  84. StartTime: &st,
  85. EndTime: &et,
  86. UseMainLogPath: true,
  87. LogPaths: []string{"/var/log/nginx/b.log", "/var/log/nginx/a.log"}, // reversed order
  88. Methods: []string{"GET"},
  89. StatusCodes: []int{404, 200}, // different order
  90. }
  91. keyA := cache.GenerateKey(reqA)
  92. keyB := cache.GenerateKey(reqB)
  93. if keyA != keyB {
  94. t.Fatalf("expected identical cache keys for order-insensitive params, got A=%s B=%s", keyA, keyB)
  95. }
  96. // Different log path should yield different key
  97. reqC := &SearchRequest{
  98. Query: "q",
  99. Limit: 10,
  100. Offset: 0,
  101. StartTime: &st,
  102. EndTime: &et,
  103. UseMainLogPath: true,
  104. LogPaths: []string{"/var/log/nginx/a.log"}, // different set
  105. Methods: []string{"GET"},
  106. StatusCodes: []int{200, 404},
  107. }
  108. keyC := cache.GenerateKey(reqC)
  109. if keyA == keyC {
  110. t.Fatalf("expected different cache keys when LogPaths differ, got A=%s C=%s", keyA, keyC)
  111. }
  112. }
  113. func BenchmarkCacheOperations(b *testing.B) {
  114. cache := NewCache(10000)
  115. defer cache.Close()
  116. req := &SearchRequest{
  117. Query: "benchmark",
  118. Limit: 50,
  119. }
  120. result := &SearchResult{
  121. TotalHits: 100,
  122. Hits: []*SearchHit{
  123. {ID: "doc1", Score: 1.0},
  124. {ID: "doc2", Score: 0.9},
  125. },
  126. }
  127. b.Run("Put", func(b *testing.B) {
  128. b.ResetTimer()
  129. b.ReportAllocs()
  130. for i := 0; i < b.N; i++ {
  131. testReq := &SearchRequest{
  132. Query: req.Query + string(rune(i%1000)),
  133. Limit: req.Limit,
  134. Offset: i,
  135. }
  136. cache.Put(testReq, result, 1*time.Minute)
  137. }
  138. })
  139. b.Run("Get", func(b *testing.B) {
  140. // Pre-populate cache
  141. cache.Put(req, result, 1*time.Minute)
  142. b.ResetTimer()
  143. b.ReportAllocs()
  144. for i := 0; i < b.N; i++ {
  145. _ = cache.Get(req)
  146. }
  147. })
  148. }