This repository has no description
3.5 kB
84 lines
1package main
2
3import (
4 "fmt"
5 "net/http/httptest"
6 "strings"
7 "testing"
8
9 "github.com/bluesky-social/indigo/atproto/syntax"
10 "tangled.org/core/repoident"
11)
12
13var (
14 sha1Oid = strings.Repeat("a", 40)
15 sha256Oid = strings.Repeat("b", 64)
16)
17
18func decodeBody(t *testing.T, body string) (indexRequest, error) {
19 t.Helper()
20 return decodeIndexRequest(httptest.NewRequest("POST", "/admin/enqueueIndex", strings.NewReader(body)))
21}
22
23func TestDecodeIndexRequest_Accepts(t *testing.T) {
24 cases := map[string]struct {
25 name, oid, wantRef string
26 }{
27 "a branch and a sha1": {name: "main", oid: sha1Oid, wantRef: "refs/heads/main"},
28 "HEAD and a sha256": {name: "HEAD", oid: sha256Oid, wantRef: "HEAD"},
29 }
30 for label, tc := range cases {
31 t.Run(label, func(t *testing.T) {
32 req, err := decodeBody(t, fmt.Sprintf(`{"repo":"did:plc:limpet","branches":[{"Name":%q,"Version":%q}]}`, tc.name, tc.oid))
33 if err != nil {
34 t.Fatalf("decodeIndexRequest: %v", err)
35 }
36 if req.Repo.String() != "did:plc:limpet" {
37 t.Errorf("Repo = %q, want did:plc:limpet", req.Repo)
38 }
39 want := indexBranch{Name: branchName(tc.name), Version: objectID(tc.oid)}
40 if len(req.Branches) != 1 || req.Branches[0] != want {
41 t.Errorf("Branches = %v, want %v", req.Branches, want)
42 }
43 if got := req.Branches[0].Name.Ref(); got != tc.wantRef {
44 t.Errorf("Ref = %q, want %q", got, tc.wantRef)
45 }
46 })
47 }
48}
49
50func TestDecodeIndexRequest_RejectsBadRequests(t *testing.T) {
51 cases := map[string]string{
52 "branch name is a git option": fmt.Sprintf(`{"repo":"did:plc:limpet","branches":[{"Name":"-d","Version":%q}]}`, sha1Oid),
53 "version is a git option": `{"repo":"did:plc:limpet","branches":[{"Name":"main","Version":"--upload-pack=touch /tmp/pwned"}]}`,
54 "version is a ref": `{"repo":"did:plc:limpet","branches":[{"Name":"main","Version":"refs/heads/main"}]}`,
55 "version is short hex": `{"repo":"did:plc:limpet","branches":[{"Name":"main","Version":"deadbeef"}]}`,
56 "branch name walks up": fmt.Sprintf(`{"repo":"did:plc:limpet","branches":[{"Name":"../../objects","Version":%q}]}`, sha1Oid),
57 "branch name is a full ref": fmt.Sprintf(`{"repo":"did:plc:limpet","branches":[{"Name":"refs/heads/main","Version":%q}]}`, sha1Oid),
58 "branch name is empty": fmt.Sprintf(`{"repo":"did:plc:limpet","branches":[{"Name":"","Version":%q}]}`, sha1Oid),
59 "repo isn't a did": fmt.Sprintf(`{"repo":"limpet","branches":[{"Name":"main","Version":%q}]}`, sha1Oid),
60 "repo is absent": fmt.Sprintf(`{"branches":[{"Name":"main","Version":%q}]}`, sha1Oid),
61 "branches are absent": `{"repo":"did:plc:limpet"}`,
62 "branches are empty": `{"repo":"did:plc:limpet","branches":[]}`,
63 "unknown field": fmt.Sprintf(`{"repo":"did:plc:limpet","branches":[{"Name":"main","Version":%q}],"shards":3}`, sha1Oid),
64 }
65 for name, body := range cases {
66 t.Run(name, func(t *testing.T) {
67 if _, err := decodeBody(t, body); err == nil {
68 t.Errorf("decodeIndexRequest accepted %s", body)
69 }
70 })
71 }
72}
73
74func TestRepoCloneURL(t *testing.T) {
75 knot, err := repoident.ParseKnotURL("https://knot.oyster.cafe", repoident.RequireHTTPS)
76 if err != nil {
77 t.Fatalf("ParseKnotURL: %v", err)
78 }
79 repo := Repo{Did: "did:plc:limpet", Owner: "did:plc:akshay", Slug: syntax.RecordKey("3kkkkkkkkkkkk"), Knot: knot}
80 const want = "https://knot.oyster.cafe/did:plc:limpet"
81 if got := repo.CloneURL(); got != want {
82 t.Errorf("CloneURL = %q, want %q", got, want)
83 }
84}