github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/block_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/state"
    16  	"github.com/juju/juju/testing"
    17  )
    18  
    19  type blockSuite struct {
    20  	ConnSuite
    21  }
    22  
    23  var _ = gc.Suite(&blockSuite{})
    24  
    25  func (s *blockSuite) SetUpTest(c *gc.C) {
    26  	s.ConnSuite.SetUpTest(c)
    27  }
    28  
    29  func assertNoEnvBlock(c *gc.C, st *state.State) {
    30  	all, err := st.AllBlocks()
    31  	c.Assert(err, jc.ErrorIsNil)
    32  	c.Assert(all, gc.HasLen, 0)
    33  }
    34  
    35  func (s *blockSuite) assertNoTypedBlock(c *gc.C, t state.BlockType) {
    36  	one, found, err := s.State.GetBlockForType(t)
    37  	c.Assert(err, jc.ErrorIsNil)
    38  	c.Assert(found, jc.IsFalse)
    39  	c.Assert(one, gc.IsNil)
    40  }
    41  
    42  func assertEnvHasBlock(c *gc.C, st *state.State, t state.BlockType, msg string) {
    43  	dBlock, found, err := st.GetBlockForType(t)
    44  	c.Assert(err, jc.ErrorIsNil)
    45  	c.Assert(found, jc.IsTrue)
    46  	c.Assert(dBlock, gc.NotNil)
    47  	c.Assert(dBlock.Type(), gc.DeepEquals, t)
    48  	tag, err := dBlock.Tag()
    49  	c.Assert(err, jc.ErrorIsNil)
    50  	c.Assert(tag, gc.DeepEquals, st.ModelTag())
    51  	c.Assert(dBlock.Message(), gc.DeepEquals, msg)
    52  }
    53  
    54  func (s *blockSuite) switchOnBlock(c *gc.C, t state.BlockType) string {
    55  	msg := ""
    56  	err := s.State.SwitchBlockOn(t, msg)
    57  	c.Assert(err, jc.ErrorIsNil)
    58  
    59  	assertEnvHasBlock(c, s.State, t, msg)
    60  	return msg
    61  }
    62  
    63  func (s *blockSuite) switchOffBlock(c *gc.C, t state.BlockType) {
    64  	err := s.State.SwitchBlockOff(t)
    65  	c.Assert(err, jc.ErrorIsNil)
    66  	assertNoEnvBlock(c, s.State)
    67  	s.assertNoTypedBlock(c, t)
    68  }
    69  
    70  func (s *blockSuite) assertBlocked(c *gc.C, t state.BlockType) {
    71  	msg := s.switchOnBlock(c, t)
    72  
    73  	expectedErr := fmt.Sprintf(".*block %v is already ON.*", t.String())
    74  	// cannot duplicate
    75  	err := s.State.SwitchBlockOn(t, msg)
    76  	c.Assert(errors.Cause(err), gc.ErrorMatches, expectedErr)
    77  
    78  	// cannot update
    79  	err = s.State.SwitchBlockOn(t, "Test block update")
    80  	c.Assert(errors.Cause(err), gc.ErrorMatches, expectedErr)
    81  
    82  	s.switchOffBlock(c, t)
    83  
    84  	err = s.State.SwitchBlockOff(t)
    85  	expectedErr = fmt.Sprintf(".*block %v is already OFF.*", t.String())
    86  	c.Assert(errors.Cause(err), gc.ErrorMatches, expectedErr)
    87  }
    88  
    89  func (s *blockSuite) TestNewModelNotBlocked(c *gc.C) {
    90  	assertNoEnvBlock(c, s.State)
    91  	s.assertNoTypedBlock(c, state.DestroyBlock)
    92  	s.assertNoTypedBlock(c, state.RemoveBlock)
    93  	s.assertNoTypedBlock(c, state.ChangeBlock)
    94  }
    95  
    96  func (s *blockSuite) TestDestroyBlocked(c *gc.C) {
    97  	s.assertBlocked(c, state.DestroyBlock)
    98  }
    99  
   100  func (s *blockSuite) TestRemoveBlocked(c *gc.C) {
   101  	s.assertBlocked(c, state.RemoveBlock)
   102  }
   103  
   104  func (s *blockSuite) TestChangeBlocked(c *gc.C) {
   105  	s.assertBlocked(c, state.ChangeBlock)
   106  }
   107  
   108  func (s *blockSuite) TestNonsenseBlocked(c *gc.C) {
   109  	bType := state.BlockType(42)
   110  	// This could be useful for entity blocks...
   111  	s.switchOnBlock(c, bType)
   112  	s.switchOffBlock(c, bType)
   113  	// but for multiwatcher, it should panic.
   114  	c.Assert(func() { bType.ToParams() }, gc.PanicMatches, ".*unknown block type.*")
   115  }
   116  
   117  func (s *blockSuite) TestMultiEnvBlocked(c *gc.C) {
   118  	// create another env
   119  	_, st2 := s.createTestEnv(c)
   120  	defer st2.Close()
   121  
   122  	// switch one block type on
   123  	t := state.ChangeBlock
   124  	msg := "another env tst"
   125  	err := st2.SwitchBlockOn(t, msg)
   126  	c.Assert(err, jc.ErrorIsNil)
   127  	assertEnvHasBlock(c, st2, t, msg)
   128  
   129  	//check correct env has it
   130  	assertNoEnvBlock(c, s.State)
   131  	s.assertNoTypedBlock(c, t)
   132  }
   133  
   134  func (s *blockSuite) TestAllBlocksForController(c *gc.C) {
   135  	_, st2 := s.createTestEnv(c)
   136  	defer st2.Close()
   137  
   138  	err := st2.SwitchBlockOn(state.ChangeBlock, "block test")
   139  	c.Assert(err, jc.ErrorIsNil)
   140  	err = s.State.SwitchBlockOn(state.ChangeBlock, "block test")
   141  	c.Assert(err, jc.ErrorIsNil)
   142  
   143  	blocks, err := s.State.AllBlocksForController()
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	c.Assert(len(blocks), gc.Equals, 2)
   146  }
   147  
   148  func (s *blockSuite) TestRemoveAllBlocksForController(c *gc.C) {
   149  	_, st2 := s.createTestEnv(c)
   150  	defer st2.Close()
   151  
   152  	err := st2.SwitchBlockOn(state.ChangeBlock, "block test")
   153  	c.Assert(err, jc.ErrorIsNil)
   154  	err = s.State.SwitchBlockOn(state.ChangeBlock, "block test")
   155  	c.Assert(err, jc.ErrorIsNil)
   156  
   157  	err = s.State.RemoveAllBlocksForController()
   158  	c.Assert(err, jc.ErrorIsNil)
   159  
   160  	blocks, err := s.State.AllBlocksForController()
   161  	c.Assert(err, jc.ErrorIsNil)
   162  	c.Assert(len(blocks), gc.Equals, 0)
   163  }
   164  
   165  func (s *blockSuite) TestRemoveAllBlocksForControllerNoBlocks(c *gc.C) {
   166  	_, st2 := s.createTestEnv(c)
   167  	defer st2.Close()
   168  
   169  	err := st2.RemoveAllBlocksForController()
   170  	c.Assert(err, jc.ErrorIsNil)
   171  
   172  	blocks, err := st2.AllBlocksForController()
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	c.Assert(len(blocks), gc.Equals, 0)
   175  }
   176  
   177  func (s *blockSuite) TestModelUUID(c *gc.C) {
   178  	st := s.Factory.MakeModel(c, nil)
   179  	defer st.Close()
   180  	err := st.SwitchBlockOn(state.ChangeBlock, "blocktest")
   181  	c.Assert(err, jc.ErrorIsNil)
   182  
   183  	blocks, err := st.AllBlocks()
   184  	c.Assert(err, jc.ErrorIsNil)
   185  	c.Assert(len(blocks), gc.Equals, 1)
   186  	c.Assert(blocks[0].ModelUUID(), gc.Equals, st.ModelUUID())
   187  }
   188  
   189  func (s *blockSuite) createTestEnv(c *gc.C) (*state.Model, *state.State) {
   190  	uuid, err := utils.NewUUID()
   191  	c.Assert(err, jc.ErrorIsNil)
   192  	cfg := testing.CustomModelConfig(c, testing.Attrs{
   193  		"name": "testing",
   194  		"uuid": uuid.String(),
   195  	})
   196  	owner := names.NewUserTag("test@remote")
   197  	env, st, err := s.State.NewModel(state.ModelArgs{Config: cfg, Owner: owner})
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	return env, st
   200  }
   201  
   202  func (s *blockSuite) TestConcurrentBlocked(c *gc.C) {
   203  	switchBlockOn := func() {
   204  		msg := ""
   205  		t := state.DestroyBlock
   206  		err := s.State.SwitchBlockOn(t, msg)
   207  		c.Assert(err, jc.ErrorIsNil)
   208  		assertEnvHasBlock(c, s.State, t, msg)
   209  	}
   210  	defer state.SetBeforeHooks(c, s.State, switchBlockOn).Check()
   211  	msg := "concurrency tst"
   212  	t := state.RemoveBlock
   213  	err := s.State.SwitchBlockOn(t, msg)
   214  	c.Assert(err, jc.ErrorIsNil)
   215  	assertEnvHasBlock(c, s.State, t, msg)
   216  }