internal/gitpin/gitpin_test.go

v1.40.1
gitbay/internal/gitpin/gitpin_test.go history · blame · raw

110 lines · 4121 bytes

  1package gitpin
  2
  3import (
  4	"context"
  5	"net"
  6	"net/url"
  7	"slices"
  8	"strings"
  9	"testing"
 10)
 11
 12func answer(ips ...string) Lookup {
 13	return func(context.Context, string) ([]net.IP, error) {
 14		var out []net.IP
 15		for _, s := range ips {
 16			out = append(out, net.ParseIP(s))
 17		}
 18		return out, nil
 19	}
 20}
 21
 22func TestResolve(t *testing.T) {
 23	ctx := context.Background()
 24	r, err := Resolve(ctx, answer("203.0.113.5"), "https://git.example/x.git", false)
 25	if err != nil || r.URL.Hostname() != "git.example" || len(r.IPs) != 1 {
 26		t.Fatalf("public: %+v %v", r, err)
 27	}
 28	if _, err := Resolve(ctx, answer("203.0.113.5", "10.0.0.7"), "https://git.example/x.git", false); err == nil || !strings.Contains(err.Error(), "10.0.0.7") {
 29		t.Fatalf("private: %v", err)
 30	}
 31	if _, err := Resolve(ctx, answer("10.0.0.7"), "https://git.example/x.git", true); err != nil {
 32		t.Fatalf("allow_local: %v", err)
 33	}
 34	// An empty resolve list would leave curl to resolve the host itself.
 35	if _, err := Resolve(ctx, answer(), "https://git.example/x.git", true); err == nil || !strings.Contains(err.Error(), "no address") {
 36		t.Fatalf("empty answer: %v", err)
 37	}
 38	for _, raw := range []string{"git://git.example/x.git", "ssh://git.example/x.git", "file:///etc"} {
 39		_, err := Resolve(ctx, func(context.Context, string) ([]net.IP, error) {
 40			t.Fatalf("looked up a host for %s", raw)
 41			return nil, nil
 42		}, raw, true)
 43		if err == nil || !strings.Contains(err.Error(), "not http or https") {
 44			t.Errorf("%s: %v", raw, err)
 45		}
 46	}
 47}
 48
 49// Numeric hosts other than a dotted quad are refused before any lookup:
 50// curl reads them as addresses the check never saw.
 51func TestResolveRefusesOddNumericHosts(t *testing.T) {
 52	never := func(_ context.Context, host string) ([]net.IP, error) {
 53		t.Fatalf("looked up %s", host)
 54		return nil, nil
 55	}
 56	for _, host := range []string{"127.1", "2130706433", "0x7f.1", "0x7F000001", "017700000001", "127.0.0.01", "127.0.0.1."} {
 57		if _, err := Resolve(context.Background(), never, "http://"+host+"/x.git", true); err == nil || !strings.Contains(err.Error(), "numeric address") {
 58			t.Errorf("%s: %v", host, err)
 59		}
 60	}
 61	// Names with a numeric label, and real literals, still pass.
 62	for _, host := range []string{"1.example", "0x7f.example", "203.0.113.5", "[2001:db8::1]"} {
 63		if _, err := Resolve(context.Background(), answer("203.0.113.5"), "http://"+host+"/x.git", false); err != nil {
 64			t.Errorf("%s: %v", host, err)
 65		}
 66	}
 67}
 68
 69func TestArgs(t *testing.T) {
 70	u, _ := url.Parse("https://git.example/x.git")
 71	got := Remote{u, []net.IP{net.ParseIP("203.0.113.5"), net.ParseIP("2001:db8::1")}}.Args()
 72	want := []string{"-c", "http.followRedirects=false",
 73		"-c", "http.curloptResolve=git.example:443:203.0.113.5,[2001:db8::1]",
 74		"-c", "http.curloptResolve=*:443:203.0.113.5,[2001:db8::1]"}
 75	if !slices.Equal(got, want) {
 76		t.Fatalf("https: %q", got)
 77	}
 78	u, _ = url.Parse("http://git.example:8080/x.git")
 79	if got := (Remote{u, []net.IP{net.ParseIP("203.0.113.5")}}).Args(); got[3] != "http.curloptResolve=git.example:8080:203.0.113.5" ||
 80		got[5] != "http.curloptResolve=*:8080:203.0.113.5" {
 81		t.Fatalf("http with port: %q", got)
 82	}
 83	// An address literal is its own resolution; there is nothing to pin.
 84	u, _ = url.Parse("https://203.0.113.5/x.git")
 85	if got := (Remote{u, []net.IP{net.ParseIP("203.0.113.5")}}).Args(); !slices.Equal(got, []string{"-c", "http.followRedirects=false"}) {
 86		t.Fatalf("literal: %q", got)
 87	}
 88}
 89
 90func TestEnv(t *testing.T) {
 91	want := []string{"GIT_TERMINAL_PROMPT=0", "HOME=/srv/gitbay",
 92		"GIT_CONFIG_NOSYSTEM=1", "GIT_CONFIG_GLOBAL=/dev/null"}
 93	if got := Env("/srv/gitbay"); !slices.Equal(got, want) {
 94		t.Fatalf("Env = %q", got)
 95	}
 96}
 97
 98func TestVersionOK(t *testing.T) {
 99	for _, s := range []string{"git version 2.37.0", "git version 2.47.3", "git version 2.39.5 (Apple Git-154)",
100		"git version 2.45.2.windows.1", "git version 3.0.0\n"} {
101		if err := VersionOK(s); err != nil {
102			t.Errorf("%q: %v", s, err)
103		}
104	}
105	for _, s := range []string{"git version 2.36.9", "git version 1.99.0", "git version 2", "nonsense", ""} {
106		if err := VersionOK(s); err == nil {
107			t.Errorf("%q accepted", s)
108		}
109	}
110}