package testhelper import ( "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "runtime" "strings" "sync" log "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitaly/internal/gitaly/config" gitalylog "gitlab.com/gitlab-org/gitaly/internal/log" ) var ( configureOnce sync.Once testDirectory string ) // Configure sets up the global test configuration. On failure, // terminates the program. func Configure() func() { configureOnce.Do(func() { gitalylog.Configure("json", "info") var err error testDirectory, err = ioutil.TempDir("", "gitaly-") if err != nil { log.Fatal(err) } config.Config.Logging.Dir = filepath.Join(testDirectory, "log") if err := os.Mkdir(config.Config.Logging.Dir, 0755); err != nil { os.RemoveAll(testDirectory) log.Fatal(err) } config.Config.Storages = []config.Storage{ {Name: "default", Path: GitlabTestStoragePath()}, } if err := os.Mkdir(config.Config.Storages[0].Path, 0755); err != nil { os.RemoveAll(testDirectory) log.Fatal(err) } config.Config.SocketPath = "/bogus" config.Config.GitlabShell.Dir = "/" config.Config.InternalSocketDir = filepath.Join(testDirectory, "internal-socket") if err := os.Mkdir(config.Config.InternalSocketDir, 0755); err != nil { os.RemoveAll(testDirectory) log.Fatal(err) } config.Config.BinDir = filepath.Join(testDirectory, "bin") if err := os.Mkdir(config.Config.BinDir, 0755); err != nil { os.RemoveAll(testDirectory) log.Fatal(err) } for _, f := range []func() error{ func() error { return ConfigureRuby(&config.Config) }, ConfigureGit, func() error { return config.Config.Validate() }, } { if err := f(); err != nil { os.RemoveAll(testDirectory) log.Fatalf("error configuring tests: %v", err) } } }) return func() { if err := os.RemoveAll(testDirectory); err != nil { log.Fatalf("error removing test directory: %v", err) } } } // ConfigureGit configures git for test purpose func ConfigureGit() error { _, currentFile, _, ok := runtime.Caller(0) if !ok { return fmt.Errorf("could not get caller info") } // Set both GOCACHE and GOPATH to the currently active settings to not // have them be overridden by changing our home directory. default it for _, envvar := range []string{"GOCACHE", "GOPATH"} { cmd := exec.Command("go", "env", envvar) output, err := cmd.Output() if err != nil { return err } err = os.Setenv(envvar, strings.TrimSpace(string(output))) if err != nil { return err } } testHome := filepath.Join(filepath.Dir(currentFile), "testdata/home") // overwrite HOME env variable so user global .gitconfig doesn't influence tests return os.Setenv("HOME", testHome) } // ConfigureRuby configures Ruby settings for test purposes at run time. func ConfigureRuby(cfg *config.Cfg) error { if dir := os.Getenv("GITALY_TEST_RUBY_DIR"); len(dir) > 0 { // Sometimes runtime.Caller is unreliable. This environment variable provides a bypass. cfg.Ruby.Dir = dir } else { _, currentFile, _, ok := runtime.Caller(0) if !ok { return fmt.Errorf("could not get caller info") } cfg.Ruby.Dir = filepath.Join(filepath.Dir(currentFile), "../../ruby") } if err := cfg.ConfigureRuby(); err != nil { log.Fatalf("validate ruby config: %v", err) } return nil } // ConfigureGitalyGit2Go configures the gitaly-git2go command for tests func ConfigureGitalyGit2Go() { buildCommand("gitaly-git2go") } // ConfigureGitalyLfsSmudge configures the gitaly-lfs-smudge command for tests func ConfigureGitalyLfsSmudge() { buildCommand("gitaly-lfs-smudge") } // ConfigureGitalySSH configures the gitaly-ssh command for tests func ConfigureGitalySSH() { buildCommand("gitaly-ssh") } // ConfigureGitalyHooksBinary builds gitaly-hooks command for tests func ConfigureGitalyHooksBinary() { buildCommand("gitaly-hooks") } func buildCommand(cmd string) { if config.Config.BinDir == "" { log.Fatal("config.Config.BinDir must be set") } goBuildArgs := []string{ "build", "-tags", "static,system_libgit2", "-o", filepath.Join(config.Config.BinDir, cmd), fmt.Sprintf("gitlab.com/gitlab-org/gitaly/cmd/%s", cmd), } MustRunCommand(nil, nil, "go", goBuildArgs...) }