github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/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 TestWaitForState_inconsistent_positive(t *testing.T) {
    74  	conf := &StateChangeConf{
    75  		Pending:                   []string{"replicating"},
    76  		Target:                    []string{"done"},
    77  		Refresh:                   InconsistentStateRefreshFunc(),
    78  		Timeout:                   90 * time.Millisecond,
    79  		PollInterval:              10 * time.Millisecond,
    80  		ContinuousTargetOccurence: 3,
    81  	}
    82  
    83  	idx, err := conf.WaitForState()
    84  
    85  	if err != nil {
    86  		t.Fatalf("err: %s", err)
    87  	}
    88  
    89  	if idx != 4 {
    90  		t.Fatalf("Expected index 4, given %d", idx.(int))
    91  	}
    92  }
    93  
    94  func TestWaitForState_inconsistent_negative(t *testing.T) {
    95  	conf := &StateChangeConf{
    96  		Pending:                   []string{"replicating"},
    97  		Target:                    []string{"done"},
    98  		Refresh:                   InconsistentStateRefreshFunc(),
    99  		Timeout:                   90 * time.Millisecond,
   100  		PollInterval:              10 * time.Millisecond,
   101  		ContinuousTargetOccurence: 4,
   102  	}
   103  
   104  	_, err := conf.WaitForState()
   105  
   106  	if err == nil {
   107  		t.Fatal("Expected timeout error. No error returned.")
   108  	}
   109  	expectedErr := "timeout while waiting for state to become 'done' (last state: 'done', timeout: 90ms)"
   110  	if err.Error() != expectedErr {
   111  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   112  	}
   113  }
   114  
   115  func TestWaitForState_timeout(t *testing.T) {
   116  	conf := &StateChangeConf{
   117  		Pending: []string{"pending", "incomplete"},
   118  		Target:  []string{"running"},
   119  		Refresh: TimeoutStateRefreshFunc(),
   120  		Timeout: 1 * time.Millisecond,
   121  	}
   122  
   123  	obj, err := conf.WaitForState()
   124  
   125  	if err == nil {
   126  		t.Fatal("Expected timeout error. No error returned.")
   127  	}
   128  
   129  	expectedErr := "timeout while waiting for state to become 'running' (timeout: 1ms)"
   130  	if err.Error() != expectedErr {
   131  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   132  	}
   133  
   134  	if obj != nil {
   135  		t.Fatalf("should not return obj")
   136  	}
   137  
   138  }
   139  
   140  func TestWaitForState_success(t *testing.T) {
   141  	conf := &StateChangeConf{
   142  		Pending: []string{"pending", "incomplete"},
   143  		Target:  []string{"running"},
   144  		Refresh: SuccessfulStateRefreshFunc(),
   145  		Timeout: 200 * time.Second,
   146  	}
   147  
   148  	obj, err := conf.WaitForState()
   149  	if err != nil {
   150  		t.Fatalf("err: %s", err)
   151  	}
   152  	if obj == nil {
   153  		t.Fatalf("should return obj")
   154  	}
   155  }
   156  
   157  func TestWaitForState_successEmpty(t *testing.T) {
   158  	conf := &StateChangeConf{
   159  		Pending: []string{"pending", "incomplete"},
   160  		Target:  []string{},
   161  		Refresh: func() (interface{}, string, error) {
   162  			return nil, "", nil
   163  		},
   164  		Timeout: 200 * time.Second,
   165  	}
   166  
   167  	obj, err := conf.WaitForState()
   168  	if err != nil {
   169  		t.Fatalf("err: %s", err)
   170  	}
   171  	if obj != nil {
   172  		t.Fatalf("obj should be nil")
   173  	}
   174  }
   175  
   176  func TestWaitForState_failureEmpty(t *testing.T) {
   177  	conf := &StateChangeConf{
   178  		Pending:        []string{"pending", "incomplete"},
   179  		Target:         []string{},
   180  		NotFoundChecks: 1,
   181  		Refresh: func() (interface{}, string, error) {
   182  			return 42, "pending", nil
   183  		},
   184  		PollInterval: 10 * time.Millisecond,
   185  		Timeout:      100 * time.Millisecond,
   186  	}
   187  
   188  	_, err := conf.WaitForState()
   189  	if err == nil {
   190  		t.Fatal("Expected timeout error. Got none.")
   191  	}
   192  	expectedErr := "timeout while waiting for resource to be gone (last state: 'pending', timeout: 100ms)"
   193  	if err.Error() != expectedErr {
   194  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   195  	}
   196  }
   197  
   198  func TestWaitForState_failure(t *testing.T) {
   199  	conf := &StateChangeConf{
   200  		Pending: []string{"pending", "incomplete"},
   201  		Target:  []string{"running"},
   202  		Refresh: FailedStateRefreshFunc(),
   203  		Timeout: 200 * time.Second,
   204  	}
   205  
   206  	obj, err := conf.WaitForState()
   207  	if err == nil {
   208  		t.Fatal("Expected error. No error returned.")
   209  	}
   210  	expectedErr := "failed"
   211  	if err.Error() != expectedErr {
   212  		t.Fatalf("Errors don't match.\nExpected: %q\nGiven: %q\n", expectedErr, err.Error())
   213  	}
   214  	if obj != nil {
   215  		t.Fatalf("should not return obj")
   216  	}
   217  }