mirror of
https://github.com/asdf-vm/asdf.git
synced 2024-12-19 09:55:01 -07:00
feat(golang-rewrite): offline Go tests
Some of the Go tests actually cloned remote repos, which meant slow tests, and tests failures if I was working offline. These changes allow all Go tests to run offline. The test code now clones local Git repos instead of remotes ones. * Add otiai10/copy as a dependency * Create repotest package for test code that needs to work with Git repos * Add back missing test script for execute package * Update git, pluginindex, and plugins package tests so they work offline
This commit is contained in:
parent
2e185a0e5b
commit
f74efbf1bf
3
execute/testdata/script
vendored
Executable file
3
execute/testdata/script
vendored
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo $@
|
@ -5,35 +5,27 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"asdf/repotest"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TODO: Switch to local repo so tests don't go over the network
|
||||
const (
|
||||
testRepo = "https://github.com/Stratus3D/asdf-lua"
|
||||
testPluginName = "lua"
|
||||
)
|
||||
|
||||
func TestPluginClone(t *testing.T) {
|
||||
t.Run("when plugin name is valid but URL is invalid prints an error", func(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
directory := filepath.Join(tempDir, testPluginName)
|
||||
|
||||
plugin := NewRepo(directory)
|
||||
plugin := NewRepo(t.TempDir())
|
||||
err := plugin.Clone("foobar")
|
||||
|
||||
assert.ErrorContains(t, err, "unable to clone plugin: repository not found")
|
||||
})
|
||||
|
||||
t.Run("clones provided Git URL to plugin directory when URL is valid", func(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
directory := filepath.Join(tempDir, testPluginName)
|
||||
|
||||
repoDir := generateRepo(t)
|
||||
directory := t.TempDir()
|
||||
plugin := NewRepo(directory)
|
||||
err := plugin.Clone(testRepo)
|
||||
|
||||
err := plugin.Clone(repoDir)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Assert plugin directory contains Git repo with bin directory
|
||||
@ -42,17 +34,17 @@ func TestPluginClone(t *testing.T) {
|
||||
|
||||
entries, err := os.ReadDir(directory + "/bin")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(entries))
|
||||
assert.Equal(t, 12, len(entries))
|
||||
})
|
||||
}
|
||||
|
||||
func TestPluginHead(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
directory := filepath.Join(tempDir, testPluginName)
|
||||
repoDir := generateRepo(t)
|
||||
directory := t.TempDir()
|
||||
|
||||
plugin := NewRepo(directory)
|
||||
|
||||
err := plugin.Clone(testRepo)
|
||||
err := plugin.Clone(repoDir)
|
||||
assert.Nil(t, err)
|
||||
|
||||
head, err := plugin.Head()
|
||||
@ -61,12 +53,12 @@ func TestPluginHead(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPluginRemoteURL(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
directory := filepath.Join(tempDir, testPluginName)
|
||||
repoDir := generateRepo(t)
|
||||
directory := t.TempDir()
|
||||
|
||||
plugin := NewRepo(directory)
|
||||
|
||||
err := plugin.Clone(testRepo)
|
||||
err := plugin.Clone(repoDir)
|
||||
assert.Nil(t, err)
|
||||
|
||||
url, err := plugin.RemoteURL()
|
||||
@ -75,16 +67,16 @@ func TestPluginRemoteURL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPluginUpdate(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
directory := filepath.Join(tempDir, testPluginName)
|
||||
repoDir := generateRepo(t)
|
||||
directory := t.TempDir()
|
||||
|
||||
plugin := NewRepo(directory)
|
||||
|
||||
err := plugin.Clone(testRepo)
|
||||
err := plugin.Clone(repoDir)
|
||||
assert.Nil(t, err)
|
||||
|
||||
t.Run("returns error when plugin with name does not exist", func(t *testing.T) {
|
||||
nonexistantPath := filepath.Join(tempDir, "nonexistant")
|
||||
nonexistantPath := filepath.Join(directory, "nonexistant")
|
||||
nonexistantPlugin := NewRepo(nonexistantPath)
|
||||
updatedToRef, err := nonexistantPlugin.Update("")
|
||||
|
||||
@ -96,7 +88,7 @@ func TestPluginUpdate(t *testing.T) {
|
||||
|
||||
t.Run("returns error when plugin repo does not exist", func(t *testing.T) {
|
||||
badPluginName := "badplugin"
|
||||
badPluginDir := filepath.Join(tempDir, badPluginName)
|
||||
badPluginDir := filepath.Join(directory, badPluginName)
|
||||
err := os.MkdirAll(badPluginDir, 0o777)
|
||||
assert.Nil(t, err)
|
||||
|
||||
@ -198,3 +190,12 @@ func checkoutPreviousCommit(path string) (string, error) {
|
||||
|
||||
return previousHash.String(), nil
|
||||
}
|
||||
|
||||
func generateRepo(t *testing.T) string {
|
||||
t.Helper()
|
||||
tempDir := t.TempDir()
|
||||
path, err := repotest.GeneratePlugin("dummy_plugin", tempDir, "lua")
|
||||
|
||||
assert.Nil(t, err)
|
||||
return path
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -5,6 +5,7 @@ go 1.21.5
|
||||
require (
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/otiai10/copy v1.14.0
|
||||
github.com/sethvargo/go-envconfig v1.0.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/urfave/cli/v2 v2.27.1
|
||||
@ -35,6 +36,7 @@ require (
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -52,6 +52,10 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
@ -63,7 +63,7 @@ func (p PluginIndex) Refresh() (bool, error) {
|
||||
// directory empty, clone down repo
|
||||
err := p.repo.Clone(p.url)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, fmt.Errorf("unable to initialize index: %w", err)
|
||||
}
|
||||
|
||||
return touchFS(p.directory)
|
||||
@ -90,7 +90,7 @@ func (p PluginIndex) doUpdate() (bool, error) {
|
||||
// commit is
|
||||
_, err := p.repo.Update("")
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, fmt.Errorf("unable to update plugin index: %w", err)
|
||||
}
|
||||
|
||||
// Touch update file
|
||||
|
@ -9,13 +9,15 @@ import (
|
||||
"time"
|
||||
|
||||
"asdf/git"
|
||||
"asdf/repotest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const (
|
||||
realIndexURL = "https://github.com/asdf-vm/asdf-plugins.git"
|
||||
mockIndexURL = "https://github.com/asdf-vm/asdf-plugins.git"
|
||||
badIndexURL = "http://asdf-vm.com/non-existent"
|
||||
fooPluginURL = "http://example.com/foo"
|
||||
elixirPluginURL = "https://github.com/asdf-vm/asdf-elixir.git"
|
||||
erlangPluginURL = "https://github.com/asdf-vm/asdf-erlang.git"
|
||||
)
|
||||
@ -84,15 +86,22 @@ func writeMockPluginFile(dir, pluginName, pluginURL string) error {
|
||||
func TestGetPluginSourceURL(t *testing.T) {
|
||||
t.Run("with Git returns a plugin url when provided name of existing plugin", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, true, 0, &git.Repo{Directory: dir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("elixir")
|
||||
indexDir := filepath.Join(dir, "index")
|
||||
err := os.Mkdir(indexDir, 0o777)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, url, elixirPluginURL)
|
||||
|
||||
repoPath, err := repotest.GeneratePluginIndex(dir)
|
||||
assert.Nil(t, err)
|
||||
|
||||
pluginIndex := New(indexDir, repoPath, true, 0, &git.Repo{Directory: indexDir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("foo")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, url, fooPluginURL)
|
||||
})
|
||||
|
||||
t.Run("returns a plugin url when provided name of existing plugin", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, true, 0, &MockIndex{Directory: dir})
|
||||
pluginIndex := New(dir, mockIndexURL, true, 0, &MockIndex{Directory: dir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("elixir")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, url, elixirPluginURL)
|
||||
@ -100,7 +109,7 @@ func TestGetPluginSourceURL(t *testing.T) {
|
||||
|
||||
t.Run("returns a plugin url when provided name of existing plugin when loading from cache", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
pluginIndex := New(dir, mockIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("elixir")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, url, elixirPluginURL)
|
||||
@ -112,7 +121,7 @@ func TestGetPluginSourceURL(t *testing.T) {
|
||||
|
||||
t.Run("returns an error when given a name that isn't in the index", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
pluginIndex := New(dir, mockIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("foobar")
|
||||
assert.EqualError(t, err, "plugin foobar not found in repository")
|
||||
assert.Equal(t, url, "")
|
||||
@ -130,7 +139,7 @@ func TestGetPluginSourceURL(t *testing.T) {
|
||||
pluginIndex := New(dir, badIndexURL, false, 10, &repo)
|
||||
|
||||
url, err := pluginIndex.GetPluginSourceURL("lua")
|
||||
assert.EqualError(t, err, "unable to clone: repository not found")
|
||||
assert.EqualError(t, err, "unable to update plugin index: unable to clone: repository not found")
|
||||
assert.Equal(t, url, "")
|
||||
})
|
||||
|
||||
@ -138,7 +147,7 @@ func TestGetPluginSourceURL(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, badIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("lua")
|
||||
assert.EqualError(t, err, "unable to clone: repository not found")
|
||||
assert.EqualError(t, err, "unable to initialize index: unable to clone: repository not found")
|
||||
assert.Equal(t, url, "")
|
||||
})
|
||||
}
|
||||
@ -146,10 +155,17 @@ func TestGetPluginSourceURL(t *testing.T) {
|
||||
func TestRefresh(t *testing.T) {
|
||||
t.Run("with Git updates repo when called once", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, false, 0, &git.Repo{Directory: dir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("elixir")
|
||||
indexDir := filepath.Join(dir, "index")
|
||||
err := os.Mkdir(indexDir, 0o777)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, url, elixirPluginURL)
|
||||
|
||||
repoPath, err := repotest.GeneratePluginIndex(dir)
|
||||
assert.Nil(t, err)
|
||||
|
||||
pluginIndex := New(indexDir, repoPath, false, 0, &git.Repo{Directory: indexDir})
|
||||
url, err := pluginIndex.GetPluginSourceURL("foo")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, url, fooPluginURL)
|
||||
|
||||
updated, err := pluginIndex.Refresh()
|
||||
assert.Nil(t, err)
|
||||
@ -158,7 +174,7 @@ func TestRefresh(t *testing.T) {
|
||||
|
||||
t.Run("updates repo when called once", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, false, 0, &MockIndex{Directory: dir})
|
||||
pluginIndex := New(dir, mockIndexURL, false, 0, &MockIndex{Directory: dir})
|
||||
|
||||
updated, err := pluginIndex.Refresh()
|
||||
assert.Nil(t, err)
|
||||
@ -171,7 +187,7 @@ func TestRefresh(t *testing.T) {
|
||||
|
||||
t.Run("does not update index when time has not elaspsed", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
pluginIndex := New(dir, mockIndexURL, false, 10, &MockIndex{Directory: dir})
|
||||
|
||||
// Call Refresh twice, the second call should not perform an update
|
||||
updated, err := pluginIndex.Refresh()
|
||||
@ -185,7 +201,7 @@ func TestRefresh(t *testing.T) {
|
||||
|
||||
t.Run("updates plugin index when time has elaspsed", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, realIndexURL, false, 0, &MockIndex{Directory: dir})
|
||||
pluginIndex := New(dir, mockIndexURL, false, 0, &MockIndex{Directory: dir})
|
||||
|
||||
// Call Refresh twice, the second call should perform an update
|
||||
updated, err := pluginIndex.Refresh()
|
||||
@ -200,10 +216,10 @@ func TestRefresh(t *testing.T) {
|
||||
|
||||
t.Run("returns error when plugin index repo doesn't exist", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
pluginIndex := New(dir, badIndexURL, false, 0, &MockIndex{Directory: dir})
|
||||
|
||||
pluginIndex := New(dir, badIndexURL, false, 0, &MockIndex{Directory: dir})
|
||||
updated, err := pluginIndex.Refresh()
|
||||
assert.EqualError(t, err, "unable to clone: repository not found")
|
||||
assert.EqualError(t, err, "unable to initialize index: unable to clone: repository not found")
|
||||
assert.False(t, updated)
|
||||
})
|
||||
}
|
||||
|
@ -1,28 +1,23 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"asdf/config"
|
||||
"asdf/repotest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TODO: Switch to local repo so tests don't go over the network
|
||||
const (
|
||||
testRepo = "https://github.com/Stratus3D/asdf-lua"
|
||||
testPluginName = "lua"
|
||||
)
|
||||
const testPluginName = "lua"
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
testDataDir := t.TempDir()
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
testRepo, err := installMockPluginRepo(testDataDir, testPluginName)
|
||||
testRepo, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Add(conf, testPluginName, testRepo)
|
||||
@ -93,7 +88,7 @@ func TestAdd(t *testing.T) {
|
||||
|
||||
for _, invalid := range invalids {
|
||||
t.Run(invalid, func(t *testing.T) {
|
||||
err := Add(config.Config{}, invalid, testRepo)
|
||||
err := Add(config.Config{}, invalid, "never-cloned")
|
||||
|
||||
expectedErrMsg := "is invalid. Name may only contain lowercase letters, numbers, '_', and '-'"
|
||||
if !strings.Contains(err.Error(), expectedErrMsg) {
|
||||
@ -107,13 +102,16 @@ func TestAdd(t *testing.T) {
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
|
||||
// Add plugin
|
||||
err := Add(conf, testPluginName, testRepo)
|
||||
repoPath, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Add(conf, testPluginName, repoPath)
|
||||
if err != nil {
|
||||
t.Fatal("Expected to be able to add plugin")
|
||||
}
|
||||
|
||||
// Add it again to trigger error
|
||||
err = Add(conf, testPluginName, testRepo)
|
||||
err = Add(conf, testPluginName, repoPath)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("expected error got nil")
|
||||
@ -136,8 +134,10 @@ func TestAdd(t *testing.T) {
|
||||
t.Run("when plugin name and URL are valid installs plugin", func(t *testing.T) {
|
||||
testDataDir := t.TempDir()
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
pluginPath, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err := Add(conf, testPluginName, testRepo)
|
||||
err = Add(conf, testPluginName, pluginPath)
|
||||
|
||||
assert.Nil(t, err, "Expected to be able to add plugin")
|
||||
|
||||
@ -149,14 +149,17 @@ func TestAdd(t *testing.T) {
|
||||
|
||||
entries, err := os.ReadDir(pluginDir + "/bin")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(entries))
|
||||
assert.Equal(t, 12, len(entries))
|
||||
})
|
||||
|
||||
t.Run("when parameters are valid creates plugin download dir", func(t *testing.T) {
|
||||
testDataDir := t.TempDir()
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
|
||||
err := Add(conf, testPluginName, testRepo)
|
||||
repoPath, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Add(conf, testPluginName, repoPath)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Assert download dir exists
|
||||
@ -170,7 +173,10 @@ func TestRemove(t *testing.T) {
|
||||
testDataDir := t.TempDir()
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
|
||||
err := Add(conf, testPluginName, testRepo)
|
||||
repoPath, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Add(conf, testPluginName, repoPath)
|
||||
assert.Nil(t, err)
|
||||
|
||||
t.Run("returns error when plugin with name does not exist", func(t *testing.T) {
|
||||
@ -197,7 +203,7 @@ func TestRemove(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("removes plugin download dir when passed name of installed plugin", func(t *testing.T) {
|
||||
err := Add(conf, testPluginName, testRepo)
|
||||
err := Add(conf, testPluginName, repoPath)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Remove(conf, testPluginName)
|
||||
@ -214,7 +220,10 @@ func TestUpdate(t *testing.T) {
|
||||
testDataDir := t.TempDir()
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
|
||||
err := Add(conf, testPluginName, testRepo)
|
||||
repoPath, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Add(conf, testPluginName, repoPath)
|
||||
assert.Nil(t, err)
|
||||
|
||||
badPluginName := "badplugin"
|
||||
@ -359,7 +368,7 @@ func TestRunCallback(t *testing.T) {
|
||||
|
||||
testDataDir := t.TempDir()
|
||||
conf := config.Config{DataDir: testDataDir}
|
||||
testRepo, err := installMockPluginRepo(testDataDir, testPluginName)
|
||||
testRepo, err := repotest.GeneratePlugin("dummy_plugin", testDataDir, testPluginName)
|
||||
assert.Nil(t, err)
|
||||
|
||||
err = Add(conf, testPluginName, testRepo)
|
||||
@ -412,125 +421,3 @@ func touchFile(name string) error {
|
||||
}
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
func installMockPluginRepo(dataDir, name string) (string, error) {
|
||||
// Because the legacy dummy plugin directory is relative to the root of this
|
||||
// project I cannot use the usual testing functions to locate it. To
|
||||
// determine the location of it we compute the module root, which also
|
||||
// happens to be the root of the repo.
|
||||
modRootDir, err := moduleRoot()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
location := dataDir + "/repo-" + name
|
||||
|
||||
// Then we specify the path to the dummy plugin relative to the module root
|
||||
err = runCmd("cp", "-r", filepath.Join(modRootDir, "test/fixtures/dummy_plugin"), location)
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
// Definitely some opportunities to refactor here. This code might be
|
||||
// simplified by switching to the Go git library
|
||||
err = runCmd("git", "-C", location, "init", "-q")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "config", "user.name", "\"Test\"")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "config", "user.email", "\"test@example.com\"")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "add", "-A")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "commit", "-q", "-m", fmt.Sprintf("\"asdf %s plugin init\"", name))
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("touch", filepath.Join(location, "README.md"))
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "add", "-A")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "commit", "-q", "-m", fmt.Sprintf("\"asdf %s plugin readme \"", name))
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
// kind of ugly but I want a remote with a valid path so I use the same
|
||||
// location as the remote. Probably should refactor
|
||||
err = runCmd("git", "-C", location, "remote", "add", "origin", location)
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
return location, err
|
||||
}
|
||||
|
||||
func moduleRoot() (string, error) {
|
||||
currentDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return findModuleRoot(currentDir), nil
|
||||
}
|
||||
|
||||
// Taken from https://github.com/golang/go/blob/9e3b1d53a012e98cfd02de2de8b1bd53522464d4/src/cmd/go/internal/modload/init.go#L1504C1-L1522C2 because that function is in an internal module
|
||||
// and I can't rely on it.
|
||||
func findModuleRoot(dir string) (roots string) {
|
||||
if dir == "" {
|
||||
panic("dir not set")
|
||||
}
|
||||
dir = filepath.Clean(dir)
|
||||
|
||||
// Look for enclosing go.mod.
|
||||
for {
|
||||
if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
|
||||
return dir
|
||||
}
|
||||
d := filepath.Dir(dir)
|
||||
if d == dir {
|
||||
break
|
||||
}
|
||||
dir = d
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// helper function to make running commands easier
|
||||
func runCmd(cmdName string, args ...string) error {
|
||||
cmd := exec.Command(cmdName, args...)
|
||||
|
||||
// Capture stdout and stderr
|
||||
var stdout strings.Builder
|
||||
var stderr strings.Builder
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
// If command fails print both stderr and stdout
|
||||
fmt.Println("stdout:", stdout.String())
|
||||
fmt.Println("stderr:", stderr.String())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
200
repotest/repotest.go
Normal file
200
repotest/repotest.go
Normal file
@ -0,0 +1,200 @@
|
||||
// Package repotest contains various test helpers for tests that work with code
|
||||
// relying on plugin Git repos and the asdf plugin index
|
||||
//
|
||||
// Three main actions:
|
||||
//
|
||||
// * Install plugin index repo into asdf (index contains records that point to
|
||||
// local plugins defined by this package)
|
||||
// * Install plugin into asdf data dir
|
||||
// * Create local plugin repo that can be cloned into asdf
|
||||
package repotest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
cp "github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
const fixturesDir = "fixtures"
|
||||
|
||||
// Setup copies all files into place and initializes all repos for any Go test
|
||||
// that needs either plugin repos or the plugin index repo.
|
||||
func Setup(asdfDataDir string) error {
|
||||
if err := InstallPluginIndex(asdfDataDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GeneratePlugin copies in the specified plugin fixture into a test directory
|
||||
// and initializes a Git repo for it so it can be installed by asdf.
|
||||
func GeneratePlugin(fixtureName, asdfDataDir, pluginName string) (string, error) {
|
||||
root, err := getModuleRoot()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
fixturesDir := filepath.Join(asdfDataDir, fixturesDir)
|
||||
return generatePluginInDir(root, fixtureName, fixturesDir, pluginName)
|
||||
}
|
||||
|
||||
// InstallPluginIndex generates and installs a plugin index Git repo inside of
|
||||
// the provided asdf data directory.
|
||||
func InstallPluginIndex(asdfDataDir string) error {
|
||||
root, err := getModuleRoot()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Copy in plugin index
|
||||
source := filepath.Join(root, "test/fixtures/dummy_plugins_repo")
|
||||
return cp.Copy(source, filepath.Join(asdfDataDir, "plugin-index"))
|
||||
}
|
||||
|
||||
// GeneratePluginIndex generates a mock plugin index Git repo inside the given
|
||||
// directory.
|
||||
func GeneratePluginIndex(asdfDataDir string) (string, error) {
|
||||
root, err := getModuleRoot()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Copy in plugin index
|
||||
source := filepath.Join(root, "test/fixtures/dummy_plugins_repo")
|
||||
destination := filepath.Join(asdfDataDir, fixturesDir, "plugin-index")
|
||||
err = cp.Copy(source, destination)
|
||||
if err != nil {
|
||||
return destination, fmt.Errorf("unable to copy in plugin index: %w", err)
|
||||
}
|
||||
|
||||
// Generate git repo for plugin
|
||||
return createGitRepo(destination)
|
||||
}
|
||||
|
||||
func generatePluginInDir(root, fixtureName, outputDir, pluginName string) (string, error) {
|
||||
// Copy in plugin files into output dir
|
||||
pluginPath, err := copyInPlugin(root, fixtureName, outputDir, pluginName)
|
||||
if err != nil {
|
||||
return pluginPath, fmt.Errorf("unable to copy in plugin files: %w", err)
|
||||
}
|
||||
|
||||
// Generate git repo for plugin
|
||||
return createGitRepo(pluginPath)
|
||||
}
|
||||
|
||||
func getModuleRoot() (string, error) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to get current working directory: %w", err)
|
||||
}
|
||||
|
||||
root := findModuleRoot(cwd)
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func createGitRepo(location string) (string, error) {
|
||||
// Definitely some opportunities to refactor here. This code might be
|
||||
// simplified by switching to the Go git library
|
||||
err := runCmd("git", "-C", location, "init", "-q")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "config", "user.name", "\"Test\"")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "config", "user.email", "\"test@example.com\"")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "add", "-A")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "commit", "-q", "-m", "init repo")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("touch", filepath.Join(location, "README.md"))
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "add", "-A")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
err = runCmd("git", "-C", location, "commit", "-q", "-m", "add readme")
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
// kind of ugly but I want a remote with a valid path so I use the same
|
||||
// location as the remote. Probably should refactor
|
||||
err = runCmd("git", "-C", location, "remote", "add", "origin", location)
|
||||
if err != nil {
|
||||
return location, err
|
||||
}
|
||||
|
||||
return location, err
|
||||
}
|
||||
|
||||
func copyInPlugin(root, name, destination, newName string) (string, error) {
|
||||
source := filepath.Join(root, "test/fixtures/", name)
|
||||
dest := filepath.Join(destination, newName)
|
||||
return dest, cp.Copy(source, dest)
|
||||
}
|
||||
|
||||
// Taken from https://github.com/golang/go/blob/9e3b1d53a012e98cfd02de2de8b1bd53522464d4/src/cmd/go/internal/modload/init.go#L1504C1-L1522C2 because that function is in an internal module
|
||||
// and I can't rely on it.
|
||||
func findModuleRoot(dir string) (roots string) {
|
||||
if dir == "" {
|
||||
panic("dir not set")
|
||||
}
|
||||
dir = filepath.Clean(dir)
|
||||
|
||||
// Look for enclosing go.mod.
|
||||
for {
|
||||
if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
|
||||
return dir
|
||||
}
|
||||
d := filepath.Dir(dir)
|
||||
if d == dir {
|
||||
break
|
||||
}
|
||||
dir = d
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// helper function to make running commands easier
|
||||
func runCmd(cmdName string, args ...string) error {
|
||||
cmd := exec.Command(cmdName, args...)
|
||||
|
||||
// Capture stdout and stderr
|
||||
var stdout strings.Builder
|
||||
var stderr strings.Builder
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
// If command fails print both stderr and stdout
|
||||
fmt.Println("stdout:", stdout.String())
|
||||
fmt.Println("stderr:", stderr.String())
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user