package health import ( "io" "net/http" "net/http/httptest" "strings" "sync" "testing" "github.com/stretchr/testify/assert" ) const probeName = "probe" func TestHealthManager(t *testing.T) { hm := NewHealthManager(probeName) assert.False(t, hm.IsReady()) hm.MarkReady() assert.True(t, hm.IsReady()) hm.MarkNotReady() assert.False(t, hm.IsReady()) t.Run("concurrent should works", func(t *testing.T) { var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func() { hm.MarkReady() wg.Done() }() } wg.Wait() assert.True(t, hm.IsReady()) }) } func TestComboHealthManager(t *testing.T) { t.Run("base", func(t *testing.T) { chm := newComboHealthManager() hm1 := NewHealthManager(probeName) hm2 := NewHealthManager(probeName + "2") assert.True(t, chm.IsReady()) chm.addProbe(hm1) chm.addProbe(hm2) assert.False(t, chm.IsReady()) hm1.MarkReady() assert.False(t, chm.IsReady()) hm2.MarkReady() assert.True(t, chm.IsReady()) }) t.Run("is ready verbose", func(t *testing.T) { chm := newComboHealthManager() hm := NewHealthManager(probeName) assert.True(t, chm.IsReady()) chm.addProbe(hm) assert.False(t, chm.IsReady()) hm.MarkReady() assert.True(t, chm.IsReady()) assert.Contains(t, chm.verboseInfo(), probeName) assert.Contains(t, chm.verboseInfo(), "is ready") }) t.Run("concurrent add probes", func(t *testing.T) { chm := newComboHealthManager() var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func() { hm := NewHealthManager(probeName) hm.MarkReady() chm.addProbe(hm) wg.Done() }() } wg.Wait() assert.True(t, chm.IsReady()) }) t.Run("markReady and markNotReady", func(t *testing.T) { chm := newComboHealthManager() for i := 0; i < 10; i++ { hm := NewHealthManager(probeName) chm.addProbe(hm) } assert.False(t, chm.IsReady()) chm.MarkReady() assert.True(t, chm.IsReady()) chm.MarkNotReady() assert.False(t, chm.IsReady()) }) } func TestAddGlobalProbes(t *testing.T) { cleanupForTest(t) t.Run("concurrent add probes", func(t *testing.T) { var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func() { hm := NewHealthManager(probeName) hm.MarkReady() AddProbe(hm) wg.Done() }() } wg.Wait() assert.True(t, defaultHealthManager.IsReady()) }) } func TestCreateHttpHandler(t *testing.T) { cleanupForTest(t) srv := httptest.NewServer(CreateHttpHandler()) defer srv.Close() resp, err := http.Get(srv.URL) assert.Nil(t, err) _ = resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) hm := NewHealthManager(probeName) defaultHealthManager.addProbe(hm) resp, err = http.Get(srv.URL) assert.Nil(t, err) assert.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) content, _ := io.ReadAll(resp.Body) assert.True(t, strings.HasPrefix(string(content), "Service Unavailable")) _ = resp.Body.Close() hm.MarkReady() resp, err = http.Get(srv.URL) assert.Nil(t, err) _ = resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) } func cleanupForTest(t *testing.T) { t.Cleanup(func() { defaultHealthManager = &comboHealthManager{} }) }