-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhttps_test.go
More file actions
115 lines (105 loc) · 3.95 KB
/
https_test.go
File metadata and controls
115 lines (105 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package main
import (
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
)
// newTestDestination returns a *Destination wired to the given URL with a
// label so log calls inside HTTPS don't panic. The Scheme/Host/Port fields
// aren't read by HTTPS itself (it uses dest.URL), but they're populated for
// consistency with what NewDestination would produce.
func newTestDestination(t *testing.T, url string) *Destination {
t.Helper()
t.Cleanup(func() { drainQueue(t) })
drainQueue(t)
return &Destination{
Label: "test",
URL: url,
Protocol: "tcp",
Scheme: "http",
Host: "example.com",
Port: 80,
}
}
func TestHTTPS_Returns200(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
t.Cleanup(srv.Close)
dest := newTestDestination(t, srv.URL)
if !HTTPS(dest) {
t.Errorf("HTTPS(2xx) = false; want true")
}
}
// TestHTTPS_Returns500ButReportsSuccess documents that HTTPS does not check
// the response status code, so a 5xx response still returns true. The Go
// stdlib http.Get only returns an error for transport-level failures (DNS,
// dial, TLS, etc.), not for HTTP error statuses.
//
// Refs #7 — flip when fixed: once HTTPS checks status codes, a 5xx response
// should return false. To flip this test then, change `want true` to
// `want false` and update the test name.
func TestHTTPS_Returns500ButReportsSuccess(t *testing.T) {
cases := []struct {
name string
status int
}{
{name: "internal_server_error", status: http.StatusInternalServerError},
{name: "bad_gateway", status: http.StatusBadGateway},
{name: "service_unavailable", status: http.StatusServiceUnavailable},
{name: "not_found", status: http.StatusNotFound},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(tc.status)
}))
t.Cleanup(srv.Close)
dest := newTestDestination(t, srv.URL)
if !HTTPS(dest) {
t.Errorf("HTTPS(%d) = false; want true (current buggy behavior — #7: no status-code check)", tc.status)
}
})
}
}
// TestHTTPS_FollowsRedirects documents that HTTPS follows redirects (up to
// Go's default of 10 hops) without restriction. A check tool that silently
// follows a redirect to a different host can mask the very routing /
// availability issues it's meant to detect.
//
// Refs #15 — flip when fixed: once HTTPS disables redirect following (or
// records the redirect chain), this test should assert that the destination
// behind a 3xx is NOT considered reachable, or that the redirect target was
// recorded.
func TestHTTPS_FollowsRedirects(t *testing.T) {
var finalHits int32
final := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
atomic.AddInt32(&finalHits, 1)
w.WriteHeader(http.StatusOK)
}))
t.Cleanup(final.Close)
redirector := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, final.URL, http.StatusFound)
}))
t.Cleanup(redirector.Close)
dest := newTestDestination(t, redirector.URL)
if !HTTPS(dest) {
t.Errorf("HTTPS(redirect) = false; want true (current buggy behavior — #15: redirects are followed)")
}
if got := atomic.LoadInt32(&finalHits); got != 1 {
t.Errorf("final server hit count = %d; want 1 (current buggy behavior — #15: redirects are followed)", got)
}
}
// TestHTTPS_DialFailureReturnsFalse pins the only error path HTTPS currently
// surfaces: a transport-level dial failure. This is the one input where the
// current implementation behaves correctly, so the assertion is `want false`
// outright.
func TestHTTPS_DialFailureReturnsFalse(t *testing.T) {
// 127.0.0.1:1 is a port that's vanishingly unlikely to have a
// listener; the connection refuses immediately on Linux.
dest := newTestDestination(t, "http://127.0.0.1:1/")
if HTTPS(dest) {
t.Errorf("HTTPS(unreachable) = true; want false")
}
}