Skip to content
quarry Artifact [0190b13f5d]
Login

Artifact [0190b13f5d]

Artifact 0190b13f5df26cdcbf1f759dead1a9c88b563970705b5a3cddf337ec5d267c40:


package api

import (
	"context"
	"errors"
	"net"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

// zit says "cannot connect" for every way an upstream is unreachable.
// The fleet page must say which (bf5fbed5): the host no longer
// resolves, nothing listens, or TLS fails. A pull that failed for
// another reason, or whose upstream answers fine, gets no cause.
func TestADeadMirrorSaysWhyItCannotConnect(t *testing.T) {
	ctx := context.Background()
	cannot := errors.New("zit pull: cannot connect to the peer")

	closed, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	refusedURL := "https://" + closed.Addr().String() + "/x"
	closed.Close()

	selfSigned := httptest.NewTLSServer(http.NotFoundHandler())
	defer selfSigned.Close()
	plain := httptest.NewServer(http.NotFoundHandler())
	defer plain.Close()

	cases := []struct {
		name, url string
		err       error
		hook      string // a stable fragment of the cause, "" for none
	}{
		{"dns", "https://no-such-host.invalid/x", cannot, "does not resolve"},
		{"refused", refusedURL, cannot, "refused"},
		{"tls", selfSigned.URL + "/x", cannot, "TLS with"},
		{"reachable", plain.URL + "/x", cannot, ""},
		{"http status", "https://no-such-host.invalid/x", errors.New("zit pull: the peer answered HTTP 404 (Not Found)"), ""},
		{"no error", "https://no-such-host.invalid/x", nil, ""},
	}
	for _, c := range cases {
		got := connectCause(ctx, c.url, c.err)
		if c.hook == "" && got != "" || c.hook != "" && !strings.Contains(got, c.hook) {
			t.Errorf("FAIL %s: cause %q, want one containing %q", c.name, got, c.hook)
			continue
		}
		t.Logf("ok %s: %q", c.name, got)
	}
}