github.com/rjeczalik/terraform@v0.6.7-0.20160812060014-e251d5c7bd39/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:                   10 * time.Second,
    79  		ContinuousTargetOccurence: 3,
    80  	}
    81  
    82  	idx, err := conf.WaitForState()
    83  
    84  	if err != nil {
    85  		t.Fatalf("err: %s", err)
    86  	}
    87  
    88  	if idx != 4 {
    89  		t.Fatalf("Expected index 4, given %d", idx.(int))
    90  	}
    91  }
    92  
    93  func TestWaitForState_inconsistent_negative(t *testing.T) {
    94  	conf := &StateChangeConf{
    95  		Pending:                   []string{"replicating"},
    96  		Target:                    []string{"done"},
    97  		Refresh:                   InconsistentStateRefreshFunc(),
    98  		Timeout:                   10 * time.Second,
    99  		ContinuousTargetOccurence: 4,
   100  	}
   101  
   102  	_, err := conf.WaitForState()
   103  
   104  	if err == nil && err.Error() != "timeout while waiting for state to become 'done'" {
   105  		t.Fatalf("err: %s", err)
   106  	}
   107  }
   108  
   109  func TestWaitForState_timeout(t *testing.T) {
   110  	conf := &StateChangeConf{
   111  		Pending: []string{"pending", "incomplete"},
   112  		Target:  []string{"running"},
   113  		Refresh: TimeoutStateRefreshFunc(),
   114  		Timeout: 1 * time.Millisecond,
   115  	}
   116  
   117  	obj, err := conf.WaitForState()
   118  
   119  	if err == nil && err.Error() != "timeout while waiting for state to become 'running'" {
   120  		t.Fatalf("err: %s", err)
   121  	}
   122  
   123  	if obj != nil {
   124  		t.Fatalf("should not return obj")
   125  	}
   126  
   127  }
   128  
   129  func TestWaitForState_success(t *testing.T) {
   130  	conf := &StateChangeConf{
   131  		Pending: []string{"pending", "incomplete"},
   132  		Target:  []string{"running"},
   133  		Refresh: SuccessfulStateRefreshFunc(),
   134  		Timeout: 200 * time.Second,
   135  	}
   136  
   137  	obj, err := conf.WaitForState()
   138  	if err != nil {
   139  		t.Fatalf("err: %s", err)
   140  	}
   141  	if obj == nil {
   142  		t.Fatalf("should return obj")
   143  	}
   144  }
   145  
   146  func TestWaitForState_successEmpty(t *testing.T) {
   147  	conf := &StateChangeConf{
   148  		Pending: []string{"pending", "incomplete"},
   149  		Target:  []string{},
   150  		Refresh: func() (interface{}, string, error) {
   151  			return nil, "", nil
   152  		},
   153  		Timeout: 200 * time.Second,
   154  	}
   155  
   156  	obj, err := conf.WaitForState()
   157  	if err != nil {
   158  		t.Fatalf("err: %s", err)
   159  	}
   160  	if obj != nil {
   161  		t.Fatalf("obj should be nil")
   162  	}
   163  }
   164  
   165  func TestWaitForState_failure(t *testing.T) {
   166  	conf := &StateChangeConf{
   167  		Pending: []string{"pending", "incomplete"},
   168  		Target:  []string{"running"},
   169  		Refresh: FailedStateRefreshFunc(),
   170  		Timeout: 200 * time.Second,
   171  	}
   172  
   173  	obj, err := conf.WaitForState()
   174  	if err == nil && err.Error() != "failed" {
   175  		t.Fatalf("err: %s", err)
   176  	}
   177  	if obj != nil {
   178  		t.Fatalf("should not return obj")
   179  	}
   180  }