github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/handlers/health_test.go (about) 1 package handlers 2 3 import ( 4 "io/ioutil" 5 "net" 6 "net/http" 7 "net/http/httptest" 8 "os" 9 "testing" 10 "time" 11 12 "github.com/docker/distribution/configuration" 13 "github.com/docker/distribution/context" 14 "github.com/docker/distribution/health" 15 ) 16 17 func TestFileHealthCheck(t *testing.T) { 18 interval := time.Second 19 20 tmpfile, err := ioutil.TempFile(os.TempDir(), "healthcheck") 21 if err != nil { 22 t.Fatalf("could not create temporary file: %v", err) 23 } 24 defer tmpfile.Close() 25 26 config := &configuration.Configuration{ 27 Storage: configuration.Storage{ 28 "inmemory": configuration.Parameters{}, 29 }, 30 Health: configuration.Health{ 31 FileCheckers: []configuration.FileChecker{ 32 { 33 Interval: interval, 34 File: tmpfile.Name(), 35 }, 36 }, 37 }, 38 } 39 40 ctx := context.Background() 41 42 app := NewApp(ctx, config) 43 healthRegistry := health.NewRegistry() 44 app.RegisterHealthChecks(healthRegistry) 45 46 // Wait for health check to happen 47 <-time.After(2 * interval) 48 49 status := healthRegistry.CheckStatus() 50 if len(status) != 1 { 51 t.Fatal("expected 1 item in health check results") 52 } 53 if status[tmpfile.Name()] != "file exists" { 54 t.Fatal(`did not get "file exists" result for health check`) 55 } 56 57 os.Remove(tmpfile.Name()) 58 59 <-time.After(2 * interval) 60 if len(healthRegistry.CheckStatus()) != 0 { 61 t.Fatal("expected 0 items in health check results") 62 } 63 } 64 65 func TestTCPHealthCheck(t *testing.T) { 66 interval := time.Second 67 68 ln, err := net.Listen("tcp", "127.0.0.1:0") 69 if err != nil { 70 t.Fatalf("could not create listener: %v", err) 71 } 72 addrStr := ln.Addr().String() 73 74 // Start accepting 75 go func() { 76 for { 77 conn, err := ln.Accept() 78 if err != nil { 79 // listener was closed 80 return 81 } 82 defer conn.Close() 83 } 84 }() 85 86 config := &configuration.Configuration{ 87 Storage: configuration.Storage{ 88 "inmemory": configuration.Parameters{}, 89 }, 90 Health: configuration.Health{ 91 TCPCheckers: []configuration.TCPChecker{ 92 { 93 Interval: interval, 94 Addr: addrStr, 95 Timeout: 500 * time.Millisecond, 96 }, 97 }, 98 }, 99 } 100 101 ctx := context.Background() 102 103 app := NewApp(ctx, config) 104 healthRegistry := health.NewRegistry() 105 app.RegisterHealthChecks(healthRegistry) 106 107 // Wait for health check to happen 108 <-time.After(2 * interval) 109 110 if len(healthRegistry.CheckStatus()) != 0 { 111 t.Fatal("expected 0 items in health check results") 112 } 113 114 ln.Close() 115 <-time.After(2 * interval) 116 117 // Health check should now fail 118 status := healthRegistry.CheckStatus() 119 if len(status) != 1 { 120 t.Fatal("expected 1 item in health check results") 121 } 122 if status[addrStr] != "connection to "+addrStr+" failed" { 123 t.Fatal(`did not get "connection failed" result for health check`) 124 } 125 } 126 127 func TestHTTPHealthCheck(t *testing.T) { 128 interval := time.Second 129 threshold := 3 130 131 stopFailing := make(chan struct{}) 132 133 checkedServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 134 if r.Method != "HEAD" { 135 t.Fatalf("expected HEAD request, got %s", r.Method) 136 } 137 select { 138 case <-stopFailing: 139 w.WriteHeader(http.StatusOK) 140 default: 141 w.WriteHeader(http.StatusInternalServerError) 142 } 143 })) 144 145 config := &configuration.Configuration{ 146 Storage: configuration.Storage{ 147 "inmemory": configuration.Parameters{}, 148 }, 149 Health: configuration.Health{ 150 HTTPCheckers: []configuration.HTTPChecker{ 151 { 152 Interval: interval, 153 URI: checkedServer.URL, 154 Threshold: threshold, 155 }, 156 }, 157 }, 158 } 159 160 ctx := context.Background() 161 162 app := NewApp(ctx, config) 163 healthRegistry := health.NewRegistry() 164 app.RegisterHealthChecks(healthRegistry) 165 166 for i := 0; ; i++ { 167 <-time.After(interval) 168 169 status := healthRegistry.CheckStatus() 170 171 if i < threshold-1 { 172 // definitely shouldn't have hit the threshold yet 173 if len(status) != 0 { 174 t.Fatal("expected 1 item in health check results") 175 } 176 continue 177 } 178 if i < threshold+1 { 179 // right on the threshold - don't expect a failure yet 180 continue 181 } 182 183 if len(status) != 1 { 184 t.Fatal("expected 1 item in health check results") 185 } 186 if status[checkedServer.URL] != "downstream service returned unexpected status: 500" { 187 t.Fatal("did not get expected result for health check") 188 } 189 190 break 191 } 192 193 // Signal HTTP handler to start returning 200 194 close(stopFailing) 195 196 <-time.After(2 * interval) 197 198 if len(healthRegistry.CheckStatus()) != 0 { 199 t.Fatal("expected 0 items in health check results") 200 } 201 }