From a86ad5d9500b45de432685838a671f6b3d024bf9 Mon Sep 17 00:00:00 2001 From: George Angel Date: Fri, 4 Jan 2019 22:32:53 +0000 Subject: [PATCH] add timeout tests - custom `git` command option - tests on slow running git commands --- cmd/git-sync/main.go | 29 +++++++++++++------------ slow_git.sh | 3 +++ test_e2e.sh | 50 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 13 deletions(-) create mode 100755 slow_git.sh diff --git a/cmd/git-sync/main.go b/cmd/git-sync/main.go index bdf433a..e29f4e5 100644 --- a/cmd/git-sync/main.go +++ b/cmd/git-sync/main.go @@ -75,6 +75,9 @@ var flSSHKnownHosts = flag.Bool("ssh-known-hosts", envBool("GIT_KNOWN_HOSTS", tr var flCookieFile = flag.Bool("cookie-file", envBool("GIT_COOKIE_FILE", false), "use git cookiefile") +var flGitCmd = flag.String("git", envString("GIT_SYNC_GIT", "git"), + "the git command to run (subject to PATH search)") + var log = newLoggerOrDie() func newLoggerOrDie() logr.Logger { @@ -147,8 +150,8 @@ func main() { flag.Usage() os.Exit(1) } - if _, err := exec.LookPath("git"); err != nil { - fmt.Fprintf(os.Stderr, "ERROR: git executable not found: %v\n", err) + if _, err := exec.LookPath(*flGitCmd); err != nil { + fmt.Fprintf(os.Stderr, "ERROR: git executable %q not found: %v\n", *flGitCmd, err) os.Exit(1) } @@ -275,7 +278,7 @@ func updateSymlink(ctx context.Context, gitRoot, link, newDir string) error { log.V(1).Infof("removed %s", currentDir) - _, err := runCommand(ctx, gitRoot, "git", "worktree", "prune") + _, err := runCommand(ctx, gitRoot, *flGitCmd, "worktree", "prune") if err != nil { return err } @@ -291,13 +294,13 @@ func addWorktreeAndSwap(ctx context.Context, gitRoot, dest, branch, rev, hash st log.V(0).Infof("syncing to %s (%s)", rev, hash) // Update from the remote. - if _, err := runCommand(ctx, gitRoot, "git", "fetch", "--tags", "origin", branch); err != nil { + if _, err := runCommand(ctx, gitRoot, *flGitCmd, "fetch", "--tags", "origin", branch); err != nil { return err } // Make a worktree for this exact git hash. worktreePath := path.Join(gitRoot, "rev-"+hash) - _, err := runCommand(ctx, gitRoot, "git", "worktree", "add", worktreePath, "origin/"+branch) + _, err := runCommand(ctx, gitRoot, *flGitCmd, "worktree", "add", worktreePath, "origin/"+branch) if err != nil { return err } @@ -317,7 +320,7 @@ func addWorktreeAndSwap(ctx context.Context, gitRoot, dest, branch, rev, hash st } // Reset the worktree's working copy to the specific rev. - _, err = runCommand(ctx, worktreePath, "git", "reset", "--hard", hash) + _, err = runCommand(ctx, worktreePath, *flGitCmd, "reset", "--hard", hash) if err != nil { return err } @@ -340,7 +343,7 @@ func cloneRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot args = append(args, "--depth", strconv.Itoa(depth)) } args = append(args, repo, gitRoot) - _, err := runCommand(ctx, "", "git", args...) + _, err := runCommand(ctx, "", *flGitCmd, args...) if err != nil { if strings.Contains(err.Error(), "already exists and is not an empty directory") { // Maybe a previous run crashed? Git won't use this dir. @@ -349,7 +352,7 @@ func cloneRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot if err != nil { return err } - _, err = runCommand(ctx, "", "git", args...) + _, err = runCommand(ctx, "", *flGitCmd, args...) if err != nil { return err } @@ -363,7 +366,7 @@ func cloneRepo(ctx context.Context, repo, branch, rev string, depth int, gitRoot } func hashForRev(ctx context.Context, rev, gitRoot string) (string, error) { - output, err := runCommand(ctx, gitRoot, "git", "rev-parse", rev) + output, err := runCommand(ctx, gitRoot, *flGitCmd, "rev-parse", rev) if err != nil { return "", err } @@ -445,7 +448,7 @@ func getRevs(ctx context.Context, localDir, branch, rev string) (string, string, } func remoteHashForRef(ctx context.Context, ref, gitRoot string) (string, error) { - output, err := runCommand(ctx, gitRoot, "git", "ls-remote", "-q", "origin", ref) + output, err := runCommand(ctx, gitRoot, *flGitCmd, "ls-remote", "-q", "origin", ref) if err != nil { return "", err } @@ -485,13 +488,13 @@ func runCommand(ctx context.Context, cwd, command string, args ...string) (strin func setupGitAuth(username, password, gitURL string) error { log.V(1).Infof("setting up the git credential cache") - cmd := exec.Command("git", "config", "--global", "credential.helper", "cache") + cmd := exec.Command(*flGitCmd, "config", "--global", "credential.helper", "cache") output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("error setting up git credentials %v: %s", err, string(output)) } - cmd = exec.Command("git", "credential", "approve") + cmd = exec.Command(*flGitCmd, "credential", "approve") stdin, err := cmd.StdinPipe() if err != nil { return err @@ -551,7 +554,7 @@ func setupGitCookieFile() error { return fmt.Errorf("error: could not find git cookie file: %v", err) } - cmd := exec.Command("git", "config", "--global", "http.cookiefile", pathToCookieFile) + cmd := exec.Command(*flGitCmd, "config", "--global", "http.cookiefile", pathToCookieFile) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("error configuring git cookie file %v: %s", err, string(output)) diff --git a/slow_git.sh b/slow_git.sh new file mode 100755 index 0000000..4e46f7c --- /dev/null +++ b/slow_git.sh @@ -0,0 +1,3 @@ +#!/bin/sh +sleep 1.1 +git "$@" diff --git a/test_e2e.sh b/test_e2e.sh index b281546..a6d744a 100755 --- a/test_e2e.sh +++ b/test_e2e.sh @@ -39,6 +39,12 @@ function assert_file_exists() { fi } +function assert_file_absent() { + if [[ -f "$1" ]]; then + fail "$1 exists" + fi +} + function assert_file_eq() { if [[ $(cat "$1") == "$2" ]]; then return @@ -82,6 +88,7 @@ function GIT_SYNC() { -i \ -u $(id -u):$(id -g) \ -v "$DIR":"$DIR" \ + -v "$(pwd)/slow_git.sh":"/slow_git.sh" \ --rm \ e2e/git-sync:$(make -s version)__$(go env GOOS)_$(go env GOARCH) \ "$@" @@ -93,6 +100,8 @@ function remove_sync_container() { docker rm -f $CONTAINER_NAME >/dev/null 2>&1 } +SLOW_GIT=/slow_git.sh + REPO="$DIR/repo" mkdir "$REPO" @@ -488,5 +497,46 @@ assert_file_eq "$ROOT"/link/file "$TESTCASE 1" # Wrap up pass +# Test sync loop timeout +testcase "sync-loop-timeout" +# First sync +echo "$TESTCASE 1" > "$REPO"/file +git -C "$REPO" commit -qam "$TESTCASE 1" +GIT_SYNC \ + --git=$SLOW_GIT \ + --timeout=1 \ + --logtostderr \ + --v=5 \ + --one-time \ + --repo="$REPO" \ + --root="$ROOT" \ + --dest="link" > "$DIR"/log."$TESTCASE" 2>&1 & +sleep 3 +# check for failure +assert_file_absent "$ROOT"/link/file +# run with slow_git but without timing out +GIT_SYNC \ + --git=$SLOW_GIT \ + --timeout=16 \ + --logtostderr \ + --v=5 \ + --wait=0.1 \ + --repo="$REPO" \ + --root="$ROOT" \ + --dest="link" > "$DIR"/log."$TESTCASE" 2>&1 & +sleep 10 +assert_link_exists "$ROOT"/link +assert_file_exists "$ROOT"/link/file +assert_file_eq "$ROOT"/link/file "$TESTCASE 1" +# Move forward +echo "$TESTCASE 2" > "$REPO"/file +git -C "$REPO" commit -qam "$TESTCASE 2" +sleep 10 +assert_link_exists "$ROOT"/link +assert_file_exists "$ROOT"/link/file +assert_file_eq "$ROOT"/link/file "$TESTCASE 2" +# Wrap up +pass + echo "cleaning up $DIR" rm -rf "$DIR"