Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135package api
import ( "context" "encoding/json" "errors" "net/http" "net/url" "strings" "sync" "testing"
"tangled.org/core/api/org_tangled")
type stubRunner struct { mu sync.Mutex calls []string out string err error}
func (r *stubRunner) Run(_ context.Context, _ string, _ []string, name string, args ...string) (string, error) { r.mu.Lock() defer r.mu.Unlock() r.calls = append(r.calls, name+" "+strings.Join(args, " ")) return r.out, r.err}
func (r *stubRunner) LookPath(string) (string, error) { return "/usr/bin/git", nil }
func TestRepoNameFromURL(t *testing.T) { tests := []struct { url string want string wantErr string }{ {"https://example.com/alice/repo.git", "repo", ""}, {"https://example.com/alice/repo", "repo", ""}, {"https://example.com/alice/repo/", "repo", ""}, {"https://example.com/repo.git", "repo", ""}, {"https://example.com/alice/repo.git/", "repo", ""}, {"ssh://git@example.com/alice/repo.git", "repo", ""}, {"http://example.com/alice/repo", "repo", ""}, {"https://example.com/", "", "must name a repository path"}, } for _, tt := range tests { got, err := RepoNameFromURL(tt.url) if tt.wantErr != "" { if err == nil || !strings.Contains(err.Error(), tt.wantErr) { t.Fatalf("RepoNameFromURL(%q) = %q, %v; want error containing %q", tt.url, got, err, tt.wantErr) } continue } if err != nil { t.Fatalf("RepoNameFromURL(%q): %v", tt.url, err) } if got != tt.want { t.Fatalf("RepoNameFromURL(%q) = %q, want %q", tt.url, got, tt.want) } }}
func TestDescribeSource(t *testing.T) { const path = "/xrpc/" + org_tangled.TempMigratorDescribeSourceNSID const symref = "ref: refs/heads/main\tHEAD\n1a2b3c4d5e6f\tHEAD\n"
t.Run("needs the same auth as every other method", func(t *testing.T) { ts := setupTestServer(t) rec := ts.do(t, "GET", path+"?sourceUrl=https://example.com/a/repo.git", "", nil) if rec.Code != http.StatusForbidden { t.Fatalf("want 403, got %d", rec.Code) } })
t.Run("missing sourceUrl is an InvalidRequest", func(t *testing.T) { ts := setupTestServer(t) rec := ts.do(t, "GET", path, ts.token(t, ts.alice, org_tangled.TempMigratorDescribeSourceNSID), nil) if rec.Code != http.StatusBadRequest || !strings.Contains(rec.Body.String(), "InvalidRequest") { t.Fatalf("want 400 InvalidRequest, got %d (%s)", rec.Code, rec.Body.String()) } })
t.Run("a url the importer would refuse is InvalidSource", func(t *testing.T) { ts := setupTestServer(t) for _, bad := range []string{ "http://example.com/a/repo.git", // not https "https://alice:secret@example.com/a/repo.git", // credentials "https://example.com/a/repo.git?ref=main", // query "https://example.com", // no repository path } { rec := ts.do(t, "GET", path+"?sourceUrl="+url.QueryEscape(bad), ts.token(t, ts.alice, org_tangled.TempMigratorDescribeSourceNSID), nil) if rec.Code != http.StatusBadRequest || !strings.Contains(rec.Body.String(), "InvalidSource") { t.Fatalf("%s: want 400 InvalidSource, got %d (%s)", bad, rec.Code, rec.Body.String()) } } })
t.Run("a repository that cannot be reached is UnreachableSource", func(t *testing.T) { ts := setupTestServer(t) runner := &stubRunner{err: errors.New("exit status 128 (output: fatal: could not read from remote)")} ts.server.gitRunner = runner rec := ts.do(t, "GET", path+"?sourceUrl="+url.QueryEscape("https://example.com/a/repo.git"), ts.token(t, ts.alice, org_tangled.TempMigratorDescribeSourceNSID), nil) if rec.Code != http.StatusBadRequest || !strings.Contains(rec.Body.String(), "UnreachableSource") { t.Fatalf("want 400 UnreachableSource, got %d (%s)", rec.Code, rec.Body.String()) } })
t.Run("success answers with the derived name and the remote default branch", func(t *testing.T) { ts := setupTestServer(t) runner := &stubRunner{out: symref} ts.server.gitRunner = runner source := "https://example.com/alice/repo.git" rec := ts.do(t, "GET", path+"?sourceUrl="+url.QueryEscape(source), ts.token(t, ts.alice, org_tangled.TempMigratorDescribeSourceNSID), nil) if rec.Code != http.StatusOK { t.Fatalf("want 200, got %d (%s)", rec.Code, rec.Body.String()) } var out org_tangled.TempMigratorDescribeSource_Output if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil { t.Fatal(err) } if out.Name != "repo" || out.DefaultBranch != "main" { t.Fatalf("output = %+v, want name repo and defaultBranch main", out) } runner.mu.Lock() defer runner.mu.Unlock() if len(runner.calls) != 1 || !strings.Contains(runner.calls[0], "--symref "+source) { t.Fatalf("git calls = %v, want one ls-remote --symref against the source url", runner.calls) } })}