github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/annotations_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 "github.com/juju/errors" 8 "github.com/juju/names" 9 jc "github.com/juju/testing/checkers" 10 "github.com/juju/utils" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/testing" 15 ) 16 17 type AnnotationsSuite struct { 18 ConnSuite 19 // any entity that implements 20 // state.GlobalEntity will do 21 testEntity *state.Machine 22 } 23 24 var _ = gc.Suite(&AnnotationsSuite{}) 25 26 func (s *AnnotationsSuite) SetUpTest(c *gc.C) { 27 s.ConnSuite.SetUpTest(c) 28 29 var err error 30 s.testEntity, err = s.State.AddMachine("quantal", state.JobHostUnits) 31 c.Assert(err, jc.ErrorIsNil) 32 } 33 34 func (s *AnnotationsSuite) TestSetAnnotationsInvalidKey(c *gc.C) { 35 key := "tes.tkey" 36 expected := "typo" 37 err := s.setAnnotationResult(c, key, expected) 38 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*invalid key.*") 39 } 40 41 func (s *AnnotationsSuite) TestSetAnnotationsCreate(c *gc.C) { 42 s.createTestAnnotation(c) 43 } 44 45 func (s *AnnotationsSuite) createTestAnnotation(c *gc.C) string { 46 key := "testkey" 47 expected := "typo" 48 s.assertSetAnnotation(c, key, expected) 49 assertAnnotation(c, s.State, s.testEntity, key, expected) 50 return key 51 } 52 53 func (s *AnnotationsSuite) setAnnotationResult(c *gc.C, key, value string) error { 54 annts := map[string]string{key: value} 55 return s.State.SetAnnotations(s.testEntity, annts) 56 } 57 58 func (s *AnnotationsSuite) assertSetAnnotation(c *gc.C, key, value string) { 59 err := s.setAnnotationResult(c, key, value) 60 c.Assert(err, jc.ErrorIsNil) 61 } 62 63 func assertAnnotation(c *gc.C, st *state.State, entity state.GlobalEntity, key, expected string) { 64 value, err := st.Annotation(entity, key) 65 c.Assert(err, jc.ErrorIsNil) 66 c.Assert(value, gc.DeepEquals, expected) 67 } 68 69 func (s *AnnotationsSuite) TestSetAnnotationsUpdate(c *gc.C) { 70 key := s.createTestAnnotation(c) 71 updated := "fixed" 72 73 s.assertSetAnnotation(c, key, updated) 74 assertAnnotation(c, s.State, s.testEntity, key, updated) 75 } 76 77 func (s *AnnotationsSuite) TestSetAnnotationsRemove(c *gc.C) { 78 key := s.createTestAnnotation(c) 79 updated := "" 80 s.assertSetAnnotation(c, key, updated) 81 assertAnnotation(c, s.State, s.testEntity, key, updated) 82 83 annts, err := s.State.Annotations(s.testEntity) 84 c.Assert(err, jc.ErrorIsNil) 85 86 // we are expecting not to find this key... 87 for akey := range annts { 88 c.Assert(akey == key, jc.IsFalse) 89 } 90 } 91 92 func (s *AnnotationsSuite) TestSetAnnotationsDestroyedEntity(c *gc.C) { 93 key := s.createTestAnnotation(c) 94 95 err := s.testEntity.ForceDestroy() 96 c.Assert(err, jc.ErrorIsNil) 97 err = s.testEntity.EnsureDead() 98 c.Assert(err, jc.ErrorIsNil) 99 err = s.testEntity.Remove() 100 c.Assert(err, jc.ErrorIsNil) 101 _, err = s.State.Machine(s.testEntity.Id()) 102 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*not found.*") 103 104 annts, err := s.State.Annotations(s.testEntity) 105 c.Assert(err, jc.ErrorIsNil) 106 c.Assert(annts, gc.DeepEquals, map[string]string{}) 107 108 annts[key] = "oops" 109 err = s.State.SetAnnotations(s.testEntity, annts) 110 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*no longer exists.*") 111 c.Assert(err, gc.ErrorMatches, ".*cannot update annotations.*") 112 } 113 114 func (s *AnnotationsSuite) TestSetAnnotationsNonExistentEntity(c *gc.C) { 115 annts := map[string]string{"key": "oops"} 116 err := s.State.SetAnnotations(state.MockGlobalEntity{}, annts) 117 118 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*no longer exists.*") 119 c.Assert(err, gc.ErrorMatches, ".*cannot update annotations.*") 120 } 121 122 func (s *AnnotationsSuite) TestSetAnnotationsConcurrently(c *gc.C) { 123 key := "conkey" 124 first := "alpha" 125 last := "omega" 126 127 setAnnotations := func() { 128 s.assertSetAnnotation(c, key, first) 129 assertAnnotation(c, s.State, s.testEntity, key, first) 130 } 131 defer state.SetBeforeHooks(c, s.State, setAnnotations).Check() 132 s.assertSetAnnotation(c, key, last) 133 assertAnnotation(c, s.State, s.testEntity, key, last) 134 } 135 136 type AnnotationsEnvSuite struct { 137 ConnSuite 138 } 139 140 var _ = gc.Suite(&AnnotationsEnvSuite{}) 141 142 func (s *AnnotationsEnvSuite) SetUpTest(c *gc.C) { 143 s.ConnSuite.SetUpTest(c) 144 s.ConnSuite.PatchValue(&state.TagToCollectionAndId, func(st *state.State, tag names.Tag) (string, interface{}, error) { 145 return "", nil, errors.Errorf("this error should not be reached with current implementation %v", tag) 146 }) 147 } 148 149 func (s *AnnotationsEnvSuite) TestSetAnnotationsDestroyedEnvironment(c *gc.C) { 150 env, st := s.createTestEnv(c) 151 defer st.Close() 152 153 key := "key" 154 expected := "oops" 155 annts := map[string]string{key: expected} 156 err := st.SetAnnotations(env, annts) 157 c.Assert(err, jc.ErrorIsNil) 158 assertAnnotation(c, st, env, key, expected) 159 160 err = env.Destroy() 161 c.Assert(err, jc.ErrorIsNil) 162 err = st.RemoveAllModelDocs() 163 c.Assert(err, jc.ErrorIsNil) 164 err = st.Close() 165 c.Assert(err, jc.ErrorIsNil) 166 167 expected = "fail" 168 annts[key] = expected 169 err = s.State.SetAnnotations(env, annts) 170 c.Assert(errors.Cause(err), gc.ErrorMatches, ".*model not found.*") 171 c.Assert(err, gc.ErrorMatches, ".*cannot update annotations.*") 172 } 173 174 func (s *AnnotationsEnvSuite) createTestEnv(c *gc.C) (*state.Model, *state.State) { 175 uuid, err := utils.NewUUID() 176 c.Assert(err, jc.ErrorIsNil) 177 cfg := testing.CustomModelConfig(c, testing.Attrs{ 178 "name": "testing", 179 "uuid": uuid.String(), 180 }) 181 owner := names.NewUserTag("test@remote") 182 env, st, err := s.State.NewModel(state.ModelArgs{Config: cfg, Owner: owner}) 183 c.Assert(err, jc.ErrorIsNil) 184 return env, st 185 }