Files
weave-scope/probe/appclient/app_client_internal_test.go
Alfonso Acosta c0a672c02a Review feedback
2016-07-01 16:51:57 +00:00

232 lines
5.2 KiB
Go

package appclient
import (
"compress/gzip"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"reflect"
"strings"
"testing"
"time"
"github.com/gorilla/handlers"
"github.com/ugorji/go/codec"
"github.com/weaveworks/scope/common/xfer"
"github.com/weaveworks/scope/report"
"github.com/weaveworks/scope/test"
)
func dummyServer(t *testing.T, expectedToken, expectedID string, expectedVersion string, expectedReport report.Report, done chan struct{}) *httptest.Server {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if have := r.Header.Get("Authorization"); fmt.Sprintf("Scope-Probe token=%s", expectedToken) != have {
t.Errorf("want %q, have %q", expectedToken, have)
}
if have := r.Header.Get(xfer.ScopeProbeIDHeader); expectedID != have {
t.Errorf("want %q, have %q", expectedID, have)
}
if have := r.Header.Get(xfer.ScopeProbeVersionHeader); expectedVersion != have {
t.Errorf("want %q, have %q", expectedID, have)
}
var have report.Report
reader := r.Body
var err error
if strings.Contains(r.Header.Get("Content-Encoding"), "gzip") {
reader, err = gzip.NewReader(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
defer reader.Close()
}
decoder := codec.NewDecoder(reader, &codec.MsgpackHandle{})
if err := decoder.Decode(&have); err != nil {
t.Error(err)
return
}
if !reflect.DeepEqual(expectedReport, have) {
t.Error(test.Diff(expectedReport, have))
return
}
w.WriteHeader(http.StatusOK)
done <- struct{}{}
})
return httptest.NewServer(handlers.CompressHandler(handler))
}
func TestAppClientPublish(t *testing.T) {
var (
token = "abcdefg"
id = "1234567"
version = "0.18"
rpt = report.MakeReport()
done = make(chan struct{}, 10)
)
// marshalling->unmarshaling is not idempotent due to `json:"omitempty"`
// tags, transforming empty slices into nils. So, we make DeepEqual
// happy by setting empty `json:"omitempty"` entries to nil
rpt.Endpoint = report.MakeTopology()
rpt.Process = report.MakeTopology()
rpt.Container = report.MakeTopology()
rpt.ContainerImage = report.MakeTopology()
rpt.Pod = report.MakeTopology()
rpt.Service = report.MakeTopology()
rpt.Deployment = report.MakeTopology()
rpt.ReplicaSet = report.MakeTopology()
rpt.Host = report.MakeTopology()
rpt.Overlay = report.MakeTopology()
rpt.Endpoint.Controls = nil
rpt.Process.Controls = nil
rpt.Container.Controls = nil
rpt.ContainerImage.Controls = nil
rpt.Pod.Controls = nil
rpt.Service.Controls = nil
rpt.Deployment.Controls = nil
rpt.ReplicaSet.Controls = nil
rpt.Host.Controls = nil
rpt.Overlay.Controls = nil
s := dummyServer(t, token, id, version, rpt, done)
defer s.Close()
u, err := url.Parse(s.URL)
if err != nil {
t.Fatal(err)
}
pc := ProbeConfig{
Token: token,
ProbeVersion: version,
ProbeID: id,
Insecure: false,
}
p, err := NewAppClient(pc, u.Host, s.URL, nil)
if err != nil {
t.Fatal(err)
}
defer p.Stop()
// First few reports might be dropped as the client is spinning up.
rp := NewReportPublisher(p, false)
for i := 0; i < 10; i++ {
if err := rp.Publish(rpt); err != nil {
t.Error(err)
}
time.Sleep(10 * time.Millisecond)
}
select {
case <-done:
case <-time.After(100 * time.Millisecond):
t.Error("timeout")
}
}
func TestAppClientDetails(t *testing.T) {
var (
id = "foobarbaz"
version = "imalittleteapot"
want = xfer.Details{ID: id, Version: version}
)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
encoder := codec.NewEncoder(w, &codec.JsonHandle{})
if err := encoder.Encode(want); err != nil {
t.Fatal(err)
}
})
s := httptest.NewServer(handlers.CompressHandler(handler))
defer s.Close()
u, err := url.Parse(s.URL)
if err != nil {
t.Fatal(err)
}
pc := ProbeConfig{
Token: "",
ProbeID: "",
Insecure: false,
}
p, err := NewAppClient(pc, u.Host, s.URL, nil)
if err != nil {
t.Fatal(err)
}
defer p.Stop()
have, err := p.Details()
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(want, have) {
t.Error(test.Diff(want, have))
return
}
}
// Make sure Stopping a client works even if the connection or the remote app
// gets stuck for whatever reason.
// See https://github.com/weaveworks/scope/issues/1576
func TestStop(t *testing.T) {
var (
rpt = report.MakeReport()
stopHanging = make(chan struct{})
receivedReport = make(chan struct{})
)
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
close(receivedReport)
<-stopHanging
})
s := httptest.NewServer(handlers.CompressHandler(handler))
defer s.Close()
u, err := url.Parse(s.URL)
if err != nil {
t.Fatal(err)
}
pc := ProbeConfig{
Token: "",
ProbeID: "",
Insecure: false,
}
p, err := NewAppClient(pc, u.Host, s.URL, nil)
if err != nil {
t.Fatal(err)
}
rp := NewReportPublisher(p, false)
// Make sure the app received our report and is stuck
for done := false; !done; {
select {
case <-receivedReport:
done = true
default:
if err := rp.Publish(rpt); err != nil {
t.Error(err)
}
time.Sleep(10 * time.Millisecond)
}
}
// Close the client while the app is stuck
p.Stop()
// Let the server go so that the test can end
close(stopHanging)
}