243 lines
4.4 KiB
Go
243 lines
4.4 KiB
Go
package watchdog_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"code.uint32.ru/tiny/watchdog"
|
|
)
|
|
|
|
type mockChecker struct {
|
|
name string
|
|
err error
|
|
called bool
|
|
}
|
|
|
|
func (m *mockChecker) Func(ctx context.Context) error {
|
|
m.called = true
|
|
|
|
time.Sleep(time.Millisecond * 10)
|
|
if err := ctx.Err(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return m.err
|
|
}
|
|
|
|
func (m *mockChecker) HasBeenCalled() bool {
|
|
return m.called
|
|
}
|
|
|
|
func (m *mockChecker) Check() watchdog.Check {
|
|
return watchdog.Check{
|
|
Name: m.name,
|
|
Interval: time.Minute,
|
|
Check: m.Func,
|
|
}
|
|
}
|
|
|
|
func newMockChecker(name string, err error) *mockChecker {
|
|
return &mockChecker{name: name, err: err}
|
|
}
|
|
|
|
func TestCreateWith_new(t *testing.T) {
|
|
w := new(watchdog.Watchdog)
|
|
|
|
if len(w.ListChecks()) != 0 {
|
|
t.Errorf("expected len = 0")
|
|
}
|
|
}
|
|
|
|
func TestNew(t *testing.T) {
|
|
w := watchdog.New()
|
|
|
|
if len(w.ListChecks()) != 0 {
|
|
t.Errorf("expected len = 0")
|
|
}
|
|
|
|
m1 := newMockChecker("mock", nil)
|
|
m2 := newMockChecker("mock2", nil)
|
|
|
|
w = watchdog.New()
|
|
w.AddChecks(m1.Check(), m2.Check())
|
|
if len(w.ListChecks()) != 2 {
|
|
t.Errorf("expected len = 2")
|
|
}
|
|
|
|
w.RemoveChecks("mock")
|
|
|
|
if len(w.ListChecks()) != 1 {
|
|
t.Errorf("expected len = 1")
|
|
}
|
|
|
|
w.RemoveChecks("mock2")
|
|
|
|
if len(w.ListChecks()) != 0 {
|
|
t.Errorf("expected len = 0")
|
|
}
|
|
|
|
w = watchdog.New(m1.Check(), m2.Check())
|
|
if len(w.ListChecks()) != 2 {
|
|
t.Errorf("")
|
|
}
|
|
}
|
|
|
|
func TestRunImmediately(t *testing.T) {
|
|
w := new(watchdog.Watchdog)
|
|
out, err := w.RunImmediately(t.Context(), 1)
|
|
if err == nil {
|
|
t.Error("empty instance must return error on RunImmediately")
|
|
}
|
|
if len(out) != 0 {
|
|
t.Errorf("expected zero len slice for empty instance, got %d", len(out))
|
|
}
|
|
|
|
m1 := newMockChecker("mock", nil)
|
|
m2 := newMockChecker("mock2", nil)
|
|
|
|
w = watchdog.New(m1.Check(), m2.Check())
|
|
out, _ = w.RunImmediately(t.Context(), 0)
|
|
if len(out) != 2 {
|
|
t.Error("expected result of len 2")
|
|
}
|
|
|
|
for _, m := range []*mockChecker{m1, m2} {
|
|
if !m.HasBeenCalled() {
|
|
t.Errorf("mock %s has not been called", m.name)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func TestStartStop(t *testing.T) {
|
|
w := new(watchdog.Watchdog)
|
|
if _, err := w.Start(0); err == nil {
|
|
t.Error("Start doen't error on empty checks slice")
|
|
}
|
|
|
|
m1 := newMockChecker("mock", nil)
|
|
m2 := newMockChecker("mock2", nil)
|
|
|
|
w.AddChecks(m1.Check(), m2.Check())
|
|
|
|
out, err := w.Start(0)
|
|
if err != nil {
|
|
t.Error("Start returns error", err)
|
|
}
|
|
|
|
out2, err := w.Start(0)
|
|
if err != nil {
|
|
t.Error("second call to Start returns error")
|
|
}
|
|
|
|
if !reflect.DeepEqual(out, out2) {
|
|
t.Error("returned channels are not equal")
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
if err := w.Stop(); err != nil {
|
|
t.Error("Stop returned error", err)
|
|
}
|
|
|
|
count := 0
|
|
|
|
for range out {
|
|
count++
|
|
}
|
|
|
|
if count != 0 {
|
|
t.Error("incorrect result count received from chan")
|
|
}
|
|
|
|
for _, m := range []*mockChecker{m1, m2} {
|
|
if !m.HasBeenCalled() {
|
|
t.Errorf("mock %s has not been called", m.name)
|
|
}
|
|
}
|
|
|
|
if err := w.Stop(); err == nil {
|
|
t.Error("call to stop on stopped instance does not return err")
|
|
}
|
|
}
|
|
|
|
func TestSetTimeout(t *testing.T) {
|
|
w := new(watchdog.Watchdog)
|
|
w.SetTimeout(time.Millisecond)
|
|
m1 := newMockChecker("mock", nil)
|
|
w.AddChecks(m1.Check())
|
|
|
|
out, _ := w.Start(0)
|
|
time.Sleep(time.Second)
|
|
w.Stop()
|
|
res := <-out
|
|
|
|
if !errors.Is(res.Error, context.DeadlineExceeded) {
|
|
t.Logf("got err: %v", res.Error)
|
|
t.Fatal("incorrect status for timed out op")
|
|
}
|
|
}
|
|
|
|
func TestDuplicates(t *testing.T) {
|
|
gethandler := func() http.HandlerFunc {
|
|
count := 0
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
count++
|
|
if count >= 10 {
|
|
// we, re up again
|
|
w.Write([]byte("OK"))
|
|
return
|
|
}
|
|
|
|
http.Error(w, "down", http.StatusInternalServerError)
|
|
}
|
|
}
|
|
|
|
srv := httptest.NewServer(gethandler())
|
|
|
|
addr := srv.URL
|
|
|
|
fn, err := watchdog.GetHTTP(addr, time.Second)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
w := new(watchdog.Watchdog)
|
|
|
|
check := watchdog.Check{
|
|
Name: "test",
|
|
Interval: time.Millisecond * 10,
|
|
Check: fn,
|
|
}
|
|
|
|
w.AddChecks(check)
|
|
w.SetTimeout(time.Millisecond * 10)
|
|
|
|
out, err := w.Start(1000)
|
|
if err != nil {
|
|
t.Error("Start returns error", err)
|
|
}
|
|
|
|
go func() {
|
|
time.Sleep(time.Second)
|
|
w.Stop()
|
|
}()
|
|
|
|
count := 0
|
|
|
|
for range out {
|
|
count++
|
|
}
|
|
|
|
if count != 2 {
|
|
// must only return one event on initial failure and
|
|
// one event whet endpoint becomes available
|
|
t.Error("incorrect result count received from chan")
|
|
t.Log("received count is", count)
|
|
}
|
|
}
|