github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/terraform/shadow_resource_provider_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func TestShadowResourceProvider_impl(t *testing.T) {
    11  	var _ Shadow = new(shadowResourceProviderShadow)
    12  }
    13  
    14  func TestShadowResourceProvider_cachedValues(t *testing.T) {
    15  	mock := new(MockResourceProvider)
    16  	real, shadow := newShadowResourceProvider(mock)
    17  
    18  	// Resources
    19  	{
    20  		actual := shadow.Resources()
    21  		expected := real.Resources()
    22  		if !reflect.DeepEqual(actual, expected) {
    23  			t.Fatalf("bad:\n\n%#v\n\n%#v", actual, expected)
    24  		}
    25  	}
    26  
    27  	// DataSources
    28  	{
    29  		actual := shadow.DataSources()
    30  		expected := real.DataSources()
    31  		if !reflect.DeepEqual(actual, expected) {
    32  			t.Fatalf("bad:\n\n%#v\n\n%#v", actual, expected)
    33  		}
    34  	}
    35  }
    36  
    37  func TestShadowResourceProviderInput(t *testing.T) {
    38  	mock := new(MockResourceProvider)
    39  	real, shadow := newShadowResourceProvider(mock)
    40  
    41  	// Test values
    42  	ui := new(MockUIInput)
    43  	config := testResourceConfig(t, map[string]interface{}{
    44  		"foo": "bar",
    45  	})
    46  	returnConfig := testResourceConfig(t, map[string]interface{}{
    47  		"bar": "baz",
    48  	})
    49  
    50  	// Configure the mock
    51  	mock.InputReturnConfig = returnConfig
    52  
    53  	// Verify that it blocks until the real input is called
    54  	var actual *ResourceConfig
    55  	var err error
    56  	doneCh := make(chan struct{})
    57  	go func() {
    58  		defer close(doneCh)
    59  		actual, err = shadow.Input(ui, config)
    60  	}()
    61  
    62  	select {
    63  	case <-doneCh:
    64  		t.Fatal("should block until finished")
    65  	case <-time.After(10 * time.Millisecond):
    66  	}
    67  
    68  	// Call the real input
    69  	realResult, realErr := real.Input(ui, config)
    70  	if !realResult.Equal(returnConfig) {
    71  		t.Fatalf("bad: %#v", realResult)
    72  	}
    73  	if realErr != nil {
    74  		t.Fatalf("bad: %s", realErr)
    75  	}
    76  
    77  	// The shadow should finish now
    78  	<-doneCh
    79  
    80  	// Verify the shadow returned the same values
    81  	if !actual.Equal(returnConfig) {
    82  		t.Fatalf("bad: %#v", actual)
    83  	}
    84  	if err != nil {
    85  		t.Fatalf("bad: %s", err)
    86  	}
    87  
    88  	// Verify we have no errors
    89  	if err := shadow.CloseShadow(); err != nil {
    90  		t.Fatalf("bad: %s", err)
    91  	}
    92  }
    93  
    94  func TestShadowResourceProviderInput_badInput(t *testing.T) {
    95  	mock := new(MockResourceProvider)
    96  	real, shadow := newShadowResourceProvider(mock)
    97  
    98  	// Test values
    99  	ui := new(MockUIInput)
   100  	config := testResourceConfig(t, map[string]interface{}{
   101  		"foo": "bar",
   102  	})
   103  	configBad := testResourceConfig(t, map[string]interface{}{
   104  		"foo": "nope",
   105  	})
   106  
   107  	// Call the real with one
   108  	real.Input(ui, config)
   109  
   110  	// Call the shadow with another
   111  	_, err := shadow.Input(ui, configBad)
   112  	if err != nil {
   113  		t.Fatalf("bad: %s", err)
   114  	}
   115  
   116  	// Verify we have an error
   117  	if err := shadow.CloseShadow(); err != nil {
   118  		t.Fatalf("bad: %s", err)
   119  	}
   120  	if err := shadow.ShadowError(); err == nil {
   121  		t.Fatal("should error")
   122  	}
   123  }
   124  
   125  func TestShadowResourceProviderValidate(t *testing.T) {
   126  	mock := new(MockResourceProvider)
   127  	real, shadow := newShadowResourceProvider(mock)
   128  
   129  	// Test values
   130  	config := testResourceConfig(t, map[string]interface{}{
   131  		"foo": "bar",
   132  	})
   133  	returnWarns := []string{"foo"}
   134  	returnErrs := []error{fmt.Errorf("bar")}
   135  
   136  	// Configure the mock
   137  	mock.ValidateReturnWarns = returnWarns
   138  	mock.ValidateReturnErrors = returnErrs
   139  
   140  	// Verify that it blocks until the real func is called
   141  	var warns []string
   142  	var errs []error
   143  	doneCh := make(chan struct{})
   144  	go func() {
   145  		defer close(doneCh)
   146  		warns, errs = shadow.Validate(config)
   147  	}()
   148  
   149  	select {
   150  	case <-doneCh:
   151  		t.Fatal("should block until finished")
   152  	case <-time.After(10 * time.Millisecond):
   153  	}
   154  
   155  	// Call the real func
   156  	realWarns, realErrs := real.Validate(config)
   157  	if !reflect.DeepEqual(realWarns, returnWarns) {
   158  		t.Fatalf("bad: %#v", realWarns)
   159  	}
   160  	if !reflect.DeepEqual(realErrs, returnErrs) {
   161  		t.Fatalf("bad: %#v", realWarns)
   162  	}
   163  
   164  	// The shadow should finish now
   165  	<-doneCh
   166  
   167  	// Verify the shadow returned the same values
   168  	if !reflect.DeepEqual(warns, returnWarns) {
   169  		t.Fatalf("bad: %#v", warns)
   170  	}
   171  	if !reflect.DeepEqual(errs, returnErrs) {
   172  		t.Fatalf("bad: %#v", errs)
   173  	}
   174  
   175  	// Verify we have no errors
   176  	if err := shadow.CloseShadow(); err != nil {
   177  		t.Fatalf("bad: %s", err)
   178  	}
   179  }
   180  
   181  func TestShadowResourceProviderValidate_badInput(t *testing.T) {
   182  	mock := new(MockResourceProvider)
   183  	real, shadow := newShadowResourceProvider(mock)
   184  
   185  	// Test values
   186  	config := testResourceConfig(t, map[string]interface{}{
   187  		"foo": "bar",
   188  	})
   189  	configBad := testResourceConfig(t, map[string]interface{}{
   190  		"foo": "nope",
   191  	})
   192  
   193  	// Call the real with one
   194  	real.Validate(config)
   195  
   196  	// Call the shadow with another
   197  	shadow.Validate(configBad)
   198  
   199  	// Verify we have an error
   200  	if err := shadow.CloseShadow(); err != nil {
   201  		t.Fatalf("bad: %s", err)
   202  	}
   203  	if err := shadow.ShadowError(); err == nil {
   204  		t.Fatal("should error")
   205  	}
   206  }
   207  
   208  func TestShadowResourceProviderConfigure(t *testing.T) {
   209  	mock := new(MockResourceProvider)
   210  	real, shadow := newShadowResourceProvider(mock)
   211  
   212  	// Test values
   213  	config := testResourceConfig(t, map[string]interface{}{
   214  		"foo": "bar",
   215  	})
   216  	returnErr := fmt.Errorf("bar")
   217  
   218  	// Configure the mock
   219  	mock.ConfigureReturnError = returnErr
   220  
   221  	// Verify that it blocks until the real func is called
   222  	var err error
   223  	doneCh := make(chan struct{})
   224  	go func() {
   225  		defer close(doneCh)
   226  		err = shadow.Configure(config)
   227  	}()
   228  
   229  	select {
   230  	case <-doneCh:
   231  		t.Fatal("should block until finished")
   232  	case <-time.After(10 * time.Millisecond):
   233  	}
   234  
   235  	// Call the real func
   236  	realErr := real.Configure(config)
   237  	if !reflect.DeepEqual(realErr, returnErr) {
   238  		t.Fatalf("bad: %#v", realErr)
   239  	}
   240  
   241  	// The shadow should finish now
   242  	<-doneCh
   243  
   244  	// Verify the shadow returned the same values
   245  	if !reflect.DeepEqual(err, returnErr) {
   246  		t.Fatalf("bad: %#v", err)
   247  	}
   248  
   249  	// Verify we have no errors
   250  	if err := shadow.CloseShadow(); err != nil {
   251  		t.Fatalf("bad: %s", err)
   252  	}
   253  }
   254  
   255  func TestShadowResourceProviderConfigure_badInput(t *testing.T) {
   256  	mock := new(MockResourceProvider)
   257  	real, shadow := newShadowResourceProvider(mock)
   258  
   259  	// Test values
   260  	config := testResourceConfig(t, map[string]interface{}{
   261  		"foo": "bar",
   262  	})
   263  	configBad := testResourceConfig(t, map[string]interface{}{
   264  		"foo": "nope",
   265  	})
   266  
   267  	// Call the real with one
   268  	real.Configure(config)
   269  
   270  	// Call the shadow with another
   271  	shadow.Configure(configBad)
   272  
   273  	// Verify we have an error
   274  	if err := shadow.CloseShadow(); err != nil {
   275  		t.Fatalf("bad: %s", err)
   276  	}
   277  	if err := shadow.ShadowError(); err == nil {
   278  		t.Fatal("should error")
   279  	}
   280  }
   281  
   282  func TestShadowResourceProviderApply(t *testing.T) {
   283  	mock := new(MockResourceProvider)
   284  	real, shadow := newShadowResourceProvider(mock)
   285  
   286  	// Test values
   287  	info := &InstanceInfo{Id: "foo"}
   288  	state := &InstanceState{ID: "foo"}
   289  	diff := &InstanceDiff{Destroy: true}
   290  	mockResult := &InstanceState{ID: "bar"}
   291  
   292  	// Configure the mock
   293  	mock.ApplyReturn = mockResult
   294  
   295  	// Verify that it blocks until the real func is called
   296  	var result *InstanceState
   297  	var err error
   298  	doneCh := make(chan struct{})
   299  	go func() {
   300  		defer close(doneCh)
   301  		result, err = shadow.Apply(info, state, diff)
   302  	}()
   303  
   304  	select {
   305  	case <-doneCh:
   306  		t.Fatal("should block until finished")
   307  	case <-time.After(10 * time.Millisecond):
   308  	}
   309  
   310  	// Call the real func
   311  	realResult, realErr := real.Apply(info, state, diff)
   312  	if !realResult.Equal(mockResult) {
   313  		t.Fatalf("bad: %#v", realResult)
   314  	}
   315  	if realErr != nil {
   316  		t.Fatalf("bad: %#v", realErr)
   317  	}
   318  
   319  	// The shadow should finish now
   320  	<-doneCh
   321  
   322  	// Verify the shadow returned the same values
   323  	if !result.Equal(mockResult) {
   324  		t.Fatalf("bad: %#v", result)
   325  	}
   326  	if err != nil {
   327  		t.Fatalf("bad: %#v", err)
   328  	}
   329  
   330  	// Verify we have no errors
   331  	if err := shadow.CloseShadow(); err != nil {
   332  		t.Fatalf("bad: %s", err)
   333  	}
   334  }
   335  
   336  func TestShadowResourceProviderApply_modifyDiff(t *testing.T) {
   337  	mock := new(MockResourceProvider)
   338  	real, shadow := newShadowResourceProvider(mock)
   339  
   340  	// Test values
   341  	info := &InstanceInfo{Id: "foo"}
   342  	state := &InstanceState{ID: "foo"}
   343  	diff := &InstanceDiff{}
   344  	mockResult := &InstanceState{ID: "foo"}
   345  
   346  	// Configure the mock
   347  	mock.ApplyFn = func(
   348  		info *InstanceInfo,
   349  		s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
   350  		d.Destroy = true
   351  		return s, nil
   352  	}
   353  
   354  	// Call the real func
   355  	realResult, realErr := real.Apply(info, state.DeepCopy(), diff.DeepCopy())
   356  	if !realResult.Equal(mockResult) {
   357  		t.Fatalf("bad: %#v", realResult)
   358  	}
   359  	if realErr != nil {
   360  		t.Fatalf("bad: %#v", realErr)
   361  	}
   362  
   363  	// Verify the shadow returned the same values
   364  	result, err := shadow.Apply(info, state.DeepCopy(), diff.DeepCopy())
   365  	if !result.Equal(mockResult) {
   366  		t.Fatalf("bad: %#v", result)
   367  	}
   368  	if err != nil {
   369  		t.Fatalf("bad: %#v", err)
   370  	}
   371  
   372  	// Verify we have no errors
   373  	if err := shadow.CloseShadow(); err != nil {
   374  		t.Fatalf("bad: %s", err)
   375  	}
   376  	if err := shadow.ShadowError(); err != nil {
   377  		t.Fatalf("bad: %s", err)
   378  	}
   379  }
   380  
   381  func TestShadowResourceProviderApply_modifyState(t *testing.T) {
   382  	mock := new(MockResourceProvider)
   383  	real, shadow := newShadowResourceProvider(mock)
   384  
   385  	// Test values
   386  	info := &InstanceInfo{Id: "foo"}
   387  	state := &InstanceState{ID: ""}
   388  	diff := &InstanceDiff{}
   389  	mockResult := &InstanceState{ID: "foo"}
   390  
   391  	// Configure the mock
   392  	mock.ApplyFn = func(
   393  		info *InstanceInfo,
   394  		s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
   395  		s.ID = "foo"
   396  		return s, nil
   397  	}
   398  
   399  	// Call the real func
   400  	realResult, realErr := real.Apply(info, state.DeepCopy(), diff)
   401  	if !realResult.Equal(mockResult) {
   402  		t.Fatalf("bad: %#v", realResult)
   403  	}
   404  	if realErr != nil {
   405  		t.Fatalf("bad: %#v", realErr)
   406  	}
   407  
   408  	// Verify the shadow returned the same values
   409  	result, err := shadow.Apply(info, state.DeepCopy(), diff)
   410  	if !result.Equal(mockResult) {
   411  		t.Fatalf("bad: %#v", result)
   412  	}
   413  	if err != nil {
   414  		t.Fatalf("bad: %#v", err)
   415  	}
   416  
   417  	// Verify we have no errors
   418  	if err := shadow.CloseShadow(); err != nil {
   419  		t.Fatalf("bad: %s", err)
   420  	}
   421  	if err := shadow.ShadowError(); err != nil {
   422  		t.Fatalf("bad: %s", err)
   423  	}
   424  }
   425  
   426  func TestShadowResourceProviderDiff(t *testing.T) {
   427  	mock := new(MockResourceProvider)
   428  	real, shadow := newShadowResourceProvider(mock)
   429  
   430  	// Test values
   431  	info := &InstanceInfo{Id: "foo"}
   432  	state := &InstanceState{ID: "foo"}
   433  	desired := testResourceConfig(t, map[string]interface{}{"foo": "bar"})
   434  	mockResult := &InstanceDiff{Destroy: true}
   435  
   436  	// Configure the mock
   437  	mock.DiffReturn = mockResult
   438  
   439  	// Verify that it blocks until the real func is called
   440  	var result *InstanceDiff
   441  	var err error
   442  	doneCh := make(chan struct{})
   443  	go func() {
   444  		defer close(doneCh)
   445  		result, err = shadow.Diff(info, state, desired)
   446  	}()
   447  
   448  	select {
   449  	case <-doneCh:
   450  		t.Fatal("should block until finished")
   451  	case <-time.After(10 * time.Millisecond):
   452  	}
   453  
   454  	// Call the real func
   455  	realResult, realErr := real.Diff(info, state, desired)
   456  	if !reflect.DeepEqual(realResult, mockResult) {
   457  		t.Fatalf("bad: %#v", realResult)
   458  	}
   459  	if realErr != nil {
   460  		t.Fatalf("bad: %#v", realErr)
   461  	}
   462  
   463  	// The shadow should finish now
   464  	<-doneCh
   465  
   466  	// Verify the shadow returned the same values
   467  	if !reflect.DeepEqual(result, mockResult) {
   468  		t.Fatalf("bad: %#v", result)
   469  	}
   470  	if err != nil {
   471  		t.Fatalf("bad: %#v", err)
   472  	}
   473  
   474  	// Verify we have no errors
   475  	if err := shadow.CloseShadow(); err != nil {
   476  		t.Fatalf("bad: %s", err)
   477  	}
   478  }
   479  
   480  func TestShadowResourceProviderRefresh(t *testing.T) {
   481  	mock := new(MockResourceProvider)
   482  	real, shadow := newShadowResourceProvider(mock)
   483  
   484  	// Test values
   485  	info := &InstanceInfo{Id: "foo"}
   486  	state := &InstanceState{ID: "foo"}
   487  	mockResult := &InstanceState{ID: "bar"}
   488  
   489  	// Configure the mock
   490  	mock.RefreshReturn = mockResult
   491  
   492  	// Verify that it blocks until the real func is called
   493  	var result *InstanceState
   494  	var err error
   495  	doneCh := make(chan struct{})
   496  	go func() {
   497  		defer close(doneCh)
   498  		result, err = shadow.Refresh(info, state)
   499  	}()
   500  
   501  	select {
   502  	case <-doneCh:
   503  		t.Fatal("should block until finished")
   504  	case <-time.After(10 * time.Millisecond):
   505  	}
   506  
   507  	// Call the real func
   508  	realResult, realErr := real.Refresh(info, state)
   509  	if !realResult.Equal(mockResult) {
   510  		t.Fatalf("bad: %#v", realResult)
   511  	}
   512  	if realErr != nil {
   513  		t.Fatalf("bad: %#v", realErr)
   514  	}
   515  
   516  	// The shadow should finish now
   517  	<-doneCh
   518  
   519  	// Verify the shadow returned the same values
   520  	if !result.Equal(mockResult) {
   521  		t.Fatalf("bad: %#v", result)
   522  	}
   523  	if err != nil {
   524  		t.Fatalf("bad: %#v", err)
   525  	}
   526  
   527  	// Verify we have no errors
   528  	if err := shadow.CloseShadow(); err != nil {
   529  		t.Fatalf("bad: %s", err)
   530  	}
   531  }