package git import ( "io/ioutil" "log" "testing" "time" "github.com/mholt/caddy/middleware/git/gittest" ) // init sets the OS used to fakeOS. func init() { SetOS(gittest.FakeOS) } func check(t *testing.T, err error) { if err != nil { t.Errorf("Error not expected but found %v", err) } } func TestInit(t *testing.T) { err := Init() check(t, err) } func TestHelpers(t *testing.T) { f, err := writeScriptFile([]byte("script")) check(t, err) var b [6]byte _, err = f.Read(b[:]) check(t, err) if string(b[:]) != "script" { t.Errorf("Expected script found %v", string(b[:])) } out, err := runCmdOutput(gitBinary, []string{"-version"}, "") check(t, err) if out != gittest.CmdOutput { t.Errorf("Expected %v found %v", gittest.CmdOutput, out) } err = runCmd(gitBinary, []string{"-version"}, "") check(t, err) wScript := gitWrapperScript() if string(wScript) != expectedWrapperScript { t.Errorf("Expected %v found %v", expectedWrapperScript, string(wScript)) } f, err = writeScriptFile(wScript) check(t, err) repo := &Repo{Host: "github.com", KeyPath: "~/.key"} script := string(bashScript(f.Name(), repo, []string{"clone", "git@github.com/repo/user"})) if script != expectedBashScript { t.Errorf("Expected %v found %v", expectedBashScript, script) } } func TestGit(t *testing.T) { // prepare repos := []*Repo{ nil, &Repo{Path: "gitdir", URL: "success.git"}, } for _, r := range repos { repo := createRepo(r) err := repo.Prepare() check(t, err) } // pull with success logFile := gittest.Open("file") Logger = log.New(logFile, "", 0) tests := []struct { repo *Repo output string }{ { &Repo{Path: "gitdir", URL: "git@github.com:user/repo.git", KeyPath: "~/.key", Then: "echo Hello"}, `git@github.com:user/repo.git pulled. Command echo Hello successful. `, }, { &Repo{Path: "gitdir", URL: "https://github.com/user/repo.git", Then: "echo Hello"}, `https://github.com/user/repo.git pulled. Command echo Hello successful. `, }, { &Repo{URL: "git@github.com:user/repo"}, `git@github.com:user/repo pulled. `, }, } for i, test := range tests { gittest.CmdOutput = test.repo.URL test.repo = createRepo(test.repo) err := test.repo.Prepare() check(t, err) err = test.repo.Pull() check(t, err) out, err := ioutil.ReadAll(logFile) check(t, err) if test.output != string(out) { t.Errorf("Pull with Success %v: Expected %v found %v", i, test.output, string(out)) } } // pull with error repos = []*Repo{ &Repo{Path: "gitdir", URL: "http://github.com:u/repo.git"}, &Repo{Path: "gitdir", URL: "https://github.com/user/repo.git", Then: "echo Hello"}, &Repo{Path: "gitdir"}, &Repo{Path: "gitdir", KeyPath: ".key"}, } gittest.CmdOutput = "git@github.com:u1/repo.git" for i, repo := range repos { repo = createRepo(repo) err := repo.Prepare() if err == nil { t.Errorf("Pull with Error %v: Error expected but not found %v", i, err) continue } expected := "Another git repo 'git@github.com:u1/repo.git' exists at gitdir" if expected != err.Error() { t.Errorf("Pull with Error %v: Expected %v found %v", i, expected, err.Error()) } } // timeout checks timeoutTests := []struct { repo *Repo shouldPull bool }{ {&Repo{Interval: time.Millisecond * 4900}, false}, {&Repo{Interval: time.Millisecond * 1}, false}, {&Repo{Interval: time.Second * 5}, true}, {&Repo{Interval: time.Second * 10}, true}, } for i, r := range timeoutTests { r.repo = createRepo(r.repo) err := r.repo.Prepare() check(t, err) err = r.repo.Pull() check(t, err) before := r.repo.lastPull time.Sleep(r.repo.Interval) err = r.repo.Pull() after := r.repo.lastPull check(t, err) expected := after.After(before) if expected != r.shouldPull { t.Errorf("Pull with Error %v: Expected %v found %v", i, expected, r.shouldPull) } } } func createRepo(r *Repo) *Repo { repo := &Repo{ URL: "git@github.com/user/test", Path: ".", Host: "github.com", Branch: "master", Interval: time.Second * 60, } if r == nil { return repo } if r.Branch != "" { repo.Branch = r.Branch } if r.Host != "" { repo.Branch = r.Branch } if r.Interval != 0 { repo.Interval = r.Interval } if r.KeyPath != "" { repo.KeyPath = r.KeyPath } if r.Path != "" { repo.Path = r.Path } if r.Then != "" { repo.Then = r.Then } if r.URL != "" { repo.URL = r.URL } return repo } var expectedBashScript = `#!/bin/bash mkdir -p ~/.ssh; touch ~/.ssh/known_hosts; ssh-keyscan -t rsa,dsa github.com 2>&1 | sort -u - ~/.ssh/known_hosts > ~/.ssh/tmp_hosts; cat ~/.ssh/tmp_hosts >> ~/.ssh/known_hosts; ` + gittest.TempFileName + ` -i ~/.key clone git@github.com/repo/user; ` var expectedWrapperScript = `#!/bin/bash # The MIT License (MIT) # Copyright (c) 2013 Alvin Abad if [ $# -eq 0 ]; then echo "Git wrapper script that can specify an ssh-key file Usage: git.sh -i ssh-key-file git-command " exit 1 fi # remove temporary file on exit trap 'rm -f /tmp/.git_ssh.$$' 0 if [ "$1" = "-i" ]; then SSH_KEY=$2; shift; shift echo "ssh -i $SSH_KEY \$@" > /tmp/.git_ssh.$$ chmod +x /tmp/.git_ssh.$$ export GIT_SSH=/tmp/.git_ssh.$$ fi # in case the git command is repeated [ "$1" = "git" ] && shift # Run the git command /usr/bin/git "$@" `