package bridge import ( "context" "sync" "testing" "time" "git.daviestechlabs.io/daviestechlabs/ntfy-discord/internal/ntfy" ) func TestBridge_IsReady(t *testing.T) { // Create a minimal bridge for testing ready state b := &Bridge{} // Initially not ready if b.IsReady() { t.Error("bridge should not be ready before Run()") } // Set ready b.ready.Store(true) if !b.IsReady() { t.Error("bridge should be ready after ready.Store(true)") } // Unset ready b.ready.Store(false) if b.IsReady() { t.Error("bridge should not be ready after ready.Store(false)") } } func TestMetricsRegistered(t *testing.T) { // Verify metrics are registered by checking they're not nil if messagesReceived == nil { t.Error("messagesReceived metric not registered") } if messagesSent == nil { t.Error("messagesSent metric not registered") } if messagesErrors == nil { t.Error("messagesErrors metric not registered") } } // Test that Bridge correctly uses the ready atomic func TestBridge_ReadyState_Concurrent(t *testing.T) { b := &Bridge{} // Test concurrent access var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(2) go func() { defer wg.Done() b.ready.Store(true) }() go func() { defer wg.Done() _ = b.IsReady() }() } wg.Wait() // Should not have any race conditions } // Test message channel buffer func TestMessageChannelBuffer(t *testing.T) { msgCh := make(chan ntfy.Message, 100) // Should be able to buffer 100 messages without blocking for i := 0; i < 100; i++ { select { case msgCh <- ntfy.Message{ID: "test"}: // OK default: t.Fatalf("channel blocked at message %d", i) } } // 101st should block (use select to avoid blocking test) select { case msgCh <- ntfy.Message{ID: "overflow"}: t.Error("channel should be full") default: // Expected - channel full } } // Test context cancellation behavior func TestContextCancellation(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) done := make(chan struct{}) go func() { // Simulate Run() loop behavior select { case <-ctx.Done(): close(done) case <-time.After(5 * time.Second): // Should not reach here } }() cancel() select { case <-done: // Success case <-time.After(time.Second): t.Error("context cancellation not handled") } }