github.com/cbroglie/terraform@v0.7.0-rc3.0.20170410193827-735dfc416d46/helper/resource/state_test.go (about)

     1  package resource
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  	"time"
     7  )
     8  
     9  func FailedStateRefreshFunc() StateRefreshFunc {
    10  	return func() (interface{}, string, error) {
    11  		return nil, "", errors.New("failed")
    12  	}
    13  }
    14  
    15  func TimeoutStateRefreshFunc() StateRefreshFunc {
    16  	return func() (interface{}, string, error) {
    17  		time.Sleep(100 * time.Second)
    18  		return nil, "", errors.New("failed")
    19  	}
    20  }
    21  
    22  func SuccessfulStateRefreshFunc() StateRefreshFunc {
    23  	return func() (interface{}, string, error) {
    24  		return struct{}{}, "running", nil
    25  	}
    26  }
    27  
    28  type StateGenerator struct {
    29  	position      int
    30  	stateSequence []string
    31  }
    32  
    33  func (r *StateGenerator) NextState() (int, string, error) {
    34  	p, v := r.position, ""
    35  	if len(r.stateSequence)-1 >= p {
    36  		v = r.stateSequence[p]
    37  	} else {
    38  		return -1, "", errors.New("No more states available")
    39  	}
    40  
    41  	r.position += 1
    42  
    43  	return p, v, nil
    44  }
    45  
    46  func NewStateGenerator(sequence []string) *StateGenerator {
    47  	r := &StateGenerator{}
    48  	r.stateSequence = sequence
    49  
    50  	return r
    51  }
    52  
    53  func InconsistentStateRefreshFunc() StateRefreshFunc {
    54  	sequence := []string{
    55  		"done", "replicating",
    56  		"done", "done", "done",
    57  		"replicating",
    58  		"done", "done", "done",
    59  	}
    60  
    61  	r := NewStateGenerator(sequence)
    62  
    63  	return func() (interface{}, string, error) {
    64  		idx, s, err := r.NextState()
    65  		if err != nil {
    66  			return nil, "", err
    67  		}
    68  
    69  		return idx, s, nil
    70  	}
    71  }
    72  
    73  func UnknownPendingStateRefreshFunc() StateRefreshFunc {
    74  	sequence := []string{
    75  		"unknown1", "unknown2", "done",
    76  	}
    77  
    78  	r := NewStateGenerator(sequence)
    79  
    80  	return func() (interface{}, string, error) {
    81  		idx, s, err := r.NextState()
    82  		if err != nil {
    83  			return nil, "", err
    84  		}
    85  
    86  		return idx, s, nil
    87  	}
    88  }
    89  
    90  func TestWaitForState_inconsistent_positive(t *testing.T) {
    91  	conf := &StateChangeConf{
    92  		Pending:                   []string{"replicating"},
    93  		Target:                    []string{"done"},
    94  		Refresh:                   InconsistentStateRefreshFunc(),
    95  		Timeout:                   90 * time.Millisecond,
    96  		PollInterval:              10 * time.Millisecond,
    97  		ContinuousTargetOccurence: 3,
    98  	}
    99  
   100  	idx, err := conf.WaitForState()
   101  
   102  	if err != nil {
   103  		t.Fatalf("err: %s", err)
   104  	}
   105  
   106  	if idx != 4 {
   107  		t.Fatalf("Expected index 4, given %d", idx.(int))
   108  	}
   109  }
   110  
   111  func TestWaitForState_inconsistent_negative(t *testing.T) {
   112  	conf := &StateChangeConf{
   113  		Pending:                   []string{"replicating"},
   114  		Target:                    []string{"done"},
   115  		Refresh:                   InconsistentStateRefreshFunc(),
   116  		Timeout:                   90 * time.Millisecond,
   117  		PollInterval:              10 * time.Millisecond,
   118  		ContinuousTargetOccurence: 4,
   119  	}
   120  
   121  	_, err := conf.WaitForState()
   122  
   123  	if err == nil {
   124  		t.Fatal("Expected timeout error. No error returned.")
   125  	}
   126  	expectedErr := "timeout while waiting for state to become 'done' (last state: 'done', timeout: 90ms)"
   127  	if err.Error() != expectedErr {
   128  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   129  	}
   130  }
   131  
   132  func TestWaitForState_timeout(t *testing.T) {
   133  	conf := &StateChangeConf{
   134  		Pending: []string{"pending", "incomplete"},
   135  		Target:  []string{"running"},
   136  		Refresh: TimeoutStateRefreshFunc(),
   137  		Timeout: 1 * time.Millisecond,
   138  	}
   139  
   140  	obj, err := conf.WaitForState()
   141  
   142  	if err == nil {
   143  		t.Fatal("Expected timeout error. No error returned.")
   144  	}
   145  
   146  	expectedErr := "timeout while waiting for state to become 'running' (timeout: 1ms)"
   147  	if err.Error() != expectedErr {
   148  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   149  	}
   150  
   151  	if obj != nil {
   152  		t.Fatalf("should not return obj")
   153  	}
   154  
   155  }
   156  
   157  func TestWaitForState_success(t *testing.T) {
   158  	conf := &StateChangeConf{
   159  		Pending: []string{"pending", "incomplete"},
   160  		Target:  []string{"running"},
   161  		Refresh: SuccessfulStateRefreshFunc(),
   162  		Timeout: 200 * time.Second,
   163  	}
   164  
   165  	obj, err := conf.WaitForState()
   166  	if err != nil {
   167  		t.Fatalf("err: %s", err)
   168  	}
   169  	if obj == nil {
   170  		t.Fatalf("should return obj")
   171  	}
   172  }
   173  
   174  func TestWaitForState_successUnknownPending(t *testing.T) {
   175  	conf := &StateChangeConf{
   176  		Target:  []string{"done"},
   177  		Refresh: UnknownPendingStateRefreshFunc(),
   178  		Timeout: 200 * time.Second,
   179  	}
   180  
   181  	obj, err := conf.WaitForState()
   182  	if err != nil {
   183  		t.Fatalf("err: %s", err)
   184  	}
   185  	if obj == nil {
   186  		t.Fatalf("should return obj")
   187  	}
   188  }
   189  
   190  func TestWaitForState_successEmpty(t *testing.T) {
   191  	conf := &StateChangeConf{
   192  		Pending: []string{"pending", "incomplete"},
   193  		Target:  []string{},
   194  		Refresh: func() (interface{}, string, error) {
   195  			return nil, "", nil
   196  		},
   197  		Timeout: 200 * time.Second,
   198  	}
   199  
   200  	obj, err := conf.WaitForState()
   201  	if err != nil {
   202  		t.Fatalf("err: %s", err)
   203  	}
   204  	if obj != nil {
   205  		t.Fatalf("obj should be nil")
   206  	}
   207  }
   208  
   209  func TestWaitForState_failureEmpty(t *testing.T) {
   210  	conf := &StateChangeConf{
   211  		Pending:        []string{"pending", "incomplete"},
   212  		Target:         []string{},
   213  		NotFoundChecks: 1,
   214  		Refresh: func() (interface{}, string, error) {
   215  			return 42, "pending", nil
   216  		},
   217  		PollInterval: 10 * time.Millisecond,
   218  		Timeout:      100 * time.Millisecond,
   219  	}
   220  
   221  	_, err := conf.WaitForState()
   222  	if err == nil {
   223  		t.Fatal("Expected timeout error. Got none.")
   224  	}
   225  	expectedErr := "timeout while waiting for resource to be gone (last state: 'pending', timeout: 100ms)"
   226  	if err.Error() != expectedErr {
   227  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   228  	}
   229  }
   230  
   231  func TestWaitForState_failure(t *testing.T) {
   232  	conf := &StateChangeConf{
   233  		Pending: []string{"pending", "incomplete"},
   234  		Target:  []string{"running"},
   235  		Refresh: FailedStateRefreshFunc(),
   236  		Timeout: 200 * time.Second,
   237  	}
   238  
   239  	obj, err := conf.WaitForState()
   240  	if err == nil {
   241  		t.Fatal("Expected error. No error returned.")
   242  	}
   243  	expectedErr := "failed"
   244  	if err.Error() != expectedErr {
   245  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   246  	}
   247  	if obj != nil {
   248  		t.Fatalf("should not return obj")
   249  	}
   250  }