command: Allow tests to run to completion without panics or hangs

There are still 160 test failures as of this commit, but at least the test
program can run to completion and list out all the failures.
This commit is contained in:
Martin Atkins 2018-09-30 09:29:51 -07:00
parent d446d32d96
commit b0016e9cf6
12 changed files with 50 additions and 7 deletions

View File

@ -163,6 +163,7 @@ func (b *Local) contextFromPlanFile(pf *planfile.Reader, opts terraform.ContextO
errSummary,
fmt.Sprintf("Failed to read plan from plan file: %s.", err),
))
return nil, snap, diags
}
variables := terraform.InputValues{}

View File

@ -137,6 +137,18 @@ func (c *ApplyCommand) Run(args []string) int {
"Failed to read plan from plan file",
fmt.Sprintf("Cannot read the plan from the given plan file: %s.", err),
))
c.showDiagnostics(diags)
return 1
}
if plan.Backend.Config == nil {
// Should never happen; always indicates a bug in the creation of the plan file
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to read plan from plan file",
fmt.Sprintf("The given plan file does not have a valid backend configuration. This is a bug in the Terraform command that generated this plan file."),
))
c.showDiagnostics(diags)
return 1
}
be, beDiags = c.BackendForPlan(plan.Backend)
}

View File

@ -108,6 +108,7 @@ func TestApply_lockedState(t *testing.T) {
// test apply with locked state, waiting for unlock
func TestApply_lockedStateWait(t *testing.T) {
t.Fatalf("FIXME: this test seems to be making the test program prematurely exit")
statePath := testTempFile(t)
unlock, err := testLockState("./testdata", statePath)

View File

@ -14,7 +14,7 @@ func TestStateList(t *testing.T) {
statePath := testStateFile(t, state)
p := testProvider()
ui := new(cli.MockUi)
ui := cli.NewMockUi()
c := &StateListCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
@ -42,7 +42,7 @@ func TestStateListWithID(t *testing.T) {
statePath := testStateFile(t, state)
p := testProvider()
ui := new(cli.MockUi)
ui := cli.NewMockUi()
c := &StateListCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
@ -71,7 +71,7 @@ func TestStateListWithNonExistentID(t *testing.T) {
statePath := testStateFile(t, state)
p := testProvider()
ui := new(cli.MockUi)
ui := cli.NewMockUi()
c := &StateListCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
@ -104,7 +104,7 @@ func TestStateList_backendState(t *testing.T) {
defer testChdir(t, td)()
p := testProvider()
ui := new(cli.MockUi)
ui := cli.NewMockUi()
c := &StateListCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
@ -130,7 +130,7 @@ func TestStateList_noState(t *testing.T) {
defer testFixCwd(t, tmp, cwd)
p := testProvider()
ui := new(cli.MockUi)
ui := cli.NewMockUi()
c := &StateListCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),

View File

@ -194,6 +194,7 @@ func TestStatePush_serialOlder(t *testing.T) {
}
func TestStatePush_forceRemoteState(t *testing.T) {
t.Fatalf("FIXME: This test seems to be getting hanged or into an infinite loop")
td := tempDir(t)
copy.CopyDir(testFixturePath("inmem-backend"), td)
defer os.RemoveAll(td)

View File

@ -6,7 +6,7 @@ import (
"sort"
"testing"
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/states/statemgr"
)
// testStateBackups returns the list of backups in order of creation
@ -33,7 +33,7 @@ func TestStateDefaultBackupExtension(t *testing.T) {
t.Fatal(err)
}
backupPath := s.(*state.BackupState).Path
backupPath := s.(*statemgr.Filesystem).BackupPath()
match := regexp.MustCompile(`terraform\.tfstate\.\d+\.backup$`).MatchString
if !match(backupPath) {
t.Fatal("Bad backup path:", backupPath)

View File

@ -215,6 +215,7 @@ func TestWorkspace_createInvalid(t *testing.T) {
}
func TestWorkspace_createWithState(t *testing.T) {
t.Fatalf("FIXME: This test seems to be getting hung or into an infinite loop")
td := tempDir(t)
copy.CopyDir(testFixturePath("inmem-backend"), td)
defer os.RemoveAll(td)

View File

@ -287,6 +287,13 @@ func valueFromTfplan(rawV *planproto.DynamicValue) (plans.DynamicValue, error) {
// writeTfplan serializes the given plan into the protobuf-based format used
// for the "tfplan" portion of a plan file.
func writeTfplan(plan *plans.Plan, w io.Writer) error {
if plan == nil {
return fmt.Errorf("cannot write plan file for nil plan")
}
if plan.Changes == nil {
return fmt.Errorf("cannot write plan file with nil changeset")
}
rawPlan := &planproto.Plan{
Version: tfplanFormatVersion,
TerraformVersion: version.String(),

View File

@ -47,6 +47,9 @@ func BuildState(cb func(*SyncState)) *State {
// in the receiver. In other words, if this state could be safely replaced
// with the return value of NewState and be functionally equivalent.
func (s *State) Empty() bool {
if s == nil {
return true
}
for _, ms := range s.Modules {
if len(ms.Resources) != 0 {
return false
@ -86,6 +89,9 @@ func (s *State) RemoveModule(addr addrs.ModuleInstance) {
// RootModule is a convenient alias for Module(addrs.RootModuleInstance).
func (s *State) RootModule() *Module {
if s == nil {
panic("RootModule called on nil State")
}
return s.Modules[addrs.RootModuleInstance.String()]
}

View File

@ -17,6 +17,11 @@ func StatesMarshalEqual(a, b *states.State) bool {
var aBuf bytes.Buffer
var bBuf bytes.Buffer
// nil states are not valid states, and so they can never martial equal.
if a == nil || b == nil {
return false
}
// We write here some temporary files that have no header information
// populated, thus ensuring that we're only comparing the state itself
// and not any metadata.

View File

@ -298,6 +298,9 @@ func writeStateV4(file *File, w io.Writer) tfdiags.Diagnostics {
// read/prepare V4 functions above would stick around.
var diags tfdiags.Diagnostics
if file == nil || file.State == nil {
panic("attempt to write nil state to file")
}
var terraformVersion string
if file.TerraformVersion != nil {

View File

@ -101,6 +101,12 @@ func (s *Filesystem) SetBackupPath(path string) {
s.writtenBackup = false
}
// BackupPath returns the manager's backup path if backup files are enabled,
// or an empty string otherwise.
func (s *Filesystem) BackupPath() string {
return s.backupPath
}
// State is an implementation of Reader.
func (s *Filesystem) State() *states.State {
defer s.mutex()()