Fix up some of the testing

This commit is contained in:
Chris Roberts 2022-10-05 17:21:00 -07:00
parent 6104e29129
commit 6d88f3a54f
14 changed files with 141 additions and 94 deletions

View File

@ -670,6 +670,7 @@ func (b *Basis) Save() (err error) {
if err != nil { if err != nil {
b.logger.Trace("failed to save basis", b.logger.Trace("failed to save basis",
"error", err) "error", err)
return err
} }
b.basis = result.Basis b.basis = result.Basis

View File

@ -165,6 +165,7 @@ func TestRemoveMissingBox(t *testing.T) {
testBoxPath := generateTestBox(t, td, bc.basis) testBoxPath := generateTestBox(t, td, bc.basis)
// Insert test box into the collection // Insert test box into the collection
box, err := bc.Add(path.NewPath(testBoxPath), "test/box", "1.2.3", "", true) box, err := bc.Add(path.NewPath(testBoxPath), "test/box", "1.2.3", "", true)
require.NoError(t, err)
boxPath, _ := box.Directory() boxPath, _ := box.Directory()
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, box) require.NotNil(t, box)

View File

@ -19,7 +19,7 @@ import (
func hashicorpBionicBoxData() *vagrant_server.Box { func hashicorpBionicBoxData() *vagrant_server.Box {
testMetadata, _ := structpb.NewStruct(make(map[string]interface{})) testMetadata, _ := structpb.NewStruct(make(map[string]interface{}))
return &vagrant_server.Box{ return &vagrant_server.Box{
Id: "123", ResourceId: "123",
Provider: "virtualbox", Provider: "virtualbox",
Version: "0.0.282", Version: "0.0.282",
Directory: "/tmp/boxes", Directory: "/tmp/boxes",
@ -32,7 +32,7 @@ func hashicorpBionicBoxData() *vagrant_server.Box {
func testboxBoxData() *vagrant_server.Box { func testboxBoxData() *vagrant_server.Box {
testMetadata, _ := structpb.NewStruct(make(map[string]interface{})) testMetadata, _ := structpb.NewStruct(make(map[string]interface{}))
return &vagrant_server.Box{ return &vagrant_server.Box{
Id: "123", ResourceId: "123",
Provider: "virtualbox", Provider: "virtualbox",
Version: "1.2.3", Version: "1.2.3",
Directory: "/tmp/boxes", Directory: "/tmp/boxes",

View File

@ -237,7 +237,9 @@ func (m *Machine) MachineState() (state *core.MachineState, err error) {
// SetMachineState implements core.Machine // SetMachineState implements core.Machine
func (m *Machine) SetMachineState(state *core.MachineState) (err error) { func (m *Machine) SetMachineState(state *core.MachineState) (err error) {
var st *vagrant_plugin_sdk.Args_Target_Machine_State var st *vagrant_plugin_sdk.Args_Target_Machine_State
mapstructure.Decode(state, &st) if err := mapstructure.Decode(state, &st); err != nil {
return err
}
m.machine.State = st m.machine.State = st
switch st.Id { switch st.Id {

View File

@ -280,8 +280,8 @@ func TestMachineSetState(t *testing.T) {
// Set MachineState // Set MachineState
desiredState := &core.MachineState{ID: tc.id} desiredState := &core.MachineState{ID: tc.id}
tm.SetMachineState(desiredState) tm.SetMachineState(desiredState)
require.Equal(t, tm.machine.State.Id, tc.id) require.Equal(t, tc.id, tm.machine.State.Id)
require.Equal(t, tm.target.State, tc.state) require.Equal(t, tc.state, tm.target.State)
// Ensure new id is save to db // Ensure new id is save to db
dbTarget, err := tm.Client().GetTarget(tm.ctx, dbTarget, err := tm.Client().GetTarget(tm.ctx,
@ -289,10 +289,8 @@ func TestMachineSetState(t *testing.T) {
Target: tm.Ref().(*vagrant_plugin_sdk.Ref_Target), Target: tm.Ref().(*vagrant_plugin_sdk.Ref_Target),
}, },
) )
if err != nil { require.NoError(t, err)
t.Errorf("Failed to get target") require.Equal(t, tc.state, dbTarget.Target.State)
}
require.Equal(t, dbTarget.Target.State, tc.state)
} }
} }

View File

@ -91,9 +91,7 @@ func TestTargetIndexSet(t *testing.T) {
func TestTargetIndexAll(t *testing.T) { func TestTargetIndexAll(t *testing.T) {
tp := TestMinimalProject(t) tp := TestMinimalProject(t)
ti, err := tp.TargetIndex() ti, err := tp.TargetIndex()
if err != nil { require.NoError(t, err)
t.Error(err)
}
// No Targets // No Targets
targets, err := ti.All() targets, err := ti.All()

View File

@ -95,6 +95,7 @@ func TestBasis(t testing.T, opts ...BasisOption) (b *Basis) {
td, err := ioutil.TempDir("", "core") td, err := ioutil.TempDir("", "core")
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { os.RemoveAll(td) }) t.Cleanup(func() { os.RemoveAll(td) })
name := filepath.Base(td)
mkSubdir := func(root, sub string) string { mkSubdir := func(root, sub string) string {
sd := filepath.Join(root, sub) sd := filepath.Join(root, sub)
@ -131,12 +132,12 @@ func TestBasis(t testing.T, opts ...BasisOption) (b *Basis) {
WithFactory(factory), WithFactory(factory),
WithClient(client), WithClient(client),
WithBasisDataDir(projDir), WithBasisDataDir(projDir),
WithBasisRef(&vagrant_plugin_sdk.Ref_Basis{Name: "test-basis"}), WithBasisRef(&vagrant_plugin_sdk.Ref_Basis{Name: name, Path: td}),
} }
b, err = factory.NewBasis("", append(defaultOpts, opts...)...) b, err = factory.NewBasis("", append(defaultOpts, opts...)...)
if err != nil { require.NoError(t, err)
t.Fatal(err)
} require.NoError(t, b.Save())
return return
} }

View File

@ -1,27 +1,39 @@
package core package core
import ( import (
"github.com/mitchellh/go-testing-interface" "io/ioutil"
"os"
"path/filepath"
// "github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk" "github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk"
"github.com/hashicorp/vagrant/internal/plugin" "github.com/hashicorp/vagrant/internal/plugin"
"github.com/mitchellh/go-testing-interface"
"github.com/stretchr/testify/require"
) )
// TestProject returns a fully in-memory and side-effect free Project that // TestProject returns a fully in-memory and side-effect free Project that
// can be used for testing. Additional options can be given to provide your own // can be used for testing. Additional options can be given to provide your own
// factories, configuration, etc. // factories, configuration, etc.
func TestProject(t testing.T, opts ...BasisOption) *Project { func TestProject(t testing.T, opts ...BasisOption) *Project {
path := testTempDir(t)
name := filepath.Base(path)
b := TestBasis(t, opts...) b := TestBasis(t, opts...)
p, err := b.factory.NewProject( p, err := b.factory.NewProject(
[]ProjectOption{ []ProjectOption{
WithBasis(b), WithBasis(b),
WithProjectName("test-project"), WithProjectRef(
&vagrant_plugin_sdk.Ref_Project{
Basis: b.Ref().(*vagrant_plugin_sdk.Ref_Basis),
Name: name,
Path: path,
},
),
}..., }...,
) )
if err != nil { require.NoError(t, err)
t.Fatal(err) require.NoError(t, p.Save())
}
return p return p
} }
@ -29,18 +41,35 @@ func TestProject(t testing.T, opts ...BasisOption) *Project {
// TestMinimalProject uses a minimal basis to setup the most basic project // TestMinimalProject uses a minimal basis to setup the most basic project
// that will work for testing // that will work for testing
func TestMinimalProject(t testing.T) *Project { func TestMinimalProject(t testing.T) *Project {
path := testTempDir(t)
name := filepath.Base(path)
pluginManager := plugin.TestManager(t) pluginManager := plugin.TestManager(t)
b := TestBasis(t, WithPluginManager(pluginManager)) b := TestBasis(t, WithPluginManager(pluginManager))
p, err := b.factory.NewProject( p, err := b.factory.NewProject(
[]ProjectOption{ []ProjectOption{
WithBasis(b), WithBasis(b),
WithProjectName("test-project"), WithProjectRef(
&vagrant_plugin_sdk.Ref_Project{
Basis: b.Ref().(*vagrant_plugin_sdk.Ref_Basis),
Name: name,
Path: path,
},
),
}..., }...,
) )
if err != nil { require.NoError(t, err)
t.Fatal(err) require.NoError(t, p.Save())
}
return p return p
} }
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
}

View File

@ -1,8 +1,8 @@
package core package core
import ( import (
"context"
"fmt" "fmt"
"path/filepath"
"github.com/imdario/mergo" "github.com/imdario/mergo"
@ -11,55 +11,40 @@ import (
"github.com/hashicorp/vagrant-plugin-sdk/core" "github.com/hashicorp/vagrant-plugin-sdk/core"
"github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk" "github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk"
"github.com/hashicorp/vagrant/internal/server/proto/vagrant_server" "github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
"github.com/hashicorp/vagrant/internal/server/ptypes"
"github.com/mitchellh/go-testing-interface" "github.com/mitchellh/go-testing-interface"
"github.com/stretchr/testify/require"
) )
// TestTarget returns a fully in-memory and side-effect free Target that // TestTarget returns a fully in-memory and side-effect free Target that
// can be used for testing. Additional options can be given to provide your own // can be used for testing. Additional options can be given to provide your own
// factories, configuration, etc. // factories, configuration, etc.
func TestTarget(t testing.T, p *Project, st *vagrant_server.Target, opts ...TestTargetOption) (target *Target) { func TestTarget(t testing.T, p *Project, st *vagrant_server.Target, opts ...TestTargetOption) (target *Target) {
testingTarget := ptypes.TestTarget(t, st) if st.Name == "" {
testingTarget.Project = p.Ref().(*vagrant_plugin_sdk.Ref_Project) st.Name = filepath.Base(testTempDir(t))
_, err := p.basis.client.UpsertTarget(
context.Background(),
&vagrant_server.UpsertTargetRequest{
Project: p.Ref().(*vagrant_plugin_sdk.Ref_Project),
Target: testingTarget,
},
)
if err != nil {
t.Fatal(err)
} }
target, err = p.factory.NewTarget( target, err := p.factory.NewTarget(
[]TargetOption{ []TargetOption{
WithProject(p),
WithTargetRef( WithTargetRef(
&vagrant_plugin_sdk.Ref_Target{ &vagrant_plugin_sdk.Ref_Target{
Project: p.Ref().(*vagrant_plugin_sdk.Ref_Project), Project: p.Ref().(*vagrant_plugin_sdk.Ref_Project),
Name: testingTarget.Name, Name: st.Name,
ResourceId: st.ResourceId,
}, },
), ),
}..., }...,
) )
require.NoError(t, err)
if err = p.Reload(); err != nil { require.NoError(t, mergo.Merge(target.target, st))
t.Fatal(err)
}
for _, opt := range opts { for _, opt := range opts {
if oerr := opt(target); oerr != nil { if oerr := opt(target); oerr != nil {
err = multierror.Append(err, oerr) err = multierror.Append(err, oerr)
} }
} }
if err != nil { require.NoError(t, err)
t.Fatal(err) require.NoError(t, target.Save())
} require.NoError(t, p.Reload())
if err = p.Reload(); err != nil {
t.Fatal(err)
}
return return
} }
@ -68,39 +53,20 @@ func TestTarget(t testing.T, p *Project, st *vagrant_server.Target, opts ...Test
// that will work for testing // that will work for testing
func TestMinimalTarget(t testing.T) (target *Target) { func TestMinimalTarget(t testing.T) (target *Target) {
tp := TestMinimalProject(t) tp := TestMinimalProject(t)
_, err := tp.basis.client.UpsertTarget( target, err := tp.factory.NewTarget(
context.Background(),
&vagrant_server.UpsertTargetRequest{
Project: tp.Ref().(*vagrant_plugin_sdk.Ref_Project),
Target: &vagrant_server.Target{
Name: "test-target",
Project: tp.Ref().(*vagrant_plugin_sdk.Ref_Project),
},
},
)
if err != nil {
t.Fatal(err)
}
target, err = tp.factory.NewTarget(
[]TargetOption{ []TargetOption{
WithProject(tp), WithProject(tp),
WithTargetRef( WithTargetRef(
&vagrant_plugin_sdk.Ref_Target{ &vagrant_plugin_sdk.Ref_Target{
Project: tp.Ref().(*vagrant_plugin_sdk.Ref_Project), Project: tp.Ref().(*vagrant_plugin_sdk.Ref_Project),
Name: "test-target", Name: filepath.Base(testTempDir(t)),
}, },
), ),
}..., }...,
) )
require.NoError(t, err)
if err != nil { require.NoError(t, target.Save())
t.Fatal(err) require.NoError(t, tp.Reload())
}
if err = tp.Reload(); err != nil {
t.Fatal(err)
}
return return
} }
@ -111,9 +77,7 @@ func TestMinimalTarget(t testing.T) (target *Target) {
func TestMachine(t testing.T, tp *Project, opts ...TestTargetOption) (machine *Machine) { func TestMachine(t testing.T, tp *Project, opts ...TestTargetOption) (machine *Machine) {
tt := TestTarget(t, tp, &vagrant_server.Target{}) tt := TestTarget(t, tp, &vagrant_server.Target{})
specialized, err := tt.Specialize((*core.Machine)(nil)) specialized, err := tt.Specialize((*core.Machine)(nil))
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
machine = specialized.(*Machine) machine = specialized.(*Machine)
for _, opt := range opts { for _, opt := range opts {
@ -121,9 +85,7 @@ func TestMachine(t testing.T, tp *Project, opts ...TestTargetOption) (machine *M
err = multierror.Append(err, oerr) err = multierror.Append(err, oerr)
} }
} }
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
return return
} }
@ -134,9 +96,8 @@ func TestMinimalMachine(t testing.T) (machine *Machine) {
tp := TestMinimalProject(t) tp := TestMinimalProject(t)
tt := TestTarget(t, tp, &vagrant_server.Target{}) tt := TestTarget(t, tp, &vagrant_server.Target{})
specialized, err := tt.Specialize((*core.Machine)(nil)) specialized, err := tt.Specialize((*core.Machine)(nil))
if err != nil { require.NoError(t, err)
t.Fatal(err)
}
machine = specialized.(*Machine) machine = specialized.(*Machine)
return return
} }

View File

@ -2,6 +2,7 @@ package state
import ( import (
"errors" "errors"
"fmt"
"github.com/go-ozzo/ozzo-validation/v4" "github.com/go-ozzo/ozzo-validation/v4"
"github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk" "github.com/hashicorp/vagrant-plugin-sdk/proto/vagrant_plugin_sdk"
@ -394,7 +395,7 @@ func (s *State) ProjectList() ([]*vagrant_plugin_sdk.Ref_Project, error) {
func (s *State) ProjectFind(p *vagrant_server.Project) (*vagrant_server.Project, error) { func (s *State) ProjectFind(p *vagrant_server.Project) (*vagrant_server.Project, error) {
project, err := s.ProjectFromProtoFuzzy(p) project, err := s.ProjectFromProtoFuzzy(p)
if err != nil { if err != nil {
return nil, saveErrorToStatus("project", err) return nil, lookupErrorToStatus("project", fmt.Errorf("%w (%#v)", err, p))
} }
return project.ToProto(), nil return project.ToProto(), nil

View File

@ -408,6 +408,11 @@ func (s *State) TargetPut(
return nil, saveErrorToStatus("target", ErrMissingProtoParent) return nil, saveErrorToStatus("target", ErrMissingProtoParent)
} }
// NOTE: this does not get set when updating to
// the UNKNOWN value since it's a zero
// value and thus ignored with soft decode
target.State = t.State
if err := s.upsertFull(target); err != nil { if err := s.upsertFull(target); err != nil {
return nil, saveErrorToStatus("target", err) return nil, saveErrorToStatus("target", err)
} }

View File

@ -247,6 +247,26 @@ func TestTarget_Update(t *testing.T) {
require.ErrorContains(result.Error, "ResourceId:") require.ErrorContains(result.Error, "ResourceId:")
}) })
t.Run("Updates the state", func(t *testing.T) {
require, db := requireAndDB(t)
target := Target{
Name: "default",
Project: testProject(t, db),
State: vagrant_server.Operation_NOT_CREATED,
}
result := db.Save(&target)
require.NoError(result.Error)
require.Equal(vagrant_server.Operation_NOT_CREATED, target.State)
target.State = vagrant_server.Operation_UNKNOWN
result = db.Save(&target)
require.NoError(result.Error)
result = db.First(&target, &Target{Model: Model{ID: target.ID}})
require.NoError(result.Error)
require.Equal(vagrant_server.Operation_UNKNOWN, target.State)
})
t.Run("Adds subtarget", func(t *testing.T) { t.Run("Adds subtarget", func(t *testing.T) {
require, db := requireAndDB(t) require, db := requireAndDB(t)
@ -359,7 +379,6 @@ func TestTarget_State(t *testing.T) {
s := TestState(t) s := TestState(t)
defer s.Close() defer s.Close()
// Set
_, err := s.TargetGet(&vagrant_plugin_sdk.Ref_Target{ _, err := s.TargetGet(&vagrant_plugin_sdk.Ref_Target{
ResourceId: "foo", ResourceId: "foo",
}) })
@ -367,6 +386,36 @@ func TestTarget_State(t *testing.T) {
require.Equal(codes.NotFound, status.Code(err)) require.Equal(codes.NotFound, status.Code(err))
}) })
t.Run("Simple update", func(t *testing.T) {
require := require.New(t)
s := TestState(t)
defer s.Close()
resp, err := s.TargetPut(&vagrant_server.Target{
Name: "default",
Project: testProject(t, s.db).ToProtoRef(),
State: vagrant_server.Operation_NOT_CREATED,
})
require.NoError(err)
require.Equal(vagrant_server.Operation_NOT_CREATED, resp.State)
target, err := s.TargetGet(&vagrant_plugin_sdk.Ref_Target{
ResourceId: resp.ResourceId,
})
require.NoError(err)
require.Equal(vagrant_server.Operation_NOT_CREATED, target.State)
target.State = vagrant_server.Operation_UNKNOWN
resp, err = s.TargetPut(target)
require.NoError(err)
require.Equal(vagrant_server.Operation_UNKNOWN, resp.State)
target, err = s.TargetGet(&vagrant_plugin_sdk.Ref_Target{
ResourceId: resp.ResourceId,
})
require.NoError(err)
require.Equal(vagrant_server.Operation_UNKNOWN, target.State)
})
t.Run("Put and Get", func(t *testing.T) { t.Run("Put and Get", func(t *testing.T) {
require := require.New(t) require := require.New(t)

View File

@ -33,7 +33,7 @@ func TestState(t testing.T) *State {
t.Cleanup(func() { t.Cleanup(func() {
t.Log(buf.String()) t.Log(buf.String())
}) })
result, err := New(l, testDB(t)) result, err := New(l, TestDB(t))
require.NoError(t, err) require.NoError(t, err)
return result return result
} }
@ -83,7 +83,7 @@ func TestState(t testing.T) *State {
// return New(hclog.L(), db) // return New(hclog.L(), db)
// } // }
func testDB(t testing.T) *gorm.DB { func TestDB(t testing.T) *gorm.DB {
t.Helper() t.Helper()
db, err := gorm.Open(sqlite.Open(""), &gorm.Config{ db, err := gorm.Open(sqlite.Open(""), &gorm.Config{
@ -106,7 +106,7 @@ func testDB(t testing.T) *gorm.DB {
} }
func requireAndDB(t testing.T) (*require.Assertions, *gorm.DB) { func requireAndDB(t testing.T) (*require.Assertions, *gorm.DB) {
db := testDB(t) db := TestDB(t)
require := require.New(t) require := require.New(t)
if err := db.AutoMigrate(models...); err != nil { if err := db.AutoMigrate(models...); err != nil {
require.NoError(err) require.NoError(err)

View File

@ -13,6 +13,7 @@ import (
"github.com/hashicorp/vagrant/internal/server" "github.com/hashicorp/vagrant/internal/server"
pb "github.com/hashicorp/vagrant/internal/server/proto/vagrant_server" pb "github.com/hashicorp/vagrant/internal/server/proto/vagrant_server"
"github.com/hashicorp/vagrant/internal/server/singleprocess/state"
"github.com/hashicorp/vagrant/internal/serverclient" "github.com/hashicorp/vagrant/internal/serverclient"
) )
@ -26,7 +27,7 @@ func TestServer(t testing.T, opts ...Option) *serverclient.VagrantClient {
// with server.TestServer. It is easier to just use TestServer directly. // with server.TestServer. It is easier to just use TestServer directly.
func TestImpl(t testing.T, opts ...Option) pb.VagrantServer { func TestImpl(t testing.T, opts ...Option) pb.VagrantServer {
impl, err := New(append( impl, err := New(append(
[]Option{WithDB(testDB(t))}, []Option{WithDB(state.TestDB(t))},
opts..., opts...,
)...) )...)
require.NoError(t, err) require.NoError(t, err)
@ -155,7 +156,7 @@ func TestBasis(t testing.T, client pb.VagrantClient, ref *pb.Basis) {
func testDB(t testing.T) *gorm.DB { func testDB(t testing.T) *gorm.DB {
t.Helper() t.Helper()
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{}) db, err := gorm.Open(sqlite.Open("file::memory:"), &gorm.Config{})
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { t.Cleanup(func() {
d, err := db.DB() d, err := db.DB()