209 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package consul
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	consul "github.com/hashicorp/consul/api"
 | 
						|
	"github.com/micro/go-micro/registry"
 | 
						|
)
 | 
						|
 | 
						|
type mockRegistry struct {
 | 
						|
	body   []byte
 | 
						|
	status int
 | 
						|
	err    error
 | 
						|
	url    string
 | 
						|
}
 | 
						|
 | 
						|
func encodeData(obj interface{}) ([]byte, error) {
 | 
						|
	buf := bytes.NewBuffer(nil)
 | 
						|
	enc := json.NewEncoder(buf)
 | 
						|
	if err := enc.Encode(obj); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return buf.Bytes(), nil
 | 
						|
}
 | 
						|
 | 
						|
func newMockServer(rg *mockRegistry, l net.Listener) error {
 | 
						|
	mux := http.NewServeMux()
 | 
						|
	mux.HandleFunc(rg.url, func(w http.ResponseWriter, r *http.Request) {
 | 
						|
		if rg.err != nil {
 | 
						|
			http.Error(w, rg.err.Error(), 500)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		w.WriteHeader(rg.status)
 | 
						|
		w.Write(rg.body)
 | 
						|
	})
 | 
						|
	return http.Serve(l, mux)
 | 
						|
}
 | 
						|
 | 
						|
func newConsulTestRegistry(r *mockRegistry) (*consulRegistry, func()) {
 | 
						|
	l, err := net.Listen("tcp", "localhost:0")
 | 
						|
	if err != nil {
 | 
						|
		// blurgh?!!
 | 
						|
		panic(err.Error())
 | 
						|
	}
 | 
						|
	cfg := consul.DefaultConfig()
 | 
						|
	cfg.Address = l.Addr().String()
 | 
						|
 | 
						|
	go newMockServer(r, l)
 | 
						|
 | 
						|
	var cr = &consulRegistry{
 | 
						|
		config:      cfg,
 | 
						|
		Address:     []string{cfg.Address},
 | 
						|
		opts:        registry.Options{},
 | 
						|
		register:    make(map[string]uint64),
 | 
						|
		lastChecked: make(map[string]time.Time),
 | 
						|
		queryOptions: &consul.QueryOptions{
 | 
						|
			AllowStale: true,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	cr.Client()
 | 
						|
 | 
						|
	return cr, func() {
 | 
						|
		l.Close()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func newServiceList(svc []*consul.ServiceEntry) []byte {
 | 
						|
	bts, _ := encodeData(svc)
 | 
						|
	return bts
 | 
						|
}
 | 
						|
 | 
						|
func TestConsul_GetService_WithError(t *testing.T) {
 | 
						|
	cr, cl := newConsulTestRegistry(&mockRegistry{
 | 
						|
		err: errors.New("client-error"),
 | 
						|
		url: "/v1/health/service/service-name",
 | 
						|
	})
 | 
						|
	defer cl()
 | 
						|
 | 
						|
	if _, err := cr.GetService("test-service"); err == nil {
 | 
						|
		t.Fatalf("Expected error not to be `nil`")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestConsul_GetService_WithHealthyServiceNodes(t *testing.T) {
 | 
						|
	// warning is still seen as healthy, critical is not
 | 
						|
	svcs := []*consul.ServiceEntry{
 | 
						|
		newServiceEntry(
 | 
						|
			"node-name-1", "node-address-1", "service-name", "v1.0.0",
 | 
						|
			[]*consul.HealthCheck{
 | 
						|
				newHealthCheck("node-name-1", "service-name", "passing"),
 | 
						|
				newHealthCheck("node-name-1", "service-name", "warning"),
 | 
						|
			},
 | 
						|
		),
 | 
						|
		newServiceEntry(
 | 
						|
			"node-name-2", "node-address-2", "service-name", "v1.0.0",
 | 
						|
			[]*consul.HealthCheck{
 | 
						|
				newHealthCheck("node-name-2", "service-name", "passing"),
 | 
						|
				newHealthCheck("node-name-2", "service-name", "warning"),
 | 
						|
			},
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	cr, cl := newConsulTestRegistry(&mockRegistry{
 | 
						|
		status: 200,
 | 
						|
		body:   newServiceList(svcs),
 | 
						|
		url:    "/v1/health/service/service-name",
 | 
						|
	})
 | 
						|
	defer cl()
 | 
						|
 | 
						|
	svc, err := cr.GetService("service-name")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal("Unexpected error", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if exp, act := 1, len(svc); exp != act {
 | 
						|
		t.Fatalf("Expected len of svc to be `%d`, got `%d`.", exp, act)
 | 
						|
	}
 | 
						|
 | 
						|
	if exp, act := 2, len(svc[0].Nodes); exp != act {
 | 
						|
		t.Fatalf("Expected len of nodes to be `%d`, got `%d`.", exp, act)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestConsul_GetService_WithUnhealthyServiceNode(t *testing.T) {
 | 
						|
	// warning is still seen as healthy, critical is not
 | 
						|
	svcs := []*consul.ServiceEntry{
 | 
						|
		newServiceEntry(
 | 
						|
			"node-name-1", "node-address-1", "service-name", "v1.0.0",
 | 
						|
			[]*consul.HealthCheck{
 | 
						|
				newHealthCheck("node-name-1", "service-name", "passing"),
 | 
						|
				newHealthCheck("node-name-1", "service-name", "warning"),
 | 
						|
			},
 | 
						|
		),
 | 
						|
		newServiceEntry(
 | 
						|
			"node-name-2", "node-address-2", "service-name", "v1.0.0",
 | 
						|
			[]*consul.HealthCheck{
 | 
						|
				newHealthCheck("node-name-2", "service-name", "passing"),
 | 
						|
				newHealthCheck("node-name-2", "service-name", "critical"),
 | 
						|
			},
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	cr, cl := newConsulTestRegistry(&mockRegistry{
 | 
						|
		status: 200,
 | 
						|
		body:   newServiceList(svcs),
 | 
						|
		url:    "/v1/health/service/service-name",
 | 
						|
	})
 | 
						|
	defer cl()
 | 
						|
 | 
						|
	svc, err := cr.GetService("service-name")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal("Unexpected error", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if exp, act := 1, len(svc); exp != act {
 | 
						|
		t.Fatalf("Expected len of svc to be `%d`, got `%d`.", exp, act)
 | 
						|
	}
 | 
						|
 | 
						|
	if exp, act := 1, len(svc[0].Nodes); exp != act {
 | 
						|
		t.Fatalf("Expected len of nodes to be `%d`, got `%d`.", exp, act)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestConsul_GetService_WithUnhealthyServiceNodes(t *testing.T) {
 | 
						|
	// warning is still seen as healthy, critical is not
 | 
						|
	svcs := []*consul.ServiceEntry{
 | 
						|
		newServiceEntry(
 | 
						|
			"node-name-1", "node-address-1", "service-name", "v1.0.0",
 | 
						|
			[]*consul.HealthCheck{
 | 
						|
				newHealthCheck("node-name-1", "service-name", "passing"),
 | 
						|
				newHealthCheck("node-name-1", "service-name", "critical"),
 | 
						|
			},
 | 
						|
		),
 | 
						|
		newServiceEntry(
 | 
						|
			"node-name-2", "node-address-2", "service-name", "v1.0.0",
 | 
						|
			[]*consul.HealthCheck{
 | 
						|
				newHealthCheck("node-name-2", "service-name", "passing"),
 | 
						|
				newHealthCheck("node-name-2", "service-name", "critical"),
 | 
						|
			},
 | 
						|
		),
 | 
						|
	}
 | 
						|
 | 
						|
	cr, cl := newConsulTestRegistry(&mockRegistry{
 | 
						|
		status: 200,
 | 
						|
		body:   newServiceList(svcs),
 | 
						|
		url:    "/v1/health/service/service-name",
 | 
						|
	})
 | 
						|
	defer cl()
 | 
						|
 | 
						|
	svc, err := cr.GetService("service-name")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal("Unexpected error", err)
 | 
						|
	}
 | 
						|
 | 
						|
	if exp, act := 1, len(svc); exp != act {
 | 
						|
		t.Fatalf("Expected len of svc to be `%d`, got `%d`.", exp, act)
 | 
						|
	}
 | 
						|
 | 
						|
	if exp, act := 0, len(svc[0].Nodes); exp != act {
 | 
						|
		t.Fatalf("Expected len of nodes to be `%d`, got `%d`.", exp, act)
 | 
						|
	}
 | 
						|
}
 |