feat: Full test suite and linter - fixed test failures and increased coverage to 61.1%
This commit is contained in:
178
internal/metrics/metrics_test.go
Normal file
178
internal/metrics/metrics_test.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestNewMetrics(t *testing.T) {
|
||||
m := New()
|
||||
if m.CacheHits == nil {
|
||||
t.Error("expected CacheHits to be initialized")
|
||||
}
|
||||
if m.CacheMisses == nil {
|
||||
t.Error("expected CacheMisses to be initialized")
|
||||
}
|
||||
if m.layerTTLs == nil {
|
||||
t.Error("expected layerTTLs to be initialized")
|
||||
}
|
||||
if m.SearchDuration == nil {
|
||||
t.Error("expected SearchDuration to be initialized")
|
||||
}
|
||||
if m.SearchDuration.maxValues != 1000 {
|
||||
t.Errorf("expected maxValues 1000, got %d", m.SearchDuration.maxValues)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsRecordCacheHit(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordCacheHit("search")
|
||||
m.RecordCacheHit("search")
|
||||
|
||||
m.mu.Lock()
|
||||
hits := m.CacheHits["search"]
|
||||
m.mu.Unlock()
|
||||
|
||||
if hits != 2 {
|
||||
t.Errorf("expected 2 cache hits, got %d", hits)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsRecordCacheMiss(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordCacheMiss("search")
|
||||
m.RecordCacheMiss("search")
|
||||
|
||||
m.mu.Lock()
|
||||
misses := m.CacheMisses["search"]
|
||||
m.mu.Unlock()
|
||||
|
||||
if misses != 2 {
|
||||
t.Errorf("expected 2 cache misses, got %d", misses)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsRecordAPIQuota(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordAPIQuota(1000)
|
||||
|
||||
m.mu.Lock()
|
||||
quota := m.APIQuotaRemaining
|
||||
m.mu.Unlock()
|
||||
|
||||
if quota != 1000 {
|
||||
t.Errorf("expected API quota 1000, got %d", quota)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsRecordCircuitBreakerTrip(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordCircuitBreakerTrip()
|
||||
m.RecordCircuitBreakerTrip()
|
||||
|
||||
m.mu.Lock()
|
||||
trips := m.CircuitBreakerTrips
|
||||
m.mu.Unlock()
|
||||
|
||||
if trips != 2 {
|
||||
t.Errorf("expected 2 circuit breaker trips, got %d", trips)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsRecordSearch(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordSearch(1000000000) // 1 second in nanoseconds
|
||||
m.RecordSearch(2000000000) // 2 seconds in nanoseconds
|
||||
|
||||
m.mu.Lock()
|
||||
count := m.SearchCount
|
||||
valuesLen := len(m.SearchDuration.values)
|
||||
m.mu.Unlock()
|
||||
|
||||
if count != 2 {
|
||||
t.Errorf("expected SearchCount 2, got %d", count)
|
||||
}
|
||||
if valuesLen != 2 {
|
||||
t.Errorf("expected 2 duration values, got %d", valuesLen)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsRecordSearchTrim(t *testing.T) {
|
||||
m := New()
|
||||
m.SearchDuration.maxValues = 2
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
m.RecordSearch(int64(i * 1000000000))
|
||||
}
|
||||
|
||||
m.mu.Lock()
|
||||
valuesLen := len(m.SearchDuration.values)
|
||||
m.mu.Unlock()
|
||||
|
||||
if valuesLen != 2 {
|
||||
t.Errorf("expected 2 duration values after trim, got %d", valuesLen)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsGetCacheHitRate(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordCacheHit("search")
|
||||
m.RecordCacheHit("search")
|
||||
m.RecordCacheMiss("search")
|
||||
|
||||
rate := m.GetCacheHitRate("search")
|
||||
if rate != 0.6666666666666666 { // 2/3
|
||||
t.Errorf("expected cache hit rate 0.6666666666666666, got %f", rate)
|
||||
}
|
||||
|
||||
// Test with no data
|
||||
rateEmpty := m.GetCacheHitRate("empty")
|
||||
if rateEmpty != 0 {
|
||||
t.Errorf("expected cache hit rate 0 for empty layer, got %f", rateEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsGetMetricsJSON(t *testing.T) {
|
||||
m := New()
|
||||
m.RecordCacheHit("search")
|
||||
m.RecordCacheMiss("search")
|
||||
m.RecordAPIQuota(500)
|
||||
m.RecordCircuitBreakerTrip()
|
||||
m.RecordSearch(1000000000)
|
||||
|
||||
json := m.GetMetricsJSON()
|
||||
|
||||
if json["cache_hits"] == nil {
|
||||
t.Error("expected cache_hits in JSON")
|
||||
}
|
||||
if json["cache_misses"] == nil {
|
||||
t.Error("expected cache_misses in JSON")
|
||||
}
|
||||
if json["api_quota_remaining"] != int64(500) {
|
||||
t.Errorf("expected api_quota_remaining 500, got %v", json["api_quota_remaining"])
|
||||
}
|
||||
if json["circuit_breaker_trips"] != int64(1) {
|
||||
t.Errorf("expected circuit_breaker_trips 1, got %v", json["circuit_breaker_trips"])
|
||||
}
|
||||
if json["search_count"] != int64(1) {
|
||||
t.Errorf("expected search_count 1, got %v", json["search_count"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetricsSetAndGetLayerTTL(t *testing.T) {
|
||||
m := New()
|
||||
m.SetLayerTTL("search", 3600*time.Second)
|
||||
|
||||
ttl, ok := m.GetLayerTTL("search")
|
||||
if !ok {
|
||||
t.Error("expected TTL to be found for 'search' layer")
|
||||
}
|
||||
if ttl != 3600*time.Second {
|
||||
t.Errorf("expected TTL 3600s, got %v", ttl)
|
||||
}
|
||||
|
||||
_, ok = m.GetLayerTTL("nonexistent")
|
||||
if ok {
|
||||
t.Error("expected TTL to not be found for 'nonexistent' layer")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user