1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
4.7 KiB
Go

package cluster
import (
"encoding/json"
"errors"
"io"
"net/http"
"net/http/httptest"
"reflect"
"testing"
"time"
)
func Test_AddressProviderString(t *testing.T) {
a := []string{"a", "b", "c"}
p := NewAddressProviderString(a)
b, err := p.Lookup()
if err != nil {
t.Fatalf("failed to lookup addresses: %s", err.Error())
}
if !reflect.DeepEqual(a, b) {
t.Fatalf("failed to get correct addresses")
}
}
func Test_NewBootstrapper(t *testing.T) {
bs := NewBootstrapper(nil, 1, nil)
if bs == nil {
t.Fatalf("failed to create a simple Bootstrapper")
}
}
func Test_BootstrapperBootDoneImmediately(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("client made HTTP request")
}))
done := func() bool {
return true
}
p := NewAddressProviderString([]string{ts.URL})
bs := NewBootstrapper(p, 1, nil)
if err := bs.Boot("node1", "192.168.1.1:1234", done, 10*time.Second); err != nil {
t.Fatalf("failed to boot: %s", err)
}
}
func Test_BootstrapperBootTimeout(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusServiceUnavailable)
}))
done := func() bool {
return false
}
p := NewAddressProviderString([]string{ts.URL})
bs := NewBootstrapper(p, 1, nil)
bs.Interval = time.Second
err := bs.Boot("node1", "192.168.1.1:1234", done, 5*time.Second)
if err == nil {
t.Fatalf("no error returned from timed-out boot")
}
if !errors.Is(err, ErrBootTimeout) {
t.Fatalf("wrong error returned")
}
}
func Test_BootstrapperBootSingleNotify(t *testing.T) {
tsNotified := false
var body map[string]string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/join" {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
tsNotified = true
b, err := io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
if err := json.Unmarshal(b, &body); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
}))
n := -1
done := func() bool {
n++
if n == 5 {
return true
}
return false
}
p := NewAddressProviderString([]string{ts.URL})
bs := NewBootstrapper(p, 1, nil)
bs.Interval = time.Second
err := bs.Boot("node1", "192.168.1.1:1234", done, 60*time.Second)
if err != nil {
t.Fatalf("failed to boot: %s", err)
}
if tsNotified != true {
t.Fatalf("notify target not contacted")
}
if got, exp := body["id"], "node1"; got != exp {
t.Fatalf("wrong node ID supplied, exp %s, got %s", exp, got)
}
if got, exp := body["addr"], "192.168.1.1:1234"; got != exp {
t.Fatalf("wrong address supplied, exp %s, got %s", exp, got)
}
}
func Test_BootstrapperBootSingleNotifyAuth(t *testing.T) {
tsNotified := false
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth()
if !ok {
t.Fatalf("request did not have Basic Auth credentials")
}
if username != "username1" || password != "password1" {
t.Fatalf("bad Basic Auth credentials received (%s, %s", username, password)
}
if r.URL.Path == "/join" {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
tsNotified = true
}))
n := -1
done := func() bool {
n++
if n == 5 {
return true
}
return false
}
p := NewAddressProviderString([]string{ts.URL})
bs := NewBootstrapper(p, 1, nil)
bs.SetBasicAuth("username1", "password1")
bs.Interval = time.Second
err := bs.Boot("node1", "192.168.1.1:1234", done, 60*time.Second)
if err != nil {
t.Fatalf("failed to boot: %s", err)
}
if tsNotified != true {
t.Fatalf("notify target not contacted")
}
}
func Test_BootstrapperBootMultiNotify(t *testing.T) {
ts1Join := false
ts1Notified := false
ts1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/join" {
ts1Join = true
w.WriteHeader(http.StatusServiceUnavailable)
return
}
ts1Notified = true
}))
ts2Join := false
ts2Notified := false
ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/join" {
ts2Join = true
w.WriteHeader(http.StatusServiceUnavailable)
return
}
ts2Notified = true
}))
n := -1
done := func() bool {
n++
if n == 5 {
return true
}
return false
}
p := NewAddressProviderString([]string{ts1.URL, ts2.URL})
bs := NewBootstrapper(p, 2, nil)
bs.Interval = time.Second
err := bs.Boot("node1", "192.168.1.1:1234", done, 60*time.Second)
if err != nil {
t.Fatalf("failed to boot: %s", err)
}
if ts1Join != true || ts2Join != true {
t.Fatalf("all join targets not contacted")
}
if ts1Notified != true || ts2Notified != true {
t.Fatalf("all notify targets not contacted")
}
}