github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/environ_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package worker_test
     5  
     6  import (
     7  	"strings"
     8  	stdtesting "testing"
     9  	"time"
    10  
    11  	"github.com/juju/loggo"
    12  	jc "github.com/juju/testing/checkers"
    13  	gc "gopkg.in/check.v1"
    14  	"launchpad.net/tomb"
    15  
    16  	"github.com/juju/juju/environs"
    17  	"github.com/juju/juju/juju/testing"
    18  	"github.com/juju/juju/mongo"
    19  	"github.com/juju/juju/state"
    20  	coretesting "github.com/juju/juju/testing"
    21  	"github.com/juju/juju/worker"
    22  )
    23  
    24  func TestPackage(t *stdtesting.T) {
    25  	coretesting.MgoTestPackage(t)
    26  }
    27  
    28  type environSuite struct {
    29  	testing.JujuConnSuite
    30  }
    31  
    32  var _ = gc.Suite(&environSuite{})
    33  
    34  func (s *environSuite) TestStop(c *gc.C) {
    35  	w := s.State.WatchForEnvironConfigChanges()
    36  	defer stopWatcher(c, w)
    37  	stop := make(chan struct{})
    38  	done := make(chan error)
    39  	go func() {
    40  		env, err := worker.WaitForEnviron(w, s.State, stop)
    41  		c.Check(env, gc.IsNil)
    42  		done <- err
    43  	}()
    44  	close(stop)
    45  	c.Assert(<-done, gc.Equals, tomb.ErrDying)
    46  }
    47  
    48  func stopWatcher(c *gc.C, w state.NotifyWatcher) {
    49  	err := w.Stop()
    50  	c.Check(err, jc.ErrorIsNil)
    51  }
    52  
    53  func (s *environSuite) TestInvalidConfig(c *gc.C) {
    54  	var oldType string
    55  	oldType = s.Environ.Config().AllAttrs()["type"].(string)
    56  
    57  	// Create an invalid config by taking the current config and
    58  	// tweaking the provider type.
    59  	info := s.MongoInfo(c)
    60  	opts := mongo.DefaultDialOpts()
    61  	st2, err := state.Open(info, opts, state.Policy(nil))
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	defer st2.Close()
    64  	err = st2.UpdateEnvironConfig(map[string]interface{}{"type": "unknown"}, nil, nil)
    65  	c.Assert(err, jc.ErrorIsNil)
    66  
    67  	w := st2.WatchForEnvironConfigChanges()
    68  	defer stopWatcher(c, w)
    69  	done := make(chan environs.Environ)
    70  	go func() {
    71  		env, err := worker.WaitForEnviron(w, st2, nil)
    72  		c.Check(err, jc.ErrorIsNil)
    73  		done <- env
    74  	}()
    75  	<-worker.LoadedInvalid
    76  
    77  	st2.UpdateEnvironConfig(map[string]interface{}{
    78  		"type":   oldType,
    79  		"secret": "environ_test",
    80  	}, nil, nil)
    81  
    82  	st2.StartSync()
    83  	env := <-done
    84  	c.Assert(env, gc.NotNil)
    85  	c.Assert(env.Config().AllAttrs()["secret"], gc.Equals, "environ_test")
    86  }
    87  
    88  func (s *environSuite) TestErrorWhenEnvironIsInvalid(c *gc.C) {
    89  	// reopen the state so that we can wangle a dodgy environ config in there.
    90  	st, err := state.Open(s.MongoInfo(c), mongo.DefaultDialOpts(), state.Policy(nil))
    91  	c.Assert(err, jc.ErrorIsNil)
    92  	defer st.Close()
    93  	err = st.UpdateEnvironConfig(map[string]interface{}{"secret": 999}, nil, nil)
    94  	c.Assert(err, jc.ErrorIsNil)
    95  	obs, err := worker.NewEnvironObserver(s.State)
    96  	c.Assert(err, gc.ErrorMatches, `cannot make Environ: secret: expected string, got int\(999\)`)
    97  	c.Assert(obs, gc.IsNil)
    98  }
    99  
   100  func (s *environSuite) TestEnvironmentChanges(c *gc.C) {
   101  	originalConfig, err := s.State.EnvironConfig()
   102  	c.Assert(err, jc.ErrorIsNil)
   103  
   104  	logc := make(logChan, 1009)
   105  	c.Assert(loggo.RegisterWriter("testing", logc, loggo.WARNING), gc.IsNil)
   106  	defer loggo.RemoveWriter("testing")
   107  
   108  	obs, err := worker.NewEnvironObserver(s.State)
   109  	c.Assert(err, jc.ErrorIsNil)
   110  
   111  	env := obs.Environ()
   112  	c.Assert(env.Config().AllAttrs(), gc.DeepEquals, originalConfig.AllAttrs())
   113  	var oldType string
   114  	oldType = env.Config().AllAttrs()["type"].(string)
   115  
   116  	info := s.MongoInfo(c)
   117  	opts := mongo.DefaultDialOpts()
   118  	st2, err := state.Open(info, opts, state.Policy(nil))
   119  	defer st2.Close()
   120  
   121  	// Change to an invalid configuration and check
   122  	// that the observer's environment remains the same.
   123  	st2.UpdateEnvironConfig(map[string]interface{}{"type": "invalid"}, nil, nil)
   124  	s.State.StartSync()
   125  
   126  	// Wait for the observer to register the invalid environment
   127  loop:
   128  	for {
   129  		select {
   130  		case msg := <-logc:
   131  			if strings.Contains(msg, "error creating Environ") {
   132  				break loop
   133  			}
   134  		case <-time.After(coretesting.LongWait):
   135  			c.Fatalf("timed out waiting to see broken environment")
   136  		}
   137  	}
   138  	// Check that the returned environ is still the same.
   139  	env = obs.Environ()
   140  	c.Assert(env.Config().AllAttrs(), gc.DeepEquals, originalConfig.AllAttrs())
   141  
   142  	// Change the environment back to a valid configuration
   143  	// with a different name and check that we see it.
   144  	st2.UpdateEnvironConfig(map[string]interface{}{"type": oldType, "name": "a-new-name"}, nil, nil)
   145  	s.State.StartSync()
   146  
   147  	for a := coretesting.LongAttempt.Start(); a.Next(); {
   148  		env := obs.Environ()
   149  		if !a.HasNext() {
   150  			c.Fatalf("timed out waiting for new environ")
   151  		}
   152  		if env.Config().Name() == "a-new-name" {
   153  			break
   154  		}
   155  	}
   156  }
   157  
   158  type logChan chan string
   159  
   160  func (logc logChan) Write(level loggo.Level, name, filename string, line int, timestamp time.Time, message string) {
   161  	logc <- message
   162  }