main 33a243c

hub_test.go RawHistoryFolder

1// SPDX-License-Identifier: MIT
2
3package registryproxy
4
5import (
6	"bytes"
7	"encoding/json"
8	"net/http/httptest"
9	"os"
10	"os/exec"
11	"strings"
12	"testing"
13
14	"github.com/bnema/zerowrap"
15)
16
17// An opt-in manual check using curl against a real local HTTP listener, with
18// Docker Hub as upstream. No daemon is required.
19func TestDockerHubCurl(t *testing.T) {
20	if os.Getenv("ERMITE_RUNNER_IT_REGISTRY") != "1" {
21		t.Skip("set ERMITE_RUNNER_IT_REGISTRY=1 for live Docker Hub curl check")
22	}
23	var logs bytes.Buffer
24	p, err := New(Config{Dir: t.TempDir(), Max: 64 << 20, Log: zerowrap.New(zerowrap.Config{Level: "debug", Format: "json", Output: &logs})})
25	if err != nil {
26		t.Fatal(err)
27	}
28	srv := httptest.NewServer(p)
29	defer srv.Close()
30	curl := func(path string) []byte {
31		t.Helper()
32		out, err := exec.Command("curl", "--max-time", "20", "-fsS", "-H", "Accept: application/vnd.oci.image.index.v1+json, application/vnd.oci.image.manifest.v1+json", srv.URL+path).CombinedOutput()
33		if err != nil {
34			t.Fatalf("curl %s: %v: %s", path, err, out)
35		}
36		t.Logf("curl %s: HTTP 200, %d bytes", path, len(out))
37		return out
38	}
39	var idx struct {
40		Manifests []struct {
41			Digest   string
42			Platform struct{ Architecture, OS string }
43		}
44	}
45	b := curl("/v2/library/alpine/manifests/3")
46	if err := json.Unmarshal(b, &idx); err != nil {
47		t.Fatal(err)
48	}
49	if !bytes.Equal(b, curl("/v2/library/alpine/manifests/3")) {
50		t.Fatal("tag changed during check")
51	}
52	var digest string
53	for _, m := range idx.Manifests {
54		if m.Platform.Architecture == "amd64" && m.Platform.OS == "linux" {
55			digest = m.Digest
56			break
57		}
58	}
59	if !validDigest(digest) {
60		t.Fatal("no linux/amd64 manifest")
61	}
62	var manifest struct{ Config struct{ Digest string } }
63	if err := json.Unmarshal(curl("/v2/library/alpine/manifests/"+digest), &manifest); err != nil {
64		t.Fatal(err)
65	}
66	if !validDigest(manifest.Config.Digest) {
67		t.Fatal("no config blob")
68	}
69	path := "/v2/library/alpine/blobs/" + manifest.Config.Digest
70	first := curl(path)
71	second := curl(path)
72	if !bytes.Equal(first, second) {
73		t.Fatal("blob differs")
74	}
75	all := logs.String()
76	t.Log(all)
77	if !strings.Contains(all, `"hit":true`) || strings.Count(all, `"message":"registry blob"`) != 1 {
78		t.Fatal("missing cache hits or repeated blob miss")
79	}
80}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 11

↑↓ moveenter openesc close