| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | package proxy
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  | 	"fmt"
 | 
					
						
							|  |  |  | 	"net/http"
 | 
					
						
							|  |  |  | 	"net/http/httptest"
 | 
					
						
							|  |  |  | 	"strings"
 | 
					
						
							|  |  |  | 	"sync/atomic"
 | 
					
						
							|  |  |  | 	"testing"
 | 
					
						
							|  |  |  | 	"time"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 16:12:56 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/dnstest"
 | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/test"
 | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/request"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 	"github.com/mholt/caddy/caddyfile"
 | 
					
						
							| 
									
										
										
										
											2018-06-15 16:12:56 +01:00
										 |  |  | 	"github.com/miekg/dns"
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestStop(t *testing.T) {
 | 
					
						
							|  |  |  | 	config := "proxy . %s {\n health_check /healthcheck:%s %dms \n}"
 | 
					
						
							|  |  |  | 	tests := []struct {
 | 
					
						
							|  |  |  | 		intervalInMilliseconds  int
 | 
					
						
							|  |  |  | 		numHealthcheckIntervals int
 | 
					
						
							|  |  |  | 	}{
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 		{5, 1},
 | 
					
						
							|  |  |  | 		{5, 2},
 | 
					
						
							|  |  |  | 		{5, 3},
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 	for i, test := range tests {
 | 
					
						
							|  |  |  | 		t.Run(fmt.Sprintf("Test %d", i), func(t *testing.T) {
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Set up proxy.
 | 
					
						
							|  |  |  | 			var counter int64
 | 
					
						
							|  |  |  | 			backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
					
						
							|  |  |  | 				r.Body.Close()
 | 
					
						
							|  |  |  | 				atomic.AddInt64(&counter, 1)
 | 
					
						
							|  |  |  | 			}))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			defer backend.Close()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			port := backend.URL[17:] // Remove all crap up to the port
 | 
					
						
							|  |  |  | 			back := backend.URL[7:]  // Remove http://
 | 
					
						
							|  |  |  | 			c := caddyfile.NewDispenser("Testfile", strings.NewReader(fmt.Sprintf(config, back, port, test.intervalInMilliseconds)))
 | 
					
						
							|  |  |  | 			upstreams, err := NewStaticUpstreams(&c)
 | 
					
						
							|  |  |  | 			if err != nil {
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 				t.Errorf("Test %d, expected no error. Got: %s", i, err)
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 			}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Give some time for healthchecks to hit the server.
 | 
					
						
							|  |  |  | 			time.Sleep(time.Duration(test.intervalInMilliseconds*test.numHealthcheckIntervals) * time.Millisecond)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			for _, upstream := range upstreams {
 | 
					
						
							|  |  |  | 				if err := upstream.Stop(); err != nil {
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 					t.Errorf("Test %d, expected no error stopping upstream, got: %s", i, err)
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 				}
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 			counterAfterShutdown := atomic.LoadInt64(&counter)
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// Give some time to see if healthchecks are still hitting the server.
 | 
					
						
							|  |  |  | 			time.Sleep(time.Duration(test.intervalInMilliseconds*test.numHealthcheckIntervals) * time.Millisecond)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 			if counterAfterShutdown == 0 {
 | 
					
						
							|  |  |  | 				t.Errorf("Test %d, Expected healthchecks to hit test server, got none", i)
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 			}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-30 10:13:45 +01:00
										 |  |  | 			// health checks are in a go routine now, so one may well occur after we shutdown,
 | 
					
						
							|  |  |  | 			// but we only ever expect one more
 | 
					
						
							| 
									
										
										
										
											2017-10-15 19:38:39 +02:00
										 |  |  | 			counterAfterWaiting := atomic.LoadInt64(&counter)
 | 
					
						
							|  |  |  | 			if counterAfterWaiting > (counterAfterShutdown + 1) {
 | 
					
						
							|  |  |  | 				t.Errorf("Test %d, expected no more healthchecks after shutdown. got: %d healthchecks after shutdown", i, counterAfterWaiting-counterAfterShutdown)
 | 
					
						
							| 
									
										
										
										
											2017-04-26 10:58:14 +01:00
										 |  |  | 			}
 | 
					
						
							|  |  |  | 		})
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-06-15 16:12:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestProxyRefused(t *testing.T) {
 | 
					
						
							|  |  |  | 	s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
 | 
					
						
							|  |  |  | 		ret := new(dns.Msg)
 | 
					
						
							|  |  |  | 		ret.SetReply(r)
 | 
					
						
							|  |  |  | 		ret.Rcode = dns.RcodeRefused
 | 
					
						
							|  |  |  | 		w.WriteMsg(ret)
 | 
					
						
							|  |  |  | 	})
 | 
					
						
							|  |  |  | 	defer s.Close()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p := NewLookup([]string{s.Addr})
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	state := request.Request{W: &test.ResponseWriter{}, Req: new(dns.Msg)}
 | 
					
						
							|  |  |  | 	state.Req.SetQuestion("example.org.", dns.TypeA)
 | 
					
						
							|  |  |  | 	resp, err := p.Forward(state)
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Fatal("Expected to receive reply, but didn't")
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	if resp.Rcode != dns.RcodeRefused {
 | 
					
						
							|  |  |  | 		t.Errorf("Expected rcode to be %d, got %d", dns.RcodeRefused, resp.Rcode)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 |