github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/environs/filestorage/filestorage_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package filestorage_test
     5  
     6  // The filestorage structs are used as stubs in tests.
     7  // The tests defined herein are simple smoke tests for the
     8  // required reader and writer functionality.
     9  
    10  import (
    11  	"bytes"
    12  	"io/ioutil"
    13  	"os"
    14  	"path/filepath"
    15  	"strings"
    16  	"testing"
    17  
    18  	"github.com/juju/errors"
    19  	jc "github.com/juju/testing/checkers"
    20  	"github.com/juju/utils"
    21  	gc "launchpad.net/gocheck"
    22  
    23  	"github.com/juju/juju/environs/filestorage"
    24  	"github.com/juju/juju/environs/storage"
    25  )
    26  
    27  func TestPackage(t *testing.T) {
    28  	gc.TestingT(t)
    29  }
    30  
    31  type filestorageSuite struct {
    32  	dir    string
    33  	reader storage.StorageReader
    34  	writer storage.StorageWriter
    35  }
    36  
    37  var _ = gc.Suite(&filestorageSuite{})
    38  
    39  func (s *filestorageSuite) SetUpTest(c *gc.C) {
    40  	s.dir = c.MkDir()
    41  	var err error
    42  	s.reader, err = filestorage.NewFileStorageReader(s.dir)
    43  	c.Assert(err, gc.IsNil)
    44  	s.writer, err = filestorage.NewFileStorageWriter(s.dir)
    45  	c.Assert(err, gc.IsNil)
    46  }
    47  
    48  func (s *filestorageSuite) createFile(c *gc.C, name string) (fullpath string, data []byte) {
    49  	fullpath = filepath.Join(s.dir, name)
    50  	dir := filepath.Dir(fullpath)
    51  	c.Assert(os.MkdirAll(dir, 0755), gc.IsNil)
    52  	data = []byte{1, 2, 3, 4, 5}
    53  	err := ioutil.WriteFile(fullpath, data, 0644)
    54  	c.Assert(err, gc.IsNil)
    55  	return fullpath, data
    56  }
    57  
    58  func (s *filestorageSuite) TestList(c *gc.C) {
    59  	names := []string{
    60  		"a/b/c",
    61  		"a/bb",
    62  		"a/c",
    63  		"aa",
    64  		"b/c/d",
    65  	}
    66  	for _, name := range names {
    67  		s.createFile(c, name)
    68  	}
    69  	type test struct {
    70  		prefix   string
    71  		expected []string
    72  	}
    73  	for i, test := range []test{
    74  		{"a", []string{"a/b/c", "a/bb", "a/c", "aa"}},
    75  		{"a/b", []string{"a/b/c", "a/bb"}},
    76  		{"a/b/c", []string{"a/b/c"}},
    77  		{"", names},
    78  	} {
    79  		c.Logf("test %d: prefix=%q", i, test.prefix)
    80  		files, err := storage.List(s.reader, test.prefix)
    81  		c.Assert(err, gc.IsNil)
    82  		c.Assert(files, gc.DeepEquals, test.expected)
    83  	}
    84  }
    85  
    86  func (s *filestorageSuite) TestListHidesTempDir(c *gc.C) {
    87  	err := s.writer.Put("test-write", bytes.NewReader(nil), 0)
    88  	c.Assert(err, gc.IsNil)
    89  	files, err := storage.List(s.reader, "")
    90  	c.Assert(err, gc.IsNil)
    91  	c.Check(files, gc.DeepEquals, []string{"test-write"})
    92  	files, err = storage.List(s.reader, "no-such-directory")
    93  	c.Assert(err, gc.IsNil)
    94  	c.Check(files, gc.DeepEquals, []string(nil))
    95  	// We also pretend the .tmp directory doesn't exist. If you call a
    96  	// directory that doesn't exist, we just return an empty list of
    97  	// strings, so we force the same behavior for '.tmp'
    98  	// we poke in a file so it would have something to return
    99  	s.createFile(c, ".tmp/test-file")
   100  	files, err = storage.List(s.reader, ".tmp")
   101  	c.Assert(err, gc.IsNil)
   102  	c.Check(files, gc.DeepEquals, []string(nil))
   103  	// For consistency, we refuse all other possibilities as well
   104  	s.createFile(c, ".tmp/foo/bar")
   105  	files, err = storage.List(s.reader, ".tmp/foo")
   106  	c.Assert(err, gc.IsNil)
   107  	c.Check(files, gc.DeepEquals, []string(nil))
   108  	s.createFile(c, ".tmpother/foo")
   109  	files, err = storage.List(s.reader, ".tmpother")
   110  	c.Assert(err, gc.IsNil)
   111  	c.Check(files, gc.DeepEquals, []string(nil))
   112  }
   113  
   114  func (s *filestorageSuite) TestURL(c *gc.C) {
   115  	expectedpath, _ := s.createFile(c, "test-file")
   116  	_, file := filepath.Split(expectedpath)
   117  	url, err := s.reader.URL(file)
   118  	c.Assert(err, gc.IsNil)
   119  	c.Assert(url, gc.Equals, "file://"+expectedpath)
   120  }
   121  
   122  func (s *filestorageSuite) TestGet(c *gc.C) {
   123  	expectedpath, data := s.createFile(c, "test-file")
   124  	_, file := filepath.Split(expectedpath)
   125  	rc, err := storage.Get(s.reader, file)
   126  	c.Assert(err, gc.IsNil)
   127  	defer rc.Close()
   128  	c.Assert(err, gc.IsNil)
   129  	b, err := ioutil.ReadAll(rc)
   130  	c.Assert(err, gc.IsNil)
   131  	c.Assert(b, gc.DeepEquals, data)
   132  
   133  	// Get on a non-existant path returns errors.NotFound
   134  	_, err = s.reader.Get("nowhere")
   135  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   136  
   137  	// Get on a directory returns errors.NotFound
   138  	s.createFile(c, "dir/file")
   139  	_, err = s.reader.Get("dir")
   140  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   141  }
   142  
   143  func (s *filestorageSuite) TestGetRefusesTemp(c *gc.C) {
   144  	s.createFile(c, ".tmp/test-file")
   145  	_, err := storage.Get(s.reader, ".tmp/test-file")
   146  	c.Check(err, gc.NotNil)
   147  	c.Check(err, jc.Satisfies, os.IsNotExist)
   148  	s.createFile(c, ".tmp/foo/test-file")
   149  	_, err = storage.Get(s.reader, ".tmp/foo/test-file")
   150  	c.Check(err, gc.NotNil)
   151  	c.Check(err, jc.Satisfies, os.IsNotExist)
   152  }
   153  
   154  func (s *filestorageSuite) TestPut(c *gc.C) {
   155  	data := []byte{1, 2, 3, 4, 5}
   156  	err := s.writer.Put("test-write", bytes.NewReader(data), int64(len(data)))
   157  	c.Assert(err, gc.IsNil)
   158  	b, err := ioutil.ReadFile(filepath.Join(s.dir, "test-write"))
   159  	c.Assert(err, gc.IsNil)
   160  	c.Assert(b, gc.DeepEquals, data)
   161  }
   162  
   163  func (s *filestorageSuite) TestPutRefusesTmp(c *gc.C) {
   164  	data := []byte{1, 2, 3, 4, 5}
   165  	err := s.writer.Put(".tmp/test-write", bytes.NewReader(data), int64(len(data)))
   166  	c.Assert(err, gc.NotNil)
   167  	c.Check(err, jc.Satisfies, os.IsPermission)
   168  	c.Check(*err.(*os.PathError), gc.Equals, os.PathError{
   169  		Op:   "Put",
   170  		Path: ".tmp/test-write",
   171  		Err:  os.ErrPermission,
   172  	})
   173  	_, err = ioutil.ReadFile(filepath.Join(s.dir, ".tmp", "test-write"))
   174  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   175  }
   176  
   177  func (s *filestorageSuite) TestRemove(c *gc.C) {
   178  	expectedpath, _ := s.createFile(c, "test-file")
   179  	_, file := filepath.Split(expectedpath)
   180  	err := s.writer.Remove(file)
   181  	c.Assert(err, gc.IsNil)
   182  	_, err = ioutil.ReadFile(expectedpath)
   183  	c.Assert(err, gc.Not(gc.IsNil))
   184  }
   185  
   186  func (s *filestorageSuite) TestRemoveAll(c *gc.C) {
   187  	expectedpath, _ := s.createFile(c, "test-file")
   188  	err := s.writer.RemoveAll()
   189  	c.Assert(err, gc.IsNil)
   190  	_, err = ioutil.ReadFile(expectedpath)
   191  	c.Assert(err, gc.Not(gc.IsNil))
   192  }
   193  
   194  func (s *filestorageSuite) TestPutTmpDir(c *gc.C) {
   195  	// Put should create and clean up the temporary directory
   196  	err := s.writer.Put("test-write", bytes.NewReader(nil), 0)
   197  	c.Assert(err, gc.IsNil)
   198  	_, err = os.Stat(s.dir + "/.tmp")
   199  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   200  
   201  	// To deal with recovering from hard failure, we
   202  	// don't care if the temporary directory already exists. It
   203  	// still removes it, though.
   204  	err = os.Mkdir(s.dir+"/.tmp", 0755)
   205  	c.Assert(err, gc.IsNil)
   206  	err = s.writer.Put("test-write", bytes.NewReader(nil), 0)
   207  	c.Assert(err, gc.IsNil)
   208  	_, err = os.Stat(s.dir + "/.tmp")
   209  	c.Assert(err, jc.Satisfies, os.IsNotExist)
   210  }
   211  
   212  func (s *filestorageSuite) TestPathRelativeToHome(c *gc.C) {
   213  	homeDir := utils.Home()
   214  	tempDir, err := ioutil.TempDir(homeDir, "")
   215  	c.Assert(err, gc.IsNil)
   216  	defer os.RemoveAll(tempDir)
   217  	dirName := strings.Replace(tempDir, homeDir, "", -1)
   218  	reader, err := filestorage.NewFileStorageReader(filepath.Join("~", dirName))
   219  	c.Assert(err, gc.IsNil)
   220  	url, err := reader.URL("")
   221  	c.Assert(err, gc.IsNil)
   222  	c.Assert(url, gc.Equals, "file://"+filepath.Join(homeDir, dirName))
   223  }
   224  
   225  func (s *filestorageSuite) TestRelativePath(c *gc.C) {
   226  	dir := c.MkDir()
   227  	err := os.MkdirAll(filepath.Join(dir, "a", "b", "c"), os.ModePerm)
   228  	c.Assert(err, gc.IsNil)
   229  	cwd, err := os.Getwd()
   230  	c.Assert(err, gc.IsNil)
   231  	err = os.Chdir(filepath.Join(dir, "a", "b", "c"))
   232  	c.Assert(err, gc.IsNil)
   233  	defer os.Chdir(cwd)
   234  	reader, err := filestorage.NewFileStorageReader("../..")
   235  	c.Assert(err, gc.IsNil)
   236  	url, err := reader.URL("")
   237  	c.Assert(err, gc.IsNil)
   238  	c.Assert(url, gc.Equals, "file://"+dir+"/a")
   239  }