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  }