package state import ( "bytes" "io/ioutil" "os" "path/filepath" "github.com/glebarez/sqlite" "github.com/hashicorp/go-hclog" "github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk" "github.com/hashicorp/vagrant/internal/server" "github.com/hashicorp/vagrant/internal/server/proto/vagrant_server" "github.com/imdario/mergo" "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" "gorm.io/gorm" "gorm.io/gorm/logger" ) // TestState returns an initialized State for testing. func TestState(t testing.T) *State { t.Helper() var buf bytes.Buffer l := hclog.New(&hclog.LoggerOptions{ Name: "test", Level: hclog.Trace, Output: &buf, IncludeLocation: true, }) t.Cleanup(func() { t.Log(buf.String()) }) result, err := New(l, testDB(t)) require.NoError(t, err) return result } // // TestStateReinit reinitializes the state by pretending to restart // // the server with the database associated with this state. This can be // // used to test index init logic. // // // // This safely copies the entire DB so the old state can continue running // // with zero impact. // func TestStateReinit(t testing.T, s *State) *State { // // Copy the old database to a brand new path // td, err := ioutil.TempDir("", "test") // require.NoError(t, err) // t.Cleanup(func() { os.RemoveAll(td) }) // path := filepath.Join(td, "test.db") // // Start db copy // require.NoError(t, s.db.View(func(tx *bolt.Tx) error { // return tx.CopyFile(path, 0600) // })) // // Open the new DB // db, err := bolt.Open(path, 0600, nil) // require.NoError(t, err) // t.Cleanup(func() { db.Close() }) // // Init new state // result, err := New(hclog.L(), db) // require.NoError(t, err) // return result // } // // TestStateRestart closes the given state and restarts it against the // // same DB file. Unlike TestStateReinit, this does not copy the data and // // the old state is no longer usable. // func TestStateRestart(t testing.T, s *State) (*State, error) { // path := s.db.Path() // require.NoError(t, s.Close()) // // Open the new DB // db, err := bolt.Open(path, 0600, nil) // require.NoError(t, err) // t.Cleanup(func() { db.Close() }) // // Init new state // return New(hclog.L(), db) // } func testDB(t testing.T) *gorm.DB { t.Helper() db, err := gorm.Open(sqlite.Open(""), &gorm.Config{ Logger: logger.Default.LogMode(logger.Silent), }) require.NoError(t, err) t.Cleanup(func() { dbconn, err := db.DB() if err == nil { dbconn.Close() } }) return db } // TestBasis creates the basis in the DB. func testBasis(t testing.T, s *State) *vagrant_plugin_sdk.Ref_Basis { t.Helper() td := testTempDir(t) name := filepath.Base(td) b := &Basis{ Name: &name, Path: &td, } result := s.db.Save(b) require.NoError(t, result.Error) return b.ToProtoRef() } func testProject(t testing.T, s *State) *vagrant_plugin_sdk.Ref_Project { t.Helper() basisRef := testBasis(t, s) b, err := s.BasisFromProtoRef(basisRef) require.NoError(t, err) td := testTempDir(t) name := filepath.Base(td) p := &Project{ Name: &name, Path: &td, Basis: b, } result := s.db.Save(p) require.NoError(t, result.Error) return p.ToProtoRef() } func testRunner(t testing.T, s *State, src *vagrant_server.Runner) *vagrant_server.Runner { t.Helper() if src == nil { src = &vagrant_server.Runner{} } id, err := server.Id() require.NoError(t, err) base := &vagrant_server.Runner{Id: id} require.NoError(t, mergo.Merge(src, base)) var runner Runner require.NoError(t, s.decode(src, &runner)) result := s.db.Save(&runner) require.NoError(t, result.Error) return runner.ToProto() } func testJob(t testing.T, src *vagrant_server.Job) *vagrant_server.Job { t.Helper() require.NoError(t, mergo.Merge(src, &vagrant_server.Job{ TargetRunner: &vagrant_server.Ref_Runner{ Target: &vagrant_server.Ref_Runner_Any{ Any: &vagrant_server.Ref_RunnerAny{}, }, }, DataSource: &vagrant_server.Job_DataSource{ Source: &vagrant_server.Job_DataSource_Local{ Local: &vagrant_server.Job_Local{}, }, }, Operation: &vagrant_server.Job_Noop_{ Noop: &vagrant_server.Job_Noop{}, }, }, )) return src } func testTempDir(t testing.T) string { t.Helper() dir, err := ioutil.TempDir("", "vagrant-test") require.NoError(t, err) t.Cleanup(func() { os.RemoveAll(dir) }) return dir }