2014-05-22 22:37:19 +04:00
|
|
|
package pkg
|
2014-05-15 09:20:40 +04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2014-05-29 22:03:15 +04:00
|
|
|
"math"
|
2014-05-15 09:20:40 +04:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
2014-05-29 22:03:15 +04:00
|
|
|
"time"
|
2014-05-15 09:20:40 +04:00
|
|
|
)
|
|
|
|
|
2014-05-29 22:03:15 +04:00
|
|
|
func TestExpBackoff(t *testing.T) {
|
|
|
|
duration := time.Millisecond
|
|
|
|
max := time.Hour
|
|
|
|
for i := 0; i < math.MaxUint16; i++ {
|
|
|
|
duration = expBackoff(duration, max)
|
|
|
|
if duration < 0 {
|
|
|
|
t.Fatalf("duration too small: %v %v", duration, i)
|
|
|
|
}
|
|
|
|
if duration > max {
|
|
|
|
t.Fatalf("duration too large: %v %v", duration, i)
|
|
|
|
}
|
|
|
|
}
|
2014-05-15 09:20:40 +04:00
|
|
|
}
|
|
|
|
|
2014-05-16 07:38:50 +04:00
|
|
|
// Test exponential backoff and that it continues retrying if a 5xx response is
|
|
|
|
// received
|
2014-05-22 22:37:19 +04:00
|
|
|
func TestGetURLExpBackOff(t *testing.T) {
|
2014-05-29 22:03:15 +04:00
|
|
|
var expBackoffTests = []struct {
|
|
|
|
count int
|
|
|
|
body string
|
|
|
|
}{
|
|
|
|
{0, "number of attempts: 0"},
|
|
|
|
{1, "number of attempts: 1"},
|
|
|
|
{2, "number of attempts: 2"},
|
|
|
|
}
|
2014-05-21 21:13:20 +04:00
|
|
|
client := NewHttpClient()
|
|
|
|
|
2014-05-15 09:20:40 +04:00
|
|
|
for i, tt := range expBackoffTests {
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
count := 0
|
|
|
|
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
if count == tt.count {
|
|
|
|
io.WriteString(w, fmt.Sprintf("number of attempts: %d", count))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
count++
|
|
|
|
http.Error(w, "", 500)
|
|
|
|
})
|
|
|
|
ts := httptest.NewServer(mux)
|
|
|
|
defer ts.Close()
|
2014-05-16 02:40:06 +04:00
|
|
|
|
2014-06-27 01:58:32 +04:00
|
|
|
data, err := client.GetRetry(ts.URL)
|
2014-05-15 09:20:40 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Test case %d produced error: %v", i, err)
|
|
|
|
}
|
2014-05-16 02:40:06 +04:00
|
|
|
|
2014-05-15 09:20:40 +04:00
|
|
|
if count != tt.count {
|
|
|
|
t.Errorf("Test case %d failed: %d != %d", i, count, tt.count)
|
|
|
|
}
|
2014-05-16 02:40:06 +04:00
|
|
|
|
2014-05-15 09:20:40 +04:00
|
|
|
if string(data) != tt.body {
|
|
|
|
t.Errorf("Test case %d failed: %s != %s", i, tt.body, data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-16 02:40:06 +04:00
|
|
|
|
|
|
|
// Test that it stops retrying if a 4xx response comes back
|
2014-05-22 22:37:19 +04:00
|
|
|
func TestGetURL4xx(t *testing.T) {
|
2014-05-21 21:13:20 +04:00
|
|
|
client := NewHttpClient()
|
2014-05-16 02:40:06 +04:00
|
|
|
retries := 0
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
retries++
|
|
|
|
http.Error(w, "", 404)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
2014-06-27 01:58:32 +04:00
|
|
|
_, err := client.GetRetry(ts.URL)
|
2014-05-16 02:40:06 +04:00
|
|
|
if err == nil {
|
2014-05-21 21:13:20 +04:00
|
|
|
t.Errorf("Incorrect result\ngot: %s\nwant: %s", err.Error(), "Not found. HTTP status code: 404")
|
2014-05-16 02:40:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if retries > 1 {
|
|
|
|
t.Errorf("Number of retries:\n%d\nExpected number of retries:\n%s", retries, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test that it fetches and returns user-data just fine
|
2014-05-22 22:37:19 +04:00
|
|
|
func TestGetURL2xx(t *testing.T) {
|
2014-05-16 02:40:06 +04:00
|
|
|
var cloudcfg = `
|
|
|
|
#cloud-config
|
|
|
|
coreos:
|
|
|
|
oem:
|
|
|
|
id: test
|
|
|
|
name: CoreOS.box for Test
|
|
|
|
version-id: %VERSION_ID%+%BUILD_ID%
|
|
|
|
home-url: https://github.com/coreos/coreos-cloudinit
|
|
|
|
bug-report-url: https://github.com/coreos/coreos-cloudinit
|
|
|
|
update:
|
|
|
|
reboot-strategy: best-effort
|
|
|
|
`
|
|
|
|
|
2014-05-21 21:13:20 +04:00
|
|
|
client := NewHttpClient()
|
2014-05-16 02:40:06 +04:00
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprint(w, cloudcfg)
|
|
|
|
}))
|
|
|
|
defer ts.Close()
|
|
|
|
|
2014-06-27 01:58:32 +04:00
|
|
|
data, err := client.GetRetry(ts.URL)
|
2014-05-16 02:40:06 +04:00
|
|
|
if err != nil {
|
|
|
|
t.Errorf("Incorrect result\ngot: %v\nwant: %v", err, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
if string(data) != cloudcfg {
|
|
|
|
t.Errorf("Incorrect result\ngot: %s\nwant: %s", string(data), cloudcfg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test attempt to fetching using malformed URL
|
2014-05-22 22:37:19 +04:00
|
|
|
func TestGetMalformedURL(t *testing.T) {
|
2014-05-21 21:13:20 +04:00
|
|
|
client := NewHttpClient()
|
|
|
|
|
2014-05-16 02:40:06 +04:00
|
|
|
var tests = []struct {
|
|
|
|
url string
|
|
|
|
want string
|
|
|
|
}{
|
2014-05-21 21:13:20 +04:00
|
|
|
{"boo", "URL boo does not have a valid HTTP scheme. Skipping."},
|
|
|
|
{"mailto://boo", "URL mailto://boo does not have a valid HTTP scheme. Skipping."},
|
|
|
|
{"ftp://boo", "URL ftp://boo does not have a valid HTTP scheme. Skipping."},
|
|
|
|
{"", "URL is empty. Skipping."},
|
2014-05-16 02:40:06 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
2014-06-27 01:58:32 +04:00
|
|
|
_, err := client.GetRetry(test.url)
|
2014-05-17 00:57:58 +04:00
|
|
|
if err == nil || err.Error() != test.want {
|
2014-05-16 02:40:06 +04:00
|
|
|
t.Errorf("Incorrect result\ngot: %v\nwant: %v", err, test.want)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|