// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package core import ( "archive/tar" "context" "io" "io/ioutil" "os" "path/filepath" "testing" "github.com/hashicorp/go-hclog" "github.com/hashicorp/vagrant-plugin-sdk/helper/path" "github.com/hashicorp/vagrant/internal/plugin" "github.com/stretchr/testify/require" ) func seedDB(t *testing.T, basis *Basis) { box1 := newFullBox(t, hashicorpBionicBoxData(), basis) box1.Save() box2 := newFullBox(t, testboxBoxData(), basis) box2.Save() } func newBoxCollection(t *testing.T) *BoxCollection { pluginManager := plugin.NewManager( context.Background(), nil, hclog.New(&hclog.LoggerOptions{}), ) basis := TestBasis(t, WithPluginManager(pluginManager)) seedDB(t, basis) td, err := ioutil.TempDir(basis.dir.DataDir().String(), "boxes") t.Cleanup(func() { os.RemoveAll(td) }) require.NoError(t, err) return &BoxCollection{ basis: basis, directory: td, logger: hclog.New(&hclog.LoggerOptions{}), } } func generateTestBox(t *testing.T, path string, basis *Basis) string { metafile := filepath.Join(path, "box", "metadata.json") os.Mkdir(filepath.Dir(metafile), 0755) data := []byte("{\"provider\":\"virtualbox\"}") err := os.WriteFile(metafile, data, 0644) require.NoError(t, err) outputPath := filepath.Join(path, "output", "box") os.Mkdir(filepath.Dir(outputPath), 0755) tarFile, err := os.Create(outputPath) require.NoError(t, err) defer tarFile.Close() tw := tar.NewWriter(tarFile) defer tw.Close() file, err := os.Open(metafile) require.NoError(t, err) defer file.Close() info, err := file.Stat() require.NoError(t, err) header, err := tar.FileInfoHeader(info, info.Name()) require.NoError(t, err) err = tw.WriteHeader(header) require.NoError(t, err) _, err = io.Copy(tw, file) require.NoError(t, err) return outputPath } func TestAddErrors(t *testing.T) { bc := newBoxCollection(t) td, err := ioutil.TempDir("/tmp", "box") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(td) }) _, err = bc.Add(path.NewPath("/path/that/doesntexist"), "test", "1.2.3", "", true) require.Error(t, err) _, err = bc.Add(path.NewPath(td), "test/box", "1.2.3", "", false) require.Error(t, err) } func TestAddNoProviders(t *testing.T) { bc := newBoxCollection(t) td, err := ioutil.TempDir("/tmp", "box") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(td) }) testBoxPath := generateTestBox(t, td, bc.basis) box, err := bc.Add(path.NewPath(testBoxPath), "test/box", "1.2.3", "", true) require.NoError(t, err) require.NotNil(t, box) } func TestAddWithProviders(t *testing.T) { bc := newBoxCollection(t) td, err := ioutil.TempDir("/tmp", "box") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(td) }) testBoxPath := generateTestBox(t, td, bc.basis) box, err := bc.Add(path.NewPath(testBoxPath), "test/box", "1.2.3", "", true, "virtualbox", "vmware") require.NoError(t, err) require.NotNil(t, box) } func TestAddBadProviders(t *testing.T) { bc := newBoxCollection(t) td, err := ioutil.TempDir("/tmp", "box") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(td) }) testBoxPath := generateTestBox(t, td, bc.basis) _, err = bc.Add(path.NewPath(testBoxPath), "test/box", "1.2.4", "", true, "vmware") require.Error(t, err) } func TestAll(t *testing.T) { bc := newBoxCollection(t) boxes, err := bc.All() require.NoError(t, err) require.Equal(t, len(boxes), 2) } func TestFind(t *testing.T) { bc := newBoxCollection(t) boxes, err := bc.Find("test/box", "1.2.3") require.NoError(t, err) require.NotNil(t, boxes) boxes, err = bc.Find("test/box", "1.2.3", "virtualbox") require.NoError(t, err) require.NotNil(t, boxes) boxes, err = bc.Find("test/box", "1.2.3", "idontexist") require.NoError(t, err) require.Nil(t, boxes) boxes, err = bc.Find("test/box", "9.9.9", "virtualbox") require.NoError(t, err) require.Nil(t, boxes) boxes, err = bc.Find("test/box", "9.9.9") require.NoError(t, err) require.Nil(t, boxes) boxes, err = bc.Find("test/box", "1.2.3", "vmware", "virtualbox") require.NoError(t, err) require.NotNil(t, boxes) } func TestRemoveMissingBox(t *testing.T) { // Create initial box collection bc := newBoxCollection(t) td, err := ioutil.TempDir("/tmp", "box") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(td) }) testBoxPath := generateTestBox(t, td, bc.basis) // Insert test box into the collection box, err := bc.Add(path.NewPath(testBoxPath), "test/box", "1.2.3", "", true) require.NoError(t, err) boxPath, _ := box.Directory() require.NoError(t, err) require.NotNil(t, box) // Create new box collection to verify test box is still accessible bc, err = NewBoxCollection(bc.basis, bc.directory, bc.logger) require.NoError(t, err) boxes, err := bc.Find("test/box", "1.2.3") require.NoError(t, err) require.NotNil(t, boxes) // Remove box os.RemoveAll(boxPath.String()) // Create new box collection to verify test box is no longer accessible bc, err = NewBoxCollection(bc.basis, bc.directory, bc.logger) require.NoError(t, err) boxes, err = bc.Find("test/box", "1.2.3") require.NoError(t, err) require.Nil(t, boxes) }