blob: 244e98925b404cb056d3c04113e3722f0d2c4bd6 [file] [log] [blame]
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"context"
"fmt"
"net/http/httptest"
"os/exec"
"reflect"
"strings"
"testing"
)
func TestHomepage(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
handleRoot(w, req)
if w.Code != 200 {
t.Fatalf("GET /: want code 200, got %d", w.Code)
}
if hdr := w.Header().Get("Content-Type"); !strings.Contains(hdr, "text/html") {
t.Fatalf("GET /: want html content-type, got %s", hdr)
}
}
func TestDebugWatcher(t *testing.T) {
r := &Repo{path: "build"}
r.setStatus("waiting")
req := httptest.NewRequest("GET", "/debug/watcher/build", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != 200 {
t.Fatalf("GET /: want code 200, got %d", w.Code)
}
body := w.Body.String()
if substr := `watcher status for repo: "build"`; !strings.Contains(body, substr) {
t.Fatalf("GET /debug/watcher/build: want %q in body, got %s", substr, body)
}
if substr := "waiting"; !strings.Contains(body, substr) {
t.Fatalf("GET /debug/watcher/build: want %q in body, got %s", substr, body)
}
}
// fakeCmd records the results of CommandContext and echoes any arguments to
// stdout.
type fakeCmd struct {
Cmd string
Args []string
callCount int
}
func (f *fakeCmd) CommandContext(ctx context.Context, cmd string, args ...string) *exec.Cmd {
f.callCount++
f.Cmd = cmd
f.Args = args
return exec.CommandContext(ctx, "echo", append([]string{cmd}, args...)...)
}
func mustHaveGit(t *testing.T) {
if _, err := exec.LookPath("git"); err != nil {
t.Skip("skipping; git not in PATH")
}
}
func TestRev(t *testing.T) {
mustHaveGit(t)
f := &fakeCmd{}
testHookArchiveCmd = f.CommandContext
defer func() { testHookArchiveCmd = nil }()
r := &Repo{path: "build"}
r.setStatus("waiting")
req := httptest.NewRequest("GET", "/build.tar.gz?rev=example-branch", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != 200 {
t.Fatalf("GET /: want code 200, got %d", w.Code)
}
if f.Cmd != "git" {
t.Fatalf("cmd: want 'git' for cmd, got %s", f.Cmd)
}
wantArgs := []string{"archive", "--format=tgz", "example-branch"}
if !reflect.DeepEqual(f.Args, wantArgs) {
t.Fatalf("cmd: want '%q' for args, got %q", wantArgs, f.Args)
}
}
func TestRevNotFound(t *testing.T) {
mustHaveGit(t)
f := &fakeCmd{}
f2 := &fakeCmd{}
testHookArchiveCmd = f.CommandContext
testHookFetchCmd = f2.CommandContext
defer func() {
testHookArchiveCmd = nil
testHookFetchCmd = nil
}()
r := &Repo{path: "build"}
r.setStatus("waiting")
req := httptest.NewRequest("GET", "/build.tar.gz?rev=example-branch", nil)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if w.Code != 200 {
t.Fatalf("GET /build.tar.gz: want code 200, got %d", w.Code)
}
if f2.callCount != 1 {
t.Fatal("GET /build.tar.gz: want 'git fetch' to be called, wasn't called")
}
wantArgs := []string{"fetch", "origin", "example-branch"}
if !reflect.DeepEqual(f2.Args, wantArgs) {
t.Fatalf("cmd: want '%q' for args, got %q", wantArgs, f2.Args)
}
}
// TestUpdate tests that we link new commits correctly in
// our linked list (parent <=> child) of commits, and update
// the Repo's map of commits correctly.
func TestUpdate(t *testing.T) {
oldNetwork := *network
defer func() {
*network = oldNetwork
}()
*network = false
hash := func(i int) string {
return fmt.Sprintf("abc123%d", i)
}
commit := func(i int) *Commit {
c := &Commit{
Hash: hash(i),
Author: "Sarah Adams <shadams@google.com>",
Date: "Fri, 15 Sep 2017 13:56:53 -0700",
Desc: fmt.Sprintf("CONTRIBUTORS: add person %d.", i),
Files: "CONTRIBUTORS",
}
if i > 0 {
c.Parent = hash(i - 1)
}
return c
}
gitLogFn = func(r *Repo, dir string, args ...string) ([]*Commit, error) {
// We are testing new commits on a non-master branch.
// So, for simplicity, return no new commits on master.
for _, a := range args {
if strings.Contains(a, "origin/master") {
return nil, nil
}
}
var cs []*Commit
for i := 0; i < 5; i++ {
cs = append(cs, commit(i))
}
return cs, nil
}
gitRemotesFn = func(r *Repo) ([]string, error) {
return []string{"origin/master", "origin/other.branch"}, nil
}
repo := newTestRepo()
// Add a known commit on master.
// This commit is HEAD of origin/master when we forked to
// create the 'origin/other.branch' branch.
head := commit(0)
head.Branch = "origin/master"
repo.commits[hash(0)] = head
master := &Branch{
Name: "origin/master",
Head: head,
LastSeen: head,
}
repo.branches["origin/master"] = master
err := repo.update(false)
if err != nil {
t.Fatalf("update: got error %v", err)
}
head = repo.branches["origin/other.branch"].Head
if head.Hash != hash(0) {
t.Fatalf("expected head to have hash %s, got %s.", hash(0), head.Hash)
}
if len(head.children) != 1 {
t.Fatalf("expected head to have 1 child commit, got %d.", len(head.children))
}
for i := 0; i < 5; i++ {
if i != 0 {
if repo.commits[hash(i)].parent == nil {
t.Errorf("expected commit %d to have a parent commit.", i)
}
}
if i != 4 {
if len(repo.commits[hash(i)].children) == 0 {
t.Errorf("expected commit %d to have child commits.", i)
}
}
}
}
func newTestRepo() *Repo {
return &Repo{
path: "",
root: "/usr/local/home/go",
commits: make(map[string]*Commit),
branches: make(map[string]*Branch),
mirror: false,
dash: false,
}
}