github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/worker/environ/environ_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package environ_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/environs/config"
    15  	coretesting "github.com/juju/juju/testing"
    16  	"github.com/juju/juju/worker/environ"
    17  	"github.com/juju/juju/worker/workertest"
    18  )
    19  
    20  type TrackerSuite struct {
    21  	coretesting.BaseSuite
    22  }
    23  
    24  var _ = gc.Suite(&TrackerSuite{})
    25  
    26  func (s *TrackerSuite) TestValidateObserver(c *gc.C) {
    27  	config := environ.Config{}
    28  	s.testValidate(c, config, func(err error) {
    29  		c.Check(err, jc.Satisfies, errors.IsNotValid)
    30  		c.Check(err, gc.ErrorMatches, "nil Observer not valid")
    31  	})
    32  }
    33  
    34  func (s *TrackerSuite) TestValidateNewEnvironFunc(c *gc.C) {
    35  	config := environ.Config{
    36  		Observer: &runContext{},
    37  	}
    38  	s.testValidate(c, config, func(err error) {
    39  		c.Check(err, jc.Satisfies, errors.IsNotValid)
    40  		c.Check(err, gc.ErrorMatches, "nil NewEnvironFunc not valid")
    41  	})
    42  }
    43  
    44  func (s *TrackerSuite) testValidate(c *gc.C, config environ.Config, check func(err error)) {
    45  	err := config.Validate()
    46  	check(err)
    47  
    48  	tracker, err := environ.NewTracker(config)
    49  	c.Check(tracker, gc.IsNil)
    50  	check(err)
    51  }
    52  
    53  func (s *TrackerSuite) TestModelConfigFails(c *gc.C) {
    54  	fix := &fixture{
    55  		observerErrs: []error{
    56  			errors.New("no yuo"),
    57  		},
    58  	}
    59  	fix.Run(c, func(context *runContext) {
    60  		tracker, err := environ.NewTracker(environ.Config{
    61  			Observer:       context,
    62  			NewEnvironFunc: newMockEnviron,
    63  		})
    64  		c.Check(err, gc.ErrorMatches, "cannot read environ config: no yuo")
    65  		c.Check(tracker, gc.IsNil)
    66  		context.CheckCallNames(c, "ModelConfig")
    67  	})
    68  }
    69  
    70  func (s *TrackerSuite) TestModelConfigInvalid(c *gc.C) {
    71  	fix := &fixture{}
    72  	fix.Run(c, func(context *runContext) {
    73  		tracker, err := environ.NewTracker(environ.Config{
    74  			Observer: context,
    75  			NewEnvironFunc: func(*config.Config) (environs.Environ, error) {
    76  				return nil, errors.NotValidf("config")
    77  			},
    78  		})
    79  		c.Check(err, gc.ErrorMatches, `cannot create environ: config not valid`)
    80  		c.Check(tracker, gc.IsNil)
    81  		context.CheckCallNames(c, "ModelConfig")
    82  	})
    83  }
    84  
    85  func (s *TrackerSuite) TestModelConfigValid(c *gc.C) {
    86  	fix := &fixture{
    87  		initialConfig: coretesting.Attrs{
    88  			"name": "this-particular-name",
    89  		},
    90  	}
    91  	fix.Run(c, func(context *runContext) {
    92  		tracker, err := environ.NewTracker(environ.Config{
    93  			Observer:       context,
    94  			NewEnvironFunc: newMockEnviron,
    95  		})
    96  		c.Assert(err, jc.ErrorIsNil)
    97  		defer workertest.CleanKill(c, tracker)
    98  
    99  		gotEnviron := tracker.Environ()
   100  		c.Assert(gotEnviron, gc.NotNil)
   101  		c.Check(gotEnviron.Config().Name(), gc.Equals, "this-particular-name")
   102  	})
   103  }
   104  
   105  func (s *TrackerSuite) TestWatchFails(c *gc.C) {
   106  	fix := &fixture{
   107  		observerErrs: []error{
   108  			nil, errors.New("grrk splat"),
   109  		},
   110  	}
   111  	fix.Run(c, func(context *runContext) {
   112  		tracker, err := environ.NewTracker(environ.Config{
   113  			Observer:       context,
   114  			NewEnvironFunc: newMockEnviron,
   115  		})
   116  		c.Assert(err, jc.ErrorIsNil)
   117  		defer workertest.DirtyKill(c, tracker)
   118  
   119  		err = workertest.CheckKilled(c, tracker)
   120  		c.Check(err, gc.ErrorMatches, "cannot watch environ config: grrk splat")
   121  		context.CheckCallNames(c, "ModelConfig", "WatchForModelConfigChanges")
   122  	})
   123  }
   124  
   125  func (s *TrackerSuite) TestWatchCloses(c *gc.C) {
   126  	fix := &fixture{}
   127  	fix.Run(c, func(context *runContext) {
   128  		tracker, err := environ.NewTracker(environ.Config{
   129  			Observer:       context,
   130  			NewEnvironFunc: newMockEnviron,
   131  		})
   132  		c.Assert(err, jc.ErrorIsNil)
   133  		defer workertest.DirtyKill(c, tracker)
   134  
   135  		context.CloseNotify()
   136  		err = workertest.CheckKilled(c, tracker)
   137  		c.Check(err, gc.ErrorMatches, "environ config watch closed")
   138  		context.CheckCallNames(c, "ModelConfig", "WatchForModelConfigChanges")
   139  	})
   140  }
   141  
   142  func (s *TrackerSuite) TestWatchedModelConfigFails(c *gc.C) {
   143  	fix := &fixture{
   144  		observerErrs: []error{
   145  			nil, nil, errors.New("blam ouch"),
   146  		},
   147  	}
   148  	fix.Run(c, func(context *runContext) {
   149  		tracker, err := environ.NewTracker(environ.Config{
   150  			Observer:       context,
   151  			NewEnvironFunc: newMockEnviron,
   152  		})
   153  		c.Check(err, jc.ErrorIsNil)
   154  		defer workertest.DirtyKill(c, tracker)
   155  
   156  		context.SendNotify()
   157  		err = workertest.CheckKilled(c, tracker)
   158  		c.Check(err, gc.ErrorMatches, "cannot read environ config: blam ouch")
   159  		context.CheckCallNames(c, "ModelConfig", "WatchForModelConfigChanges", "ModelConfig")
   160  	})
   161  }
   162  
   163  func (s *TrackerSuite) TestWatchedModelConfigIncompatible(c *gc.C) {
   164  	fix := &fixture{}
   165  	fix.Run(c, func(context *runContext) {
   166  		tracker, err := environ.NewTracker(environ.Config{
   167  			Observer: context,
   168  			NewEnvironFunc: func(*config.Config) (environs.Environ, error) {
   169  				env := &mockEnviron{}
   170  				env.SetErrors(errors.New("SetConfig is broken"))
   171  				return env, nil
   172  			},
   173  		})
   174  		c.Check(err, jc.ErrorIsNil)
   175  		defer workertest.DirtyKill(c, tracker)
   176  
   177  		context.SendNotify()
   178  		err = workertest.CheckKilled(c, tracker)
   179  		c.Check(err, gc.ErrorMatches, "cannot update environ config: SetConfig is broken")
   180  		context.CheckCallNames(c, "ModelConfig", "WatchForModelConfigChanges", "ModelConfig")
   181  	})
   182  }
   183  
   184  func (s *TrackerSuite) TestWatchedModelConfigUpdates(c *gc.C) {
   185  	fix := &fixture{
   186  		initialConfig: coretesting.Attrs{
   187  			"name": "original-name",
   188  		},
   189  	}
   190  	fix.Run(c, func(context *runContext) {
   191  		tracker, err := environ.NewTracker(environ.Config{
   192  			Observer:       context,
   193  			NewEnvironFunc: newMockEnviron,
   194  		})
   195  		c.Check(err, jc.ErrorIsNil)
   196  		defer workertest.CleanKill(c, tracker)
   197  
   198  		context.SetConfig(c, coretesting.Attrs{
   199  			"name": "updated-name",
   200  		})
   201  		gotEnviron := tracker.Environ()
   202  		c.Assert(gotEnviron.Config().Name(), gc.Equals, "original-name")
   203  
   204  		timeout := time.After(coretesting.LongWait)
   205  		attempt := time.After(0)
   206  		context.SendNotify()
   207  		for {
   208  			select {
   209  			case <-attempt:
   210  				name := gotEnviron.Config().Name()
   211  				if name == "original-name" {
   212  					attempt = time.After(coretesting.ShortWait)
   213  					continue
   214  				}
   215  				c.Check(name, gc.Equals, "updated-name")
   216  			case <-timeout:
   217  				c.Fatalf("timed out waiting for environ to be updated")
   218  			}
   219  			break
   220  		}
   221  		context.CheckCallNames(c, "ModelConfig", "WatchForModelConfigChanges", "ModelConfig")
   222  	})
   223  }