github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/wrench/wrench_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package wrench_test 5 6 import ( 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "runtime" 11 stdtesting "testing" 12 13 "github.com/juju/loggo" 14 jc "github.com/juju/testing/checkers" 15 gc "gopkg.in/check.v1" 16 17 coretesting "github.com/juju/juju/testing" 18 "github.com/juju/juju/wrench" 19 ) 20 21 func TestPackage(t *stdtesting.T) { 22 gc.TestingT(t) 23 } 24 25 type wrenchSuite struct { 26 coretesting.BaseSuite 27 wrenchDir string 28 logWriter loggo.TestWriter 29 } 30 31 var _ = gc.Suite(&wrenchSuite{}) 32 33 func (s *wrenchSuite) SetUpTest(c *gc.C) { 34 s.BaseSuite.SetUpTest(c) 35 // BaseSuite turns off wrench so restore the non-testing default. 36 wrench.SetEnabled(true) 37 c.Assert(loggo.RegisterWriter("wrench-tests", &s.logWriter, loggo.TRACE), gc.IsNil) 38 s.AddCleanup(func(*gc.C) { 39 s.logWriter.Clear() 40 loggo.RemoveWriter("wrench-tests") 41 // Ensure the wrench is turned off when these tests are done. 42 wrench.SetEnabled(false) 43 }) 44 } 45 46 func (s *wrenchSuite) createWrenchDir(c *gc.C) { 47 s.wrenchDir = c.MkDir() 48 s.PatchValue(wrench.WrenchDir, s.wrenchDir) 49 } 50 51 func (s *wrenchSuite) createWrenchFile(c *gc.C, name, content string) string { 52 filename := filepath.Join(s.wrenchDir, name) 53 err := ioutil.WriteFile(filename, []byte(content), 0700) 54 c.Assert(err, jc.ErrorIsNil) 55 return filename 56 } 57 58 func (s *wrenchSuite) TestIsActive(c *gc.C) { 59 s.createWrenchDir(c) 60 s.createWrenchFile(c, "foo", "bar") 61 c.Assert(wrench.IsActive("foo", "bar"), jc.IsTrue) 62 s.AssertActivationLogged(c) 63 } 64 65 func (s *wrenchSuite) TestIsActiveWithWhitespace(c *gc.C) { 66 s.createWrenchDir(c) 67 s.createWrenchFile(c, "foo", "\tbar ") 68 c.Assert(wrench.IsActive("foo", "bar"), jc.IsTrue) 69 s.AssertActivationLogged(c) 70 } 71 72 func (s *wrenchSuite) TestIsActiveMultiFeatures(c *gc.C) { 73 s.createWrenchDir(c) 74 s.createWrenchFile(c, "foo", "one\ntwo\nbar\n") 75 c.Assert(wrench.IsActive("foo", "bar"), jc.IsTrue) 76 s.AssertActivationLogged(c) 77 } 78 79 func (s *wrenchSuite) TestIsActiveMultiFeaturesWithMixedNewlines(c *gc.C) { 80 s.createWrenchDir(c) 81 s.createWrenchFile(c, "foo", "one\ntwo\r\nthree\nbar\n") 82 c.Assert(wrench.IsActive("foo", "bar"), jc.IsTrue) 83 s.AssertActivationLogged(c) 84 } 85 86 func (s *wrenchSuite) TestNotActive(c *gc.C) { 87 s.createWrenchDir(c) 88 s.createWrenchFile(c, "foo", "abc") 89 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 90 s.AssertNothingLogged(c) 91 } 92 93 func (s *wrenchSuite) TestNoFile(c *gc.C) { 94 s.createWrenchDir(c) 95 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 96 s.AssertFileErrorLogged(c) 97 } 98 99 func (s *wrenchSuite) TestMatchInOtherCategory(c *gc.C) { 100 s.createWrenchDir(c) 101 s.createWrenchFile(c, "other", "bar") 102 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 103 s.AssertFileErrorLogged(c) 104 } 105 106 func (s *wrenchSuite) TestNoDirectory(c *gc.C) { 107 s.PatchValue(wrench.WrenchDir, "/does/not/exist") 108 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 109 s.AssertDirErrorLogged(c) 110 } 111 112 func (s *wrenchSuite) TestFileNotOwnedByJujuUser(c *gc.C) { 113 s.createWrenchDir(c) 114 filename := s.createWrenchFile(c, "foo", "bar") 115 s.tweakOwner(c, filename) 116 117 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 118 119 c.Assert(s.logWriter.Log(), jc.LogMatches, []jc.SimpleMessage{{ 120 loggo.ERROR, 121 `wrench file for foo/bar has incorrect ownership - ignoring ` + filename, 122 }}) 123 } 124 125 func (s *wrenchSuite) TestFilePermsTooLoose(c *gc.C) { 126 if runtime.GOOS == "windows" { 127 c.Skip("Windows is not fully POSIX compliant") 128 } 129 s.createWrenchDir(c) 130 filename := s.createWrenchFile(c, "foo", "bar") 131 err := os.Chmod(filename, 0666) 132 c.Assert(err, jc.ErrorIsNil) 133 134 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 135 136 c.Assert(s.logWriter.Log(), jc.LogMatches, []jc.SimpleMessage{{ 137 loggo.ERROR, 138 `wrench file for foo/bar should only be writable by owner - ignoring ` + filename, 139 }}) 140 } 141 142 func (s *wrenchSuite) TestDirectoryNotOwnedByJujuUser(c *gc.C) { 143 s.createWrenchDir(c) 144 s.tweakOwner(c, s.wrenchDir) 145 146 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 147 148 c.Assert(s.logWriter.Log(), jc.LogMatches, []jc.SimpleMessage{{ 149 loggo.ERROR, 150 `wrench directory has incorrect ownership - wrench functionality disabled \(.+\)`, 151 }}) 152 } 153 154 func (s *wrenchSuite) TestSetEnabled(c *gc.C) { 155 s.createWrenchDir(c) 156 s.createWrenchFile(c, "foo", "bar") 157 158 // Starts enabled. 159 c.Assert(wrench.IsEnabled(), jc.IsTrue) 160 c.Assert(wrench.IsActive("foo", "bar"), jc.IsTrue) 161 162 // Disable. 163 c.Assert(wrench.SetEnabled(false), jc.IsTrue) 164 c.Assert(wrench.IsEnabled(), jc.IsFalse) 165 c.Assert(wrench.IsActive("foo", "bar"), jc.IsFalse) 166 167 // Enable again. 168 c.Assert(wrench.SetEnabled(true), jc.IsFalse) 169 c.Assert(wrench.IsEnabled(), jc.IsTrue) 170 c.Assert(wrench.IsActive("foo", "bar"), jc.IsTrue) 171 } 172 173 var notJujuUid = uint32(os.Getuid() + 1) 174 175 func (s *wrenchSuite) AssertActivationLogged(c *gc.C) { 176 c.Assert(s.logWriter.Log(), jc.LogMatches, []jc.SimpleMessage{ 177 {loggo.WARNING, `wrench for foo/bar is active`}}) 178 } 179 180 func (s *wrenchSuite) AssertNothingLogged(c *gc.C) { 181 c.Assert(len(s.logWriter.Log()), gc.Equals, 0) 182 } 183 184 func (s *wrenchSuite) AssertFileErrorLogged(c *gc.C) { 185 c.Assert(s.logWriter.Log(), jc.LogMatches, []jc.SimpleMessage{ 186 {loggo.DEBUG, `no wrench data for foo/bar \(ignored\): ` + fileNotFound}}) 187 } 188 189 func (s *wrenchSuite) AssertDirErrorLogged(c *gc.C) { 190 c.Assert(s.logWriter.Log(), jc.LogMatches, []jc.SimpleMessage{ 191 {loggo.DEBUG, `couldn't read wrench directory: ` + fileNotFound}}) 192 }