github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/state/local_test.go (about)

     1  package state
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"os/exec"
     7  	"testing"
     8  
     9  	"github.com/hashicorp/terraform/terraform"
    10  )
    11  
    12  func TestLocalState(t *testing.T) {
    13  	ls := testLocalState(t)
    14  	defer os.Remove(ls.Path)
    15  	TestState(t, ls)
    16  }
    17  
    18  func TestLocalStateLocks(t *testing.T) {
    19  	s := testLocalState(t)
    20  	defer os.Remove(s.Path)
    21  
    22  	// lock first
    23  	info := NewLockInfo()
    24  	info.Operation = "test"
    25  	lockID, err := s.Lock(info)
    26  	if err != nil {
    27  		t.Fatal(err)
    28  	}
    29  
    30  	out, err := exec.Command("go", "run", "testdata/lockstate.go", s.Path).CombinedOutput()
    31  	if err != nil {
    32  		t.Fatal("unexpected lock failure", err, string(out))
    33  	}
    34  
    35  	if string(out) != "lock failed" {
    36  		t.Fatal("expected 'locked failed', got", string(out))
    37  	}
    38  
    39  	// check our lock info
    40  	lockInfo, err := s.lockInfo()
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  
    45  	if lockInfo.Operation != "test" {
    46  		t.Fatalf("invalid lock info %#v\n", lockInfo)
    47  	}
    48  
    49  	// a noop, since we unlock on exit
    50  	if err := s.Unlock(lockID); err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	// local locks can re-lock
    55  	lockID, err = s.Lock(info)
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  
    60  	if err := s.Unlock(lockID); err != nil {
    61  		t.Fatal(err)
    62  	}
    63  
    64  	// we should not be able to unlock the same lock twice
    65  	if err := s.Unlock(lockID); err == nil {
    66  		t.Fatal("unlocking an unlocked state should fail")
    67  	}
    68  
    69  	// make sure lock info is gone
    70  	lockInfoPath := s.lockInfoPath()
    71  	if _, err := os.Stat(lockInfoPath); !os.IsNotExist(err) {
    72  		t.Fatal("lock info not removed")
    73  	}
    74  }
    75  
    76  // Verify that we can write to the state file, as Windows' mandatory locking
    77  // will prevent writing to a handle different than the one that hold the lock.
    78  func TestLocalState_writeWhileLocked(t *testing.T) {
    79  	s := testLocalState(t)
    80  	defer os.Remove(s.Path)
    81  
    82  	// lock first
    83  	info := NewLockInfo()
    84  	info.Operation = "test"
    85  	lockID, err := s.Lock(info)
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  	defer func() {
    90  		if err := s.Unlock(lockID); err != nil {
    91  			t.Fatal(err)
    92  		}
    93  	}()
    94  
    95  	if err := s.WriteState(TestStateInitial()); err != nil {
    96  		t.Fatal(err)
    97  	}
    98  }
    99  
   100  func TestLocalState_pathOut(t *testing.T) {
   101  	f, err := ioutil.TempFile("", "tf")
   102  	if err != nil {
   103  		t.Fatalf("err: %s", err)
   104  	}
   105  	f.Close()
   106  	defer os.Remove(f.Name())
   107  
   108  	ls := testLocalState(t)
   109  	ls.PathOut = f.Name()
   110  	defer os.Remove(ls.Path)
   111  
   112  	TestState(t, ls)
   113  }
   114  
   115  func TestLocalState_nonExist(t *testing.T) {
   116  	ls := &LocalState{Path: "ishouldntexist"}
   117  	if err := ls.RefreshState(); err != nil {
   118  		t.Fatalf("err: %s", err)
   119  	}
   120  
   121  	if state := ls.State(); state != nil {
   122  		t.Fatalf("bad: %#v", state)
   123  	}
   124  }
   125  
   126  func TestLocalState_impl(t *testing.T) {
   127  	var _ StateReader = new(LocalState)
   128  	var _ StateWriter = new(LocalState)
   129  	var _ StatePersister = new(LocalState)
   130  	var _ StateRefresher = new(LocalState)
   131  }
   132  
   133  func testLocalState(t *testing.T) *LocalState {
   134  	f, err := ioutil.TempFile("", "tf")
   135  	if err != nil {
   136  		t.Fatalf("err: %s", err)
   137  	}
   138  
   139  	err = terraform.WriteState(TestStateInitial(), f)
   140  	f.Close()
   141  	if err != nil {
   142  		t.Fatalf("err: %s", err)
   143  	}
   144  
   145  	ls := &LocalState{Path: f.Name()}
   146  	if err := ls.RefreshState(); err != nil {
   147  		t.Fatalf("bad: %s", err)
   148  	}
   149  
   150  	return ls
   151  }