diff --git a/fs_test.go b/fs_test.go index 5670d2c..1a7d00c 100644 --- a/fs_test.go +++ b/fs_test.go @@ -4,18 +4,11 @@ import ( "testing" . "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/go-git/go-billy/v5/internal/test" + "github.com/stretchr/testify/assert" ) -type FSSuite struct{} - -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&FSSuite{}) - -func (s *FSSuite) TestCapabilities(c *C) { +func TestCapabilities(t *testing.T) { cases := []struct { caps Capability expected bool @@ -32,9 +25,9 @@ func (s *FSSuite) TestCapabilities(c *C) { fs := new(test.NoLockCapFs) for _, e := range cases { - c.Assert(CapabilityCheck(fs, e.caps), Equals, e.expected) + assert.Equal(t, CapabilityCheck(fs, e.caps), e.expected) } dummy := new(test.BasicMock) - c.Assert(Capabilities(dummy), Equals, DefaultCapabilities) + assert.Equal(t, Capabilities(dummy), DefaultCapabilities) } diff --git a/go.mod b/go.mod index b044530..3effeb2 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,10 @@ require ( github.com/cyphar/filepath-securejoin v0.2.4 github.com/stretchr/testify v1.9.0 golang.org/x/sys v0.19.0 - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c ) require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 6ac1642..ce946af 100644 --- a/go.sum +++ b/go.sum @@ -1,27 +1,14 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/helper/chroot/chroot_test.go b/helper/chroot/chroot_test.go index 2f81c25..64a1be0 100644 --- a/helper/chroot/chroot_test.go +++ b/helper/chroot/chroot_test.go @@ -6,363 +6,356 @@ import ( "testing" "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/go-git/go-billy/v5/internal/test" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&ChrootSuite{}) - -type ChrootSuite struct{} - -func (s *ChrootSuite) TestCreate(c *C) { +func TestCreate(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") f, err := fs.Create("bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) + assert.NoError(t, err) + assert.Equal(t, f.Name(), filepath.Join("bar", "qux")) - c.Assert(m.CreateArgs, HasLen, 1) - c.Assert(m.CreateArgs[0], Equals, "/foo/bar/qux") + assert.Len(t, m.CreateArgs, 1) + assert.Equal(t, m.CreateArgs[0], "/foo/bar/qux") } -func (s *ChrootSuite) TestCreateErrCrossedBoundary(c *C) { +func TestCreateErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.Create("../foo") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestLeadingPeriodsPathNotCrossedBoundary(c *C) { +func TestLeadingPeriodsPathNotCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") f, err := fs.Create("..foo") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "..foo") + assert.NoError(t, err) + assert.Equal(t, f.Name(), "..foo") } -func (s *ChrootSuite) TestOpen(c *C) { +func TestOpen(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") f, err := fs.Open("bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) + assert.NoError(t, err) + assert.Equal(t, f.Name(), filepath.Join("bar", "qux")) - c.Assert(m.OpenArgs, HasLen, 1) - c.Assert(m.OpenArgs[0], Equals, "/foo/bar/qux") + assert.Len(t, m.OpenArgs, 1) + assert.Equal(t, m.OpenArgs[0], "/foo/bar/qux") } -func (s *ChrootSuite) TestChroot(c *C) { +func TestChroot(t *testing.T) { m := &test.BasicMock{} fs, _ := New(m, "/foo").Chroot("baz") f, err := fs.Open("bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) + assert.NoError(t, err) + assert.Equal(t, f.Name(), filepath.Join("bar", "qux")) - c.Assert(m.OpenArgs, HasLen, 1) - c.Assert(m.OpenArgs[0], Equals, "/foo/baz/bar/qux") + assert.Len(t, m.OpenArgs, 1) + assert.Equal(t, m.OpenArgs[0], "/foo/baz/bar/qux") } -func (s *ChrootSuite) TestChrootErrCrossedBoundary(c *C) { +func TestChrootErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs, err := New(m, "/foo").Chroot("../qux") - c.Assert(fs, IsNil) - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.Nil(t, fs) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestOpenErrCrossedBoundary(c *C) { +func TestOpenErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.Open("../foo") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestOpenFile(c *C) { +func TestOpenFile(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") f, err := fs.OpenFile("bar/qux", 42, 0777) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) + assert.NoError(t, err) + assert.Equal(t, f.Name(), filepath.Join("bar", "qux")) - c.Assert(m.OpenFileArgs, HasLen, 1) - c.Assert(m.OpenFileArgs[0], Equals, [3]interface{}{"/foo/bar/qux", 42, os.FileMode(0777)}) + assert.Len(t, m.OpenFileArgs, 1) + assert.Equal(t, m.OpenFileArgs[0], [3]interface{}{"/foo/bar/qux", 42, os.FileMode(0777)}) } -func (s *ChrootSuite) TestOpenFileErrCrossedBoundary(c *C) { +func TestOpenFileErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.OpenFile("../foo", 42, 0777) - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestStat(c *C) { +func TestStat(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.Stat("bar/qux") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.StatArgs, HasLen, 1) - c.Assert(m.StatArgs[0], Equals, "/foo/bar/qux") + assert.Len(t, m.StatArgs, 1) + assert.Equal(t, m.StatArgs[0], "/foo/bar/qux") } -func (s *ChrootSuite) TestStatErrCrossedBoundary(c *C) { +func TestStatErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.Stat("../foo") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestRename(c *C) { +func TestRename(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") err := fs.Rename("bar/qux", "qux/bar") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.RenameArgs, HasLen, 1) - c.Assert(m.RenameArgs[0], Equals, [2]string{"/foo/bar/qux", "/foo/qux/bar"}) + assert.Len(t, m.RenameArgs, 1) + assert.Equal(t, m.RenameArgs[0], [2]string{"/foo/bar/qux", "/foo/qux/bar"}) } -func (s *ChrootSuite) TestRenameErrCrossedBoundary(c *C) { +func TestRenameErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") err := fs.Rename("../foo", "bar") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) err = fs.Rename("foo", "../bar") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestRemove(c *C) { +func TestRemove(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") err := fs.Remove("bar/qux") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.RemoveArgs, HasLen, 1) - c.Assert(m.RemoveArgs[0], Equals, "/foo/bar/qux") + assert.Len(t, m.RemoveArgs, 1) + assert.Equal(t, m.RemoveArgs[0], "/foo/bar/qux") } -func (s *ChrootSuite) TestRemoveErrCrossedBoundary(c *C) { +func TestRemoveErrCrossedBoundary(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") err := fs.Remove("../foo") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestTempFile(c *C) { +func TestTempFile(t *testing.T) { m := &test.TempFileMock{} fs := New(m, "/foo") _, err := fs.TempFile("bar", "qux") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.TempFileArgs, HasLen, 1) - c.Assert(m.TempFileArgs[0], Equals, [2]string{"/foo/bar", "qux"}) + assert.Len(t, m.TempFileArgs, 1) + assert.Equal(t, m.TempFileArgs[0], [2]string{"/foo/bar", "qux"}) } -func (s *ChrootSuite) TestTempFileErrCrossedBoundary(c *C) { +func TestTempFileErrCrossedBoundary(t *testing.T) { m := &test.TempFileMock{} fs := New(m, "/foo") _, err := fs.TempFile("../foo", "qux") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestTempFileWithBasic(c *C) { +func TestTempFileWithBasic(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.TempFile("", "") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *ChrootSuite) TestReadDir(c *C) { +func TestReadDir(t *testing.T) { m := &test.DirMock{} fs := New(m, "/foo") _, err := fs.ReadDir("bar") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.ReadDirArgs, HasLen, 1) - c.Assert(m.ReadDirArgs[0], Equals, "/foo/bar") + assert.Len(t, m.ReadDirArgs, 1) + assert.Equal(t, m.ReadDirArgs[0], "/foo/bar") } -func (s *ChrootSuite) TestReadDirErrCrossedBoundary(c *C) { +func TestReadDirErrCrossedBoundary(t *testing.T) { m := &test.DirMock{} fs := New(m, "/foo") _, err := fs.ReadDir("../foo") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestReadDirWithBasic(c *C) { +func TestReadDirWithBasic(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.ReadDir("") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *ChrootSuite) TestMkDirAll(c *C) { +func TestMkDirAll(t *testing.T) { m := &test.DirMock{} fs := New(m, "/foo") err := fs.MkdirAll("bar", 0777) - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.MkdirAllArgs, HasLen, 1) - c.Assert(m.MkdirAllArgs[0], Equals, [2]interface{}{"/foo/bar", os.FileMode(0777)}) + assert.Len(t, m.MkdirAllArgs, 1) + assert.Equal(t, m.MkdirAllArgs[0], [2]interface{}{"/foo/bar", os.FileMode(0777)}) } -func (s *ChrootSuite) TestMkdirAllErrCrossedBoundary(c *C) { +func TestMkdirAllErrCrossedBoundary(t *testing.T) { m := &test.DirMock{} fs := New(m, "/foo") err := fs.MkdirAll("../foo", 0777) - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestMkdirAllWithBasic(c *C) { +func TestMkdirAllWithBasic(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") err := fs.MkdirAll("", 0) - c.Assert(err, Equals, billy.ErrNotSupported) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *ChrootSuite) TestLstat(c *C) { +func TestLstat(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") _, err := fs.Lstat("qux") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.LstatArgs, HasLen, 1) - c.Assert(m.LstatArgs[0], Equals, "/foo/qux") + assert.Len(t, m.LstatArgs, 1) + assert.Equal(t, m.LstatArgs[0], "/foo/qux") } -func (s *ChrootSuite) TestLstatErrCrossedBoundary(c *C) { +func TestLstatErrCrossedBoundary(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") _, err := fs.Lstat("../qux") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestLstatWithBasic(c *C) { +func TestLstatWithBasic(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.Lstat("") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *ChrootSuite) TestSymlink(c *C) { +func TestSymlink(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") err := fs.Symlink("../baz", "qux/bar") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.SymlinkArgs, HasLen, 1) - c.Assert(m.SymlinkArgs[0], Equals, [2]string{filepath.FromSlash("../baz"), "/foo/qux/bar"}) + assert.Len(t, m.SymlinkArgs, 1) + assert.Equal(t, m.SymlinkArgs[0], [2]string{filepath.FromSlash("../baz"), "/foo/qux/bar"}) } -func (s *ChrootSuite) TestSymlinkWithAbsoluteTarget(c *C) { +func TestSymlinkWithAbsoluteTarget(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") err := fs.Symlink("/bar", "qux/baz") - c.Assert(err, IsNil) + assert.NoError(t, err) - c.Assert(m.SymlinkArgs, HasLen, 1) - c.Assert(m.SymlinkArgs[0], Equals, [2]string{filepath.FromSlash("/foo/bar"), "/foo/qux/baz"}) + assert.Len(t, m.SymlinkArgs, 1) + assert.Equal(t, m.SymlinkArgs[0], [2]string{filepath.FromSlash("/foo/bar"), "/foo/qux/baz"}) } -func (s *ChrootSuite) TestSymlinkErrCrossedBoundary(c *C) { +func TestSymlinkErrCrossedBoundary(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") err := fs.Symlink("qux", "../foo") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestSymlinkWithBasic(c *C) { +func TestSymlinkWithBasic(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") err := fs.Symlink("qux", "bar") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *ChrootSuite) TestReadlink(c *C) { +func TestReadlink(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") link, err := fs.Readlink("/qux") - c.Assert(err, IsNil) - c.Assert(link, Equals, filepath.FromSlash("/qux")) + assert.NoError(t, err) + assert.Equal(t, link, filepath.FromSlash("/qux")) - c.Assert(m.ReadlinkArgs, HasLen, 1) - c.Assert(m.ReadlinkArgs[0], Equals, "/foo/qux") + assert.Len(t, m.ReadlinkArgs, 1) + assert.Equal(t, m.ReadlinkArgs[0], "/foo/qux") } -func (s *ChrootSuite) TestReadlinkWithRelative(c *C) { +func TestReadlinkWithRelative(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") link, err := fs.Readlink("qux/bar") - c.Assert(err, IsNil) - c.Assert(link, Equals, filepath.FromSlash("/qux/bar")) + assert.NoError(t, err) + assert.Equal(t, link, filepath.FromSlash("/qux/bar")) - c.Assert(m.ReadlinkArgs, HasLen, 1) - c.Assert(m.ReadlinkArgs[0], Equals, "/foo/qux/bar") + assert.Len(t, m.ReadlinkArgs, 1) + assert.Equal(t, m.ReadlinkArgs[0], "/foo/qux/bar") } -func (s *ChrootSuite) TestReadlinkErrCrossedBoundary(c *C) { +func TestReadlinkErrCrossedBoundary(t *testing.T) { m := &test.SymlinkMock{} fs := New(m, "/foo") _, err := fs.Readlink("../qux") - c.Assert(err, Equals, billy.ErrCrossedBoundary) + assert.ErrorIs(t, err, billy.ErrCrossedBoundary) } -func (s *ChrootSuite) TestReadlinkWithBasic(c *C) { +func TestReadlinkWithBasic(t *testing.T) { m := &test.BasicMock{} fs := New(m, "/foo") _, err := fs.Readlink("") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *ChrootSuite) TestCapabilities(c *C) { - testCapabilities(c, new(test.BasicMock)) - testCapabilities(c, new(test.OnlyReadCapFs)) - testCapabilities(c, new(test.NoLockCapFs)) +func TestCapabilities(t *testing.T) { + testCapabilities(t, new(test.BasicMock)) + testCapabilities(t, new(test.OnlyReadCapFs)) + testCapabilities(t, new(test.NoLockCapFs)) } -func testCapabilities(c *C, basic billy.Basic) { +func testCapabilities(t *testing.T, basic billy.Basic) { baseCapabilities := billy.Capabilities(basic) fs := New(basic, "/foo") capabilities := billy.Capabilities(fs) - c.Assert(capabilities, Equals, baseCapabilities) + assert.Equal(t, capabilities, baseCapabilities) } diff --git a/helper/mount/mount_test.go b/helper/mount/mount_test.go index ec09f05..d980151 100644 --- a/helper/mount/mount_test.go +++ b/helper/mount/mount_test.go @@ -6,158 +6,166 @@ import ( "testing" "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/internal/test" "github.com/go-git/go-billy/v5/memfs" - "github.com/go-git/go-billy/v5/test" "github.com/go-git/go-billy/v5/util" - - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&MountSuite{}) - -type MountSuite struct { - Helper *Mount - Underlying mock - Source mock -} - type mock struct { test.BasicMock test.DirMock test.SymlinkMock } -func (s *MountSuite) SetUpTest(c *C) { - s.Underlying.BasicMock = test.BasicMock{} - s.Underlying.DirMock = test.DirMock{} - s.Underlying.SymlinkMock = test.SymlinkMock{} - s.Source.BasicMock = test.BasicMock{} - s.Source.DirMock = test.DirMock{} - s.Source.SymlinkMock = test.SymlinkMock{} +func setup() (helper *Mount, underlying *mock, source *mock) { + underlying = &mock{ + BasicMock: test.BasicMock{}, + DirMock: test.DirMock{}, + SymlinkMock: test.SymlinkMock{}, + } + + source = &mock{ + BasicMock: test.BasicMock{}, + DirMock: test.DirMock{}, + SymlinkMock: test.SymlinkMock{}, + } - s.Helper = New(&s.Underlying, "/foo", &s.Source) + helper = New(underlying, "/foo", source) + return } -func (s *MountSuite) TestCreate(c *C) { - f, err := s.Helper.Create("bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) +func TestCreate(t *testing.T) { + helper, underlying, source := setup() + f, err := helper.Create("bar/qux") + assert.NoError(t, err) + assert.Equal(t, filepath.Join("bar", "qux"), f.Name()) - c.Assert(s.Underlying.CreateArgs, HasLen, 1) - c.Assert(s.Underlying.CreateArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.CreateArgs, HasLen, 0) + assert.Len(t, underlying.CreateArgs, 1) + assert.Equal(t, filepath.Join("bar", "qux"), underlying.CreateArgs[0]) + assert.Len(t, source.CreateArgs, 0) } -func (s *MountSuite) TestCreateMountPoint(c *C) { - f, err := s.Helper.Create("foo") - c.Assert(f, IsNil) - c.Assert(err, Equals, os.ErrInvalid) +func TestCreateMountPoint(t *testing.T) { + helper, _, _ := setup() + f, err := helper.Create("foo") + assert.Nil(t, f) + assert.ErrorIs(t, err, os.ErrInvalid) } -func (s *MountSuite) TestCreateInMount(c *C) { - f, err := s.Helper.Create("foo/bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("foo", "bar", "qux")) +func TestCreateInMount(t *testing.T) { + helper, underlying, source := setup() + f, err := helper.Create("foo/bar/qux") + assert.NoError(t, err) + assert.Equal(t, filepath.Join("foo", "bar", "qux"), f.Name()) - c.Assert(s.Underlying.CreateArgs, HasLen, 0) - c.Assert(s.Source.CreateArgs, HasLen, 1) - c.Assert(s.Source.CreateArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.CreateArgs, 0) + assert.Len(t, source.CreateArgs, 1) + assert.Equal(t, filepath.Join("bar", "qux"), source.CreateArgs[0]) } -func (s *MountSuite) TestOpen(c *C) { - f, err := s.Helper.Open("bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) +func TestOpen(t *testing.T) { + helper, underlying, source := setup() + f, err := helper.Open("bar/qux") + assert.NoError(t, err) + assert.Equal(t, filepath.Join("bar", "qux"), f.Name()) - c.Assert(s.Underlying.OpenArgs, HasLen, 1) - c.Assert(s.Underlying.OpenArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.OpenArgs, HasLen, 0) + assert.Len(t, underlying.OpenArgs, 1) + assert.Equal(t, filepath.Join("bar", "qux"), underlying.OpenArgs[0]) + assert.Len(t, source.OpenArgs, 0) } -func (s *MountSuite) TestOpenMountPoint(c *C) { - f, err := s.Helper.Open("foo") - c.Assert(f, IsNil) - c.Assert(err, Equals, os.ErrInvalid) +func TestOpenMountPoint(t *testing.T) { + helper, _, _ := setup() + f, err := helper.Open("foo") + assert.Nil(t, f) + assert.ErrorIs(t, err, os.ErrInvalid) } -func (s *MountSuite) TestOpenInMount(c *C) { - f, err := s.Helper.Open("foo/bar/qux") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("foo", "bar", "qux")) +func TestOpenInMount(t *testing.T) { + helper, underlying, source := setup() + f, err := helper.Open("foo/bar/qux") + assert.NoError(t, err) + assert.Equal(t, filepath.Join("foo", "bar", "qux"), f.Name()) - c.Assert(s.Underlying.OpenArgs, HasLen, 0) - c.Assert(s.Source.OpenArgs, HasLen, 1) - c.Assert(s.Source.OpenArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.OpenArgs, 0) + assert.Len(t, source.OpenArgs, 1) + assert.Equal(t, source.OpenArgs[0], filepath.Join("bar", "qux")) } -func (s *MountSuite) TestOpenFile(c *C) { - f, err := s.Helper.OpenFile("bar/qux", 42, 0777) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("bar", "qux")) +func TestOpenFile(t *testing.T) { + helper, underlying, source := setup() + f, err := helper.OpenFile("bar/qux", 42, 0777) + assert.NoError(t, err) + assert.Equal(t, filepath.Join("bar", "qux"), f.Name()) - c.Assert(s.Underlying.OpenFileArgs, HasLen, 1) - c.Assert(s.Underlying.OpenFileArgs[0], Equals, + assert.Len(t, underlying.OpenFileArgs, 1) + assert.Equal(t, underlying.OpenFileArgs[0], [3]interface{}{filepath.Join("bar", "qux"), 42, os.FileMode(0777)}) - c.Assert(s.Source.OpenFileArgs, HasLen, 0) + assert.Len(t, source.OpenFileArgs, 0) } -func (s *MountSuite) TestOpenFileMountPoint(c *C) { - f, err := s.Helper.OpenFile("foo", 42, 0777) - c.Assert(f, IsNil) - c.Assert(err, Equals, os.ErrInvalid) +func TestOpenFileMountPoint(t *testing.T) { + helper, _, _ := setup() + f, err := helper.OpenFile("foo", 42, 0777) + assert.Nil(t, f) + assert.ErrorIs(t, err, os.ErrInvalid) } -func (s *MountSuite) TestOpenFileInMount(c *C) { - f, err := s.Helper.OpenFile("foo/bar/qux", 42, 0777) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, filepath.Join("foo", "bar", "qux")) +func TestOpenFileInMount(t *testing.T) { + helper, underlying, source := setup() + f, err := helper.OpenFile("foo/bar/qux", 42, 0777) + assert.NoError(t, err) + assert.Equal(t, filepath.Join("foo", "bar", "qux"), f.Name()) - c.Assert(s.Underlying.OpenFileArgs, HasLen, 0) - c.Assert(s.Source.OpenFileArgs, HasLen, 1) - c.Assert(s.Source.OpenFileArgs[0], Equals, + assert.Len(t, underlying.OpenFileArgs, 0) + assert.Len(t, source.OpenFileArgs, 1) + assert.Equal(t, source.OpenFileArgs[0], [3]interface{}{filepath.Join("bar", "qux"), 42, os.FileMode(0777)}) } -func (s *MountSuite) TestStat(c *C) { - _, err := s.Helper.Stat("bar/qux") - c.Assert(err, IsNil) +func TestStat(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.Stat("bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.StatArgs, HasLen, 1) - c.Assert(s.Underlying.StatArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.StatArgs, HasLen, 0) + assert.Len(t, underlying.StatArgs, 1) + assert.Equal(t, underlying.StatArgs[0], filepath.Join("bar", "qux")) + assert.Len(t, source.StatArgs, 0) } -func (s *MountSuite) TestStatInMount(c *C) { - _, err := s.Helper.Stat("foo/bar/qux") - c.Assert(err, IsNil) +func TestStatInMount(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.Stat("foo/bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.StatArgs, HasLen, 0) - c.Assert(s.Source.StatArgs, HasLen, 1) - c.Assert(s.Source.StatArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.StatArgs, 0) + assert.Len(t, source.StatArgs, 1) + assert.Equal(t, source.StatArgs[0], filepath.Join("bar", "qux")) } -func (s *MountSuite) TestRename(c *C) { - err := s.Helper.Rename("bar/qux", "qux") - c.Assert(err, IsNil) +func TestRename(t *testing.T) { + helper, underlying, source := setup() + err := helper.Rename("bar/qux", "qux") + assert.NoError(t, err) - c.Assert(s.Underlying.RenameArgs, HasLen, 1) - c.Assert(s.Underlying.RenameArgs[0], Equals, [2]string{"bar/qux", "qux"}) - c.Assert(s.Source.RenameArgs, HasLen, 0) + assert.Len(t, underlying.RenameArgs, 1) + assert.Equal(t, underlying.RenameArgs[0], [2]string{"bar/qux", "qux"}) + assert.Len(t, source.RenameArgs, 0) } -func (s *MountSuite) TestRenameInMount(c *C) { - err := s.Helper.Rename("foo/bar/qux", "foo/qux") - c.Assert(err, IsNil) +func TestRenameInMount(t *testing.T) { + helper, underlying, source := setup() + err := helper.Rename("foo/bar/qux", "foo/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.RenameArgs, HasLen, 0) - c.Assert(s.Source.RenameArgs, HasLen, 1) - c.Assert(s.Source.RenameArgs[0], Equals, + assert.Len(t, underlying.RenameArgs, 0) + assert.Len(t, source.RenameArgs, 1) + assert.Equal(t, source.RenameArgs[0], [2]string{filepath.Join("bar", "qux"), "qux"}) } -func (s *MountSuite) TestRenameCross(c *C) { +func TestRenameCross(t *testing.T) { underlying := memfs.New() source := memfs.New() @@ -165,192 +173,208 @@ func (s *MountSuite) TestRenameCross(c *C) { fs := New(underlying, "/foo", source) err := fs.Rename("file", "foo/file") - c.Assert(err, IsNil) + assert.NoError(t, err) _, err = underlying.Stat("file") - c.Assert(err, Equals, os.ErrNotExist) + assert.Equal(t, err, os.ErrNotExist) _, err = source.Stat("file") - c.Assert(err, IsNil) + assert.NoError(t, err) err = fs.Rename("foo/file", "file") - c.Assert(err, IsNil) + assert.NoError(t, err) _, err = underlying.Stat("file") - c.Assert(err, IsNil) + assert.NoError(t, err) _, err = source.Stat("file") - c.Assert(err, Equals, os.ErrNotExist) + assert.Equal(t, err, os.ErrNotExist) } -func (s *MountSuite) TestRemove(c *C) { - err := s.Helper.Remove("bar/qux") - c.Assert(err, IsNil) +func TestRemove(t *testing.T) { + helper, underlying, source := setup() + err := helper.Remove("bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.RemoveArgs, HasLen, 1) - c.Assert(s.Underlying.RemoveArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.RemoveArgs, HasLen, 0) + assert.Len(t, underlying.RemoveArgs, 1) + assert.Equal(t, underlying.RemoveArgs[0], filepath.Join("bar", "qux")) + assert.Len(t, source.RemoveArgs, 0) } -func (s *MountSuite) TestRemoveMountPoint(c *C) { - err := s.Helper.Remove("foo") - c.Assert(err, Equals, os.ErrInvalid) +func TestRemoveMountPoint(t *testing.T) { + helper, _, _ := setup() + err := helper.Remove("foo") + assert.ErrorIs(t, err, os.ErrInvalid) } -func (s *MountSuite) TestRemoveInMount(c *C) { - err := s.Helper.Remove("foo/bar/qux") - c.Assert(err, IsNil) +func TestRemoveInMount(t *testing.T) { + helper, underlying, source := setup() + err := helper.Remove("foo/bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.RemoveArgs, HasLen, 0) - c.Assert(s.Source.RemoveArgs, HasLen, 1) - c.Assert(s.Source.RemoveArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.RemoveArgs, 0) + assert.Len(t, source.RemoveArgs, 1) + assert.Equal(t, source.RemoveArgs[0], filepath.Join("bar", "qux")) } -func (s *MountSuite) TestReadDir(c *C) { - _, err := s.Helper.ReadDir("bar/qux") - c.Assert(err, IsNil) +func TestReadDir(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.ReadDir("bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.ReadDirArgs, HasLen, 1) - c.Assert(s.Underlying.ReadDirArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.ReadDirArgs, HasLen, 0) + assert.Len(t, underlying.ReadDirArgs, 1) + assert.Equal(t, underlying.ReadDirArgs[0], filepath.Join("bar", "qux")) + assert.Len(t, source.ReadDirArgs, 0) } -func (s *MountSuite) TestJoin(c *C) { - s.Helper.Join("foo", "bar") +func TestJoin(t *testing.T) { + helper, underlying, source := setup() + helper.Join("foo", "bar") - c.Assert(s.Underlying.JoinArgs, HasLen, 1) - c.Assert(s.Underlying.JoinArgs[0], DeepEquals, []string{"foo", "bar"}) - c.Assert(s.Source.JoinArgs, HasLen, 0) + assert.Len(t, underlying.JoinArgs, 1) + assert.Equal(t, underlying.JoinArgs[0], []string{"foo", "bar"}) + assert.Len(t, source.JoinArgs, 0) } -func (s *MountSuite) TestReadDirInMount(c *C) { - _, err := s.Helper.ReadDir("foo/bar/qux") - c.Assert(err, IsNil) +func TestReadDirInMount(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.ReadDir("foo/bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.ReadDirArgs, HasLen, 0) - c.Assert(s.Source.ReadDirArgs, HasLen, 1) - c.Assert(s.Source.ReadDirArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.ReadDirArgs, 0) + assert.Len(t, source.ReadDirArgs, 1) + assert.Equal(t, source.ReadDirArgs[0], filepath.Join("bar", "qux")) } -func (s *MountSuite) TestMkdirAll(c *C) { - err := s.Helper.MkdirAll("bar/qux", 0777) - c.Assert(err, IsNil) +func TestMkdirAll(t *testing.T) { + helper, underlying, source := setup() + err := helper.MkdirAll("bar/qux", 0777) + assert.NoError(t, err) - c.Assert(s.Underlying.MkdirAllArgs, HasLen, 1) - c.Assert(s.Underlying.MkdirAllArgs[0], Equals, + assert.Len(t, underlying.MkdirAllArgs, 1) + assert.Equal(t, underlying.MkdirAllArgs[0], [2]interface{}{filepath.Join("bar", "qux"), os.FileMode(0777)}) - c.Assert(s.Source.MkdirAllArgs, HasLen, 0) + assert.Len(t, source.MkdirAllArgs, 0) } -func (s *MountSuite) TestMkdirAllInMount(c *C) { - err := s.Helper.MkdirAll("foo/bar/qux", 0777) - c.Assert(err, IsNil) +func TestMkdirAllInMount(t *testing.T) { + helper, underlying, source := setup() + err := helper.MkdirAll("foo/bar/qux", 0777) + assert.NoError(t, err) - c.Assert(s.Underlying.MkdirAllArgs, HasLen, 0) - c.Assert(s.Source.MkdirAllArgs, HasLen, 1) - c.Assert(s.Source.MkdirAllArgs[0], Equals, + assert.Len(t, underlying.MkdirAllArgs, 0) + assert.Len(t, source.MkdirAllArgs, 1) + assert.Equal(t, source.MkdirAllArgs[0], [2]interface{}{filepath.Join("bar", "qux"), os.FileMode(0777)}) } -func (s *MountSuite) TestLstat(c *C) { - _, err := s.Helper.Lstat("bar/qux") - c.Assert(err, IsNil) +func TestLstat(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.Lstat("bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.LstatArgs, HasLen, 1) - c.Assert(s.Underlying.LstatArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.LstatArgs, HasLen, 0) + assert.Len(t, underlying.LstatArgs, 1) + assert.Equal(t, underlying.LstatArgs[0], filepath.Join("bar", "qux")) + assert.Len(t, source.LstatArgs, 0) } -func (s *MountSuite) TestLstatInMount(c *C) { - _, err := s.Helper.Lstat("foo/bar/qux") - c.Assert(err, IsNil) +func TestLstatInMount(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.Lstat("foo/bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.LstatArgs, HasLen, 0) - c.Assert(s.Source.LstatArgs, HasLen, 1) - c.Assert(s.Source.LstatArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.LstatArgs, 0) + assert.Len(t, source.LstatArgs, 1) + assert.Equal(t, source.LstatArgs[0], filepath.Join("bar", "qux")) } -func (s *MountSuite) TestSymlink(c *C) { - err := s.Helper.Symlink("../baz", "bar/qux") - c.Assert(err, IsNil) +func TestSymlink(t *testing.T) { + helper, underlying, source := setup() + err := helper.Symlink("../baz", "bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.SymlinkArgs, HasLen, 1) - c.Assert(s.Underlying.SymlinkArgs[0], Equals, + assert.Len(t, underlying.SymlinkArgs, 1) + assert.Equal(t, underlying.SymlinkArgs[0], [2]string{"../baz", filepath.Join("bar", "qux")}) - c.Assert(s.Source.SymlinkArgs, HasLen, 0) + assert.Len(t, source.SymlinkArgs, 0) } -func (s *MountSuite) TestSymlinkCrossMount(c *C) { - err := s.Helper.Symlink("../foo", "bar/qux") - c.Assert(err, NotNil) +func TestSymlinkCrossMount(t *testing.T) { + helper, _, _ := setup() + err := helper.Symlink("../foo", "bar/qux") + assert.Error(t, err) - err = s.Helper.Symlink("../foo/qux", "bar/qux") - c.Assert(err, NotNil) + err = helper.Symlink("../foo/qux", "bar/qux") + assert.Error(t, err) - err = s.Helper.Symlink("../baz", "foo") - c.Assert(err, NotNil) + err = helper.Symlink("../baz", "foo") + assert.Error(t, err) - err = s.Helper.Symlink("../../../foo", "foo/bar/qux") - c.Assert(err, NotNil) + err = helper.Symlink("../../../foo", "foo/bar/qux") + assert.Error(t, err) } -func (s *MountSuite) TestSymlinkInMount(c *C) { - err := s.Helper.Symlink("../baz", "foo/bar/qux") - c.Assert(err, IsNil) +func TestSymlinkInMount(t *testing.T) { + helper, underlying, source := setup() + err := helper.Symlink("../baz", "foo/bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.SymlinkArgs, HasLen, 0) - c.Assert(s.Source.SymlinkArgs, HasLen, 1) - c.Assert(s.Source.SymlinkArgs[0], Equals, + assert.Len(t, underlying.SymlinkArgs, 0) + assert.Len(t, source.SymlinkArgs, 1) + assert.Equal(t, source.SymlinkArgs[0], [2]string{"../baz", filepath.Join("bar", "qux")}) } -func (s *MountSuite) TestRadlink(c *C) { - _, err := s.Helper.Readlink("bar/qux") - c.Assert(err, IsNil) +func TestRadlink(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.Readlink("bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.ReadlinkArgs, HasLen, 1) - c.Assert(s.Underlying.ReadlinkArgs[0], Equals, filepath.Join("bar", "qux")) - c.Assert(s.Source.ReadlinkArgs, HasLen, 0) + assert.Len(t, underlying.ReadlinkArgs, 1) + assert.Equal(t, underlying.ReadlinkArgs[0], filepath.Join("bar", "qux")) + assert.Len(t, source.ReadlinkArgs, 0) } -func (s *MountSuite) TestReadlinkInMount(c *C) { - _, err := s.Helper.Readlink("foo/bar/qux") - c.Assert(err, IsNil) +func TestReadlinkInMount(t *testing.T) { + helper, underlying, source := setup() + _, err := helper.Readlink("foo/bar/qux") + assert.NoError(t, err) - c.Assert(s.Underlying.ReadlinkArgs, HasLen, 0) - c.Assert(s.Source.ReadlinkArgs, HasLen, 1) - c.Assert(s.Source.ReadlinkArgs[0], Equals, filepath.Join("bar", "qux")) + assert.Len(t, underlying.ReadlinkArgs, 0) + assert.Len(t, source.ReadlinkArgs, 1) + assert.Equal(t, source.ReadlinkArgs[0], filepath.Join("bar", "qux")) } -func (s *MountSuite) TestUnderlyingNotSupported(c *C) { +func TestUnderlyingNotSupported(t *testing.T) { h := New(&test.BasicMock{}, "/foo", &test.BasicMock{}) _, err := h.ReadDir("qux") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.Equal(t, err, billy.ErrNotSupported) _, err = h.Readlink("qux") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.Equal(t, err, billy.ErrNotSupported) } -func (s *MountSuite) TestSourceNotSupported(c *C) { - h := New(&s.Underlying, "/foo", &test.BasicMock{}) +func TestSourceNotSupported(t *testing.T) { + _, underlying, _ := setup() + h := New(underlying, "/foo", &test.BasicMock{}) _, err := h.ReadDir("foo") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.Equal(t, err, billy.ErrNotSupported) _, err = h.Readlink("foo") - c.Assert(err, Equals, billy.ErrNotSupported) + assert.Equal(t, err, billy.ErrNotSupported) } -func (s *MountSuite) TestCapabilities(c *C) { - testCapabilities(c, new(test.BasicMock), new(test.BasicMock)) - testCapabilities(c, new(test.BasicMock), new(test.OnlyReadCapFs)) - testCapabilities(c, new(test.BasicMock), new(test.NoLockCapFs)) - testCapabilities(c, new(test.OnlyReadCapFs), new(test.BasicMock)) - testCapabilities(c, new(test.OnlyReadCapFs), new(test.OnlyReadCapFs)) - testCapabilities(c, new(test.OnlyReadCapFs), new(test.NoLockCapFs)) - testCapabilities(c, new(test.NoLockCapFs), new(test.BasicMock)) - testCapabilities(c, new(test.NoLockCapFs), new(test.OnlyReadCapFs)) - testCapabilities(c, new(test.NoLockCapFs), new(test.NoLockCapFs)) +func TestCapabilities(t *testing.T) { + testCapabilities(t, new(test.BasicMock), new(test.BasicMock)) + testCapabilities(t, new(test.BasicMock), new(test.OnlyReadCapFs)) + testCapabilities(t, new(test.BasicMock), new(test.NoLockCapFs)) + testCapabilities(t, new(test.OnlyReadCapFs), new(test.BasicMock)) + testCapabilities(t, new(test.OnlyReadCapFs), new(test.OnlyReadCapFs)) + testCapabilities(t, new(test.OnlyReadCapFs), new(test.NoLockCapFs)) + testCapabilities(t, new(test.NoLockCapFs), new(test.BasicMock)) + testCapabilities(t, new(test.NoLockCapFs), new(test.OnlyReadCapFs)) + testCapabilities(t, new(test.NoLockCapFs), new(test.NoLockCapFs)) } -func testCapabilities(c *C, a, b billy.Basic) { +func testCapabilities(t *testing.T, a, b billy.Basic) { aCapabilities := billy.Capabilities(a) bCapabilities := billy.Capabilities(b) @@ -359,12 +383,12 @@ func testCapabilities(c *C, a, b billy.Basic) { unionCapabilities := aCapabilities & bCapabilities - c.Assert(capabilities, Equals, unionCapabilities) + assert.Equal(t, capabilities, unionCapabilities) fs = New(b, "/foo", a) capabilities = billy.Capabilities(fs) unionCapabilities = aCapabilities & bCapabilities - c.Assert(capabilities, Equals, unionCapabilities) + assert.Equal(t, capabilities, unionCapabilities) } diff --git a/helper/polyfill/polyfill_test.go b/helper/polyfill/polyfill_test.go index b0df9a7..1254ac0 100644 --- a/helper/polyfill/polyfill_test.go +++ b/helper/polyfill/polyfill_test.go @@ -5,74 +5,63 @@ import ( "testing" "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/go-git/go-billy/v5/internal/test" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&PolyfillSuite{}) - -type PolyfillSuite struct { - Helper billy.Filesystem - Underlying billy.Filesystem -} - -func (s *PolyfillSuite) SetUpTest(c *C) { - s.Helper = New(&test.BasicMock{}) -} +var ( + helper = New(&test.BasicMock{}) +) -func (s *PolyfillSuite) TestTempFile(c *C) { - _, err := s.Helper.TempFile("", "") - c.Assert(err, Equals, billy.ErrNotSupported) +func TestTempFile(t *testing.T) { + _, err := helper.TempFile("", "") + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestReadDir(c *C) { - _, err := s.Helper.ReadDir("") - c.Assert(err, Equals, billy.ErrNotSupported) +func TestReadDir(t *testing.T) { + _, err := helper.ReadDir("") + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestMkdirAll(c *C) { - err := s.Helper.MkdirAll("", 0) - c.Assert(err, Equals, billy.ErrNotSupported) +func TestMkdirAll(t *testing.T) { + err := helper.MkdirAll("", 0) + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestSymlink(c *C) { - err := s.Helper.Symlink("", "") - c.Assert(err, Equals, billy.ErrNotSupported) +func TestSymlink(t *testing.T) { + err := helper.Symlink("", "") + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestReadlink(c *C) { - _, err := s.Helper.Readlink("") - c.Assert(err, Equals, billy.ErrNotSupported) +func TestReadlink(t *testing.T) { + _, err := helper.Readlink("") + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestLstat(c *C) { - _, err := s.Helper.Lstat("") - c.Assert(err, Equals, billy.ErrNotSupported) +func TestLstat(t *testing.T) { + _, err := helper.Lstat("") + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestChroot(c *C) { - _, err := s.Helper.Chroot("") - c.Assert(err, Equals, billy.ErrNotSupported) +func TestChroot(t *testing.T) { + _, err := helper.Chroot("") + assert.ErrorIs(t, err, billy.ErrNotSupported) } -func (s *PolyfillSuite) TestRoot(c *C) { - c.Assert(s.Helper.Root(), Equals, string(filepath.Separator)) +func TestRoot(t *testing.T) { + assert.Equal(t, string(filepath.Separator), helper.Root()) } -func (s *PolyfillSuite) TestCapabilities(c *C) { - testCapabilities(c, new(test.BasicMock)) - testCapabilities(c, new(test.OnlyReadCapFs)) - testCapabilities(c, new(test.NoLockCapFs)) +func TestCapabilities(t *testing.T) { + testCapabilities(t, new(test.BasicMock)) + testCapabilities(t, new(test.OnlyReadCapFs)) + testCapabilities(t, new(test.NoLockCapFs)) } -func testCapabilities(c *C, basic billy.Basic) { +func testCapabilities(t *testing.T, basic billy.Basic) { baseCapabilities := billy.Capabilities(basic) fs := New(basic) capabilities := billy.Capabilities(fs) - - c.Assert(capabilities, Equals, baseCapabilities) + assert.Equal(t, baseCapabilities, capabilities) } diff --git a/helper/temporal/temporal_test.go b/helper/temporal/temporal_test.go index c611a13..47cbdbd 100644 --- a/helper/temporal/temporal_test.go +++ b/helper/temporal/temporal_test.go @@ -5,29 +5,15 @@ import ( "testing" "github.com/go-git/go-billy/v5/memfs" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&TemporalSuite{}) - -type TemporalSuite struct { - test.FilesystemSuite -} - -func (s *TemporalSuite) SetUpTest(c *C) { - fs := New(memfs.New(), "foo") - s.FilesystemSuite = test.NewFilesystemSuite(fs) -} - -func (s *TemporalSuite) TestTempFileDefaultPath(c *C) { +func TestTempFileDefaultPath(t *testing.T) { fs := New(memfs.New(), "foo") f, err := fs.TempFile("", "bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - c.Assert(strings.HasPrefix(f.Name(), fs.Join("foo", "bar")), Equals, true) + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + assert.True(t, strings.HasPrefix(f.Name(), fs.Join("foo", "bar"))) } diff --git a/test/mock.go b/internal/test/mock.go similarity index 100% rename from test/mock.go rename to internal/test/mock.go diff --git a/memfs/memory_test.go b/memfs/memory_test.go index cd7fa68..7a483cb 100644 --- a/memfs/memory_test.go +++ b/memfs/memory_test.go @@ -8,68 +8,56 @@ import ( "testing" "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/test" "github.com/go-git/go-billy/v5/util" "github.com/stretchr/testify/assert" - - . "gopkg.in/check.v1" ) -func Test(t *testing.T) { TestingT(t) } - -type MemorySuite struct { - test.FilesystemSuite - path string -} - -var _ = Suite(&MemorySuite{}) - -func (s *MemorySuite) SetUpTest(c *C) { - s.FilesystemSuite = test.NewFilesystemSuite(New()) -} - -func (s *MemorySuite) TestRootExists(c *C) { - f, err := s.FS.Stat("/") - c.Assert(err, IsNil) - c.Assert(f.IsDir(), Equals, true) +func TestRootExists(t *testing.T) { + fs := New() + f, err := fs.Stat("/") + assert.NoError(t, err) + assert.True(t, f.IsDir()) } -func (s *MemorySuite) TestCapabilities(c *C) { - _, ok := s.FS.(billy.Capable) - c.Assert(ok, Equals, true) +func TestCapabilities(t *testing.T) { + fs := New() + _, ok := fs.(billy.Capable) + assert.True(t, ok) - caps := billy.Capabilities(s.FS) - c.Assert(caps, Equals, billy.DefaultCapabilities&^billy.LockCapability) + caps := billy.Capabilities(fs) + assert.Equal(t, billy.DefaultCapabilities&^billy.LockCapability, caps) } -func (s *MemorySuite) TestNegativeOffsets(c *C) { - f, err := s.FS.Create("negative") - c.Assert(err, IsNil) +func TestNegativeOffsets(t *testing.T) { + fs := New() + f, err := fs.Create("negative") + assert.NoError(t, err) buf := make([]byte, 100) _, err = f.ReadAt(buf, -100) - c.Assert(err, ErrorMatches, "readat negative: negative offset") + assert.ErrorContains(t, err, "readat negative: negative offset") _, err = f.Seek(-100, io.SeekCurrent) - c.Assert(err, IsNil) + assert.NoError(t, err) _, err = f.Write(buf) - c.Assert(err, ErrorMatches, "writeat negative: negative offset") + assert.ErrorContains(t, err, "writeat negative: negative offset") } -func (s *MemorySuite) TestExclusive(c *C) { - f, err := s.FS.OpenFile("exclusive", os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) - c.Assert(err, IsNil) +func TestExclusive(t *testing.T) { + fs := New() + f, err := fs.OpenFile("exclusive", os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) + assert.NoError(t, err) fmt.Fprint(f, "mememememe") err = f.Close() - c.Assert(err, IsNil) + assert.NoError(t, err) - _, err = s.FS.OpenFile("exclusive", os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) - c.Assert(err, ErrorMatches, os.ErrExist.Error()) + _, err = fs.OpenFile("exclusive", os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) + assert.ErrorContains(t, err, os.ErrExist.Error()) } -func (s *MemorySuite) TestOrder(c *C) { +func TestOrder(t *testing.T) { var err error files := []string{ @@ -77,50 +65,48 @@ func (s *MemorySuite) TestOrder(c *C) { "b", "c", } + fs := New() for _, f := range files { - _, err = s.FS.Create(f) - c.Assert(err, IsNil) + _, err = fs.Create(f) + assert.NoError(t, err) } attempts := 30 for n := 0; n < attempts; n++ { - actual, err := s.FS.ReadDir("") - c.Assert(err, IsNil) + actual, err := fs.ReadDir("") + assert.NoError(t, err) for i, f := range files { - c.Assert(actual[i].Name(), Equals, f) + assert.Equal(t, actual[i].Name(), f) } } } -func (s *MemorySuite) TestNotFound(c *C) { - files, err := s.FS.ReadDir("asdf") - c.Assert(files, HasLen, 0) - // JS / wasip have this error message captalised. - msg := "open /asdf: (N|n)o such file or directory" - if runtime.GOOS == "windows" { - msg = `open \\asdf: The system cannot find the file specified\.` - } - c.Assert(err, ErrorMatches, msg) +func TestNotFound(t *testing.T) { + fs := New() + files, err := fs.ReadDir("asdf") + assert.Len(t, files, 0) + assert.ErrorIs(t, err, os.ErrNotExist) } -func (s *MemorySuite) TestTruncateAppend(c *C) { - err := util.WriteFile(s.FS, "truncate_append", []byte("file-content"), 0666) - c.Assert(err, IsNil) +func TestTruncateAppend(t *testing.T) { + fs := New() + err := util.WriteFile(fs, "truncate_append", []byte("file-content"), 0666) + assert.NoError(t, err) - f, err := s.FS.OpenFile("truncate_append", os.O_WRONLY|os.O_TRUNC|os.O_APPEND, 0666) - c.Assert(err, IsNil) + f, err := fs.OpenFile("truncate_append", os.O_WRONLY|os.O_TRUNC|os.O_APPEND, 0666) + assert.NoError(t, err) n, err := f.Write([]byte("replace")) - c.Assert(err, IsNil) - c.Assert(n, Equals, len("replace")) + assert.NoError(t, err) + assert.Equal(t, n, len("replace")) err = f.Close() - c.Assert(err, IsNil) + assert.NoError(t, err) - data, err := util.ReadFile(s.FS, "truncate_append") - c.Assert(err, IsNil) - c.Assert(string(data), Equals, "replace") + data, err := util.ReadFile(fs, "truncate_append") + assert.NoError(t, err) + assert.Equal(t, string(data), "replace") } func TestReadlink(t *testing.T) { @@ -186,7 +172,7 @@ func TestReadlink(t *testing.T) { } } -func TestSymlink(t *testing.T) { +func TestSymlink2(t *testing.T) { tests := []struct { name string target string @@ -320,15 +306,16 @@ func TestJoin(t *testing.T) { } } -func (s *MemorySuite) TestSymlink(c *C) { - err := s.FS.Symlink("test", "test") - c.Assert(err, IsNil) +func TestSymlink(t *testing.T) { + fs := New() + err := fs.Symlink("test", "test") + assert.NoError(t, err) - f, err := s.FS.Open("test") - c.Assert(err, IsNil) - c.Assert(f, NotNil) + f, err := fs.Open("test") + assert.NoError(t, err) + assert.NotNil(t, f) - fi, err := s.FS.ReadDir("test") - c.Assert(err, IsNil) - c.Assert(fi, IsNil) + fi, err := fs.ReadDir("test") + assert.NoError(t, err) + assert.Nil(t, fi) } diff --git a/osfs/os_chroot_test.go b/osfs/os_chroot_test.go index 4057197..8b36d4b 100644 --- a/osfs/os_chroot_test.go +++ b/osfs/os_chroot_test.go @@ -4,57 +4,43 @@ package osfs import ( - "io/ioutil" "os" "path/filepath" "runtime" "testing" "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -type ChrootOSSuite struct { - test.FilesystemSuite - path string -} - -var _ = Suite(&ChrootOSSuite{}) - -func (s *ChrootOSSuite) SetUpTest(c *C) { - s.path, _ = ioutil.TempDir(os.TempDir(), "go-billy-osfs-test") +func setup(t *testing.T) (billy.Filesystem, string) { + path := t.TempDir() if runtime.GOOS == "plan9" { // On Plan 9, permission mode of newly created files // or directories are based on the permission mode of // the containing directory (see http://man.cat-v.org/plan_9/5/open). // Since TestOpenFileWithModes and TestStat creates files directly // in the temporary directory, we need to make it more permissive. - c.Assert(os.Chmod(s.path, 0777), IsNil) + err := os.Chmod(path, 0777) + assert.NoError(t, err) } - s.FilesystemSuite = test.NewFilesystemSuite(newChrootOS(s.path)) -} - -func (s *ChrootOSSuite) TearDownTest(c *C) { - err := os.RemoveAll(s.path) - c.Assert(err, IsNil) + return newChrootOS(path), path } -func (s *ChrootOSSuite) TestOpenDoesNotCreateDir(c *C) { - _, err := s.FS.Open("dir/non-existent") - c.Assert(err, NotNil) +func TestOpenDoesNotCreateDir(t *testing.T) { + fs, path := setup(t) + _, err := fs.Open("dir/non-existent") + assert.Error(t, err) - _, err = os.Stat(filepath.Join(s.path, "dir")) - c.Assert(os.IsNotExist(err), Equals, true) + _, err = os.Stat(filepath.Join(path, "dir")) + assert.ErrorIs(t, err, os.ErrNotExist) } -func (s *ChrootOSSuite) TestCapabilities(c *C) { - _, ok := s.FS.(billy.Capable) - c.Assert(ok, Equals, true) +func TestCapabilities(t *testing.T) { + fs, _ := setup(t) + _, ok := fs.(billy.Capable) + assert.True(t, ok) - caps := billy.Capabilities(s.FS) - c.Assert(caps, Equals, billy.AllCapabilities) + caps := billy.Capabilities(fs) + assert.Equal(t, billy.AllCapabilities, caps) } diff --git a/osfs/os_js_test.go b/osfs/os_js_test.go index fbefdf4..fef2930 100644 --- a/osfs/os_js_test.go +++ b/osfs/os_js_test.go @@ -4,7 +4,6 @@ package osfs import ( - "fmt" "os" "path/filepath" "reflect" @@ -12,41 +11,26 @@ import ( "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/helper/chroot" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -type OSSuite struct { - test.FilesystemSuite - path string - tempCounter int -} - -var _ = Suite(&OSSuite{}) - -func (s *OSSuite) SetUpTest(c *C) { - s.tempCounter++ - s.path = fmt.Sprintf("test_%d", s.tempCounter) - s.FilesystemSuite = test.NewFilesystemSuite(New(s.path)) -} - -func (s *OSSuite) TestOpenDoesNotCreateDir(c *C) { - _, err := s.FS.Open("dir/non-existent") - c.Assert(err, NotNil) +func TestOpenDoesNotCreateDir(t *testing.T) { + path := t.TempDir() + fs := New(path) + _, err := fs.Open("dir/non-existent") + assert.Error(t, err) - _, err = s.FS.Stat(filepath.Join(s.path, "dir")) - c.Assert(os.IsNotExist(err), Equals, true) + _, err = fs.Stat(filepath.Join(path, "dir")) + assert.ErrorIs(t, err, os.ErrNotExist) } -func (s *OSSuite) TestCapabilities(c *C) { - _, ok := s.FS.(billy.Capable) - c.Assert(ok, Equals, true) +func TestCapabilities(t *testing.T) { + fs := New(t.TempDir()) + _, ok := fs.(billy.Capable) + assert.True(t, ok) - caps := billy.Capabilities(s.FS) - c.Assert(caps, Equals, billy.DefaultCapabilities&^billy.LockCapability) + caps := billy.Capabilities(fs) + assert.Equal(t, billy.DefaultCapabilities&^billy.LockCapability, caps) } func TestDefault(t *testing.T) { diff --git a/osfs/os_wasip1_test.go b/osfs/os_wasip1_test.go index 73f385b..d189b4d 100644 --- a/osfs/os_wasip1_test.go +++ b/osfs/os_wasip1_test.go @@ -4,48 +4,30 @@ package osfs import ( - "fmt" - "os" "path/filepath" "reflect" "testing" "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/test" - - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -type OSSuite struct { - test.FilesystemSuite - path string - tempCounter int -} - -var _ = Suite(&OSSuite{}) - -func (s *OSSuite) SetUpTest(c *C) { - s.tempCounter++ - s.path = fmt.Sprintf("test_%d", s.tempCounter) - s.FilesystemSuite = test.NewFilesystemSuite(New(s.path)) -} - -func (s *OSSuite) TestOpenDoesNotCreateDir(c *C) { - _, err := s.FS.Open("dir/non-existent") - c.Assert(err, NotNil) +func TestOpenDoesNotCreateDir(t *testing.T) { + fs := New("/some/path") + _, err := fs.Open("dir/non-existent") + assert.Error(t, err) - _, err = s.FS.Stat(filepath.Join(s.path, "dir")) - c.Assert(os.IsNotExist(err), Equals, true) + _, err = fs.Stat(filepath.Join("/some/path", "dir")) + assert.Error(t, err) } -func (s *OSSuite) TestCapabilities(c *C) { - _, ok := s.FS.(billy.Capable) - c.Assert(ok, Equals, true) +func TestCapabilities(t *testing.T) { + fs := New("/some/path") + _, ok := fs.(billy.Capable) + assert.True(t, ok) - caps := billy.Capabilities(s.FS) - c.Assert(caps, Equals, billy.DefaultCapabilities) + caps := billy.Capabilities(fs) + assert.Equal(t, billy.DefaultCapabilities, caps) } func TestDefault(t *testing.T) { diff --git a/test/basic.go b/test/basic.go deleted file mode 100644 index ec569dc..0000000 --- a/test/basic.go +++ /dev/null @@ -1,583 +0,0 @@ -package test - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - - . "gopkg.in/check.v1" - . "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/util" -) - -// BasicSuite is a convenient test suite to validate any implementation of -// billy.Basic -type BasicSuite struct { - FS Basic -} - -func (s *BasicSuite) TestCreate(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestCreateDepth(c *C) { - f, err := s.FS.Create("bar/foo") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, s.FS.Join("bar", "foo")) - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestCreateDepthAbsolute(c *C) { - f, err := s.FS.Create("/bar/foo") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, s.FS.Join("bar", "foo")) - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestCreateOverwrite(c *C) { - for i := 0; i < 3; i++ { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - l, err := f.Write([]byte(fmt.Sprintf("foo%d", i))) - c.Assert(err, IsNil) - c.Assert(l, Equals, 4) - - err = f.Close() - c.Assert(err, IsNil) - } - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - wrote, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(wrote), DeepEquals, "foo2") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestCreateAndClose(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - _, err = f.Write([]byte("foo")) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - f, err = s.FS.Open(f.Name()) - c.Assert(err, IsNil) - - wrote, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(wrote), DeepEquals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestOpen(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo") - c.Assert(f.Close(), IsNil) - - f, err = s.FS.Open("foo") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestOpenNotExists(c *C) { - f, err := s.FS.Open("not-exists") - c.Assert(err, NotNil) - c.Assert(f, IsNil) -} - -func (s *BasicSuite) TestOpenFile(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) - c.Assert(err, IsNil) - s.testWriteClose(c, f, "foo1") - - // Truncate if it exists - f, err = s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testWriteClose(c, f, "foo1overwritten") - - // Read-only if it exists - f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testReadClose(c, f, "foo1overwritten") - - // Create when it does exist - f, err = s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testWriteClose(c, f, "bar") - - f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "bar") -} - -func (s *BasicSuite) TestOpenFileNoTruncate(c *C) { - defaultMode := os.FileMode(0666) - - // Create when it does not exist - f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testWriteClose(c, f, "foo1") - - f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "foo1") - - // Create when it does exist - f, err = s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testWriteClose(c, f, "bar") - - f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "bar1") -} - -func (s *BasicSuite) TestOpenFileAppend(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_APPEND, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testWriteClose(c, f, "foo1") - - f, err = s.FS.OpenFile("foo1", os.O_WRONLY|os.O_APPEND, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - s.testWriteClose(c, f, "bar1") - - f, err = s.FS.OpenFile("foo1", os.O_RDONLY, defaultMode) - c.Assert(err, IsNil) - s.testReadClose(c, f, "foo1bar1") -} - -func (s *BasicSuite) TestOpenFileReadWrite(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - - written, err := f.Write([]byte("foobar")) - c.Assert(written, Equals, 6) - c.Assert(err, IsNil) - - _, err = f.Seek(0, os.SEEK_SET) - c.Assert(err, IsNil) - - written, err = f.Write([]byte("qux")) - c.Assert(written, Equals, 3) - c.Assert(err, IsNil) - - _, err = f.Seek(0, os.SEEK_SET) - c.Assert(err, IsNil) - - s.testReadClose(c, f, "quxbar") -} - -func (s *BasicSuite) TestOpenFileWithModes(c *C) { - f, err := s.FS.OpenFile("foo", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, customMode) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - fi, err := s.FS.Stat("foo") - c.Assert(err, IsNil) - c.Assert(fi.Mode(), Equals, os.FileMode(customMode)) -} - -func (s *BasicSuite) testWriteClose(c *C, f File, content string) { - written, err := f.Write([]byte(content)) - c.Assert(written, Equals, len(content)) - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) testReadClose(c *C, f File, content string) { - read, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(read), Equals, content) - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestFileWrite(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - n, err := f.Write([]byte("foo")) - c.Assert(err, IsNil) - c.Assert(n, Equals, 3) - - f.Seek(0, io.SeekStart) - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(all), Equals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestFileWriteClose(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - c.Assert(f.Close(), IsNil) - - _, err = f.Write([]byte("foo")) - c.Assert(err, NotNil) -} - -func (s *BasicSuite) TestFileRead(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(all), Equals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestFileClosed(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - _, err = ioutil.ReadAll(f) - c.Assert(err, NotNil) -} - -func (s *BasicSuite) TestFileNonRead(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.OpenFile("foo", os.O_WRONLY, 0) - c.Assert(err, IsNil) - - _, err = ioutil.ReadAll(f) - c.Assert(err, NotNil) - - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestFileSeekstart(c *C) { - s.testFileSeek(c, 10, io.SeekStart) -} - -func (s *BasicSuite) TestFileSeekCurrent(c *C) { - s.testFileSeek(c, 5, io.SeekCurrent) -} - -func (s *BasicSuite) TestFileSeekEnd(c *C) { - s.testFileSeek(c, -26, io.SeekEnd) -} - -func (s *BasicSuite) testFileSeek(c *C, offset int64, whence int) { - err := util.WriteFile(s.FS, "foo", []byte("0123456789abcdefghijklmnopqrstuvwxyz"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - some := make([]byte, 5) - _, err = f.Read(some) - c.Assert(err, IsNil) - c.Assert(string(some), Equals, "01234") - - p, err := f.Seek(offset, whence) - c.Assert(err, IsNil) - c.Assert(int(p), Equals, 10) - - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(all, HasLen, 26) - c.Assert(string(all), Equals, "abcdefghijklmnopqrstuvwxyz") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestSeekToEndAndWrite(c *C) { - defaultMode := os.FileMode(0666) - - f, err := s.FS.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode) - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "foo1") - - _, err = f.Seek(10, io.SeekEnd) - c.Assert(err, IsNil) - - n, err := f.Write([]byte(`TEST`)) - c.Assert(err, IsNil) - c.Assert(n, Equals, 4) - - _, err = f.Seek(0, io.SeekStart) - c.Assert(err, IsNil) - - s.testReadClose(c, f, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00TEST") -} - -func (s *BasicSuite) TestFileSeekClosed(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - _, err = f.Seek(0, 0) - c.Assert(err, NotNil) -} - -func (s *BasicSuite) TestFileCloseTwice(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - c.Assert(f.Close(), IsNil) - c.Assert(f.Close(), NotNil) -} - -func (s *BasicSuite) TestStat(c *C) { - util.WriteFile(s.FS, "foo/bar", []byte("foo"), customMode) - - fi, err := s.FS.Stat("foo/bar") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "bar") - c.Assert(fi.Size(), Equals, int64(3)) - c.Assert(fi.Mode(), Equals, customMode) - c.Assert(fi.ModTime().IsZero(), Equals, false) - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *BasicSuite) TestStatNonExistent(c *C) { - fi, err := s.FS.Stat("non-existent") - comment := Commentf("error: %s", err) - c.Assert(os.IsNotExist(err), Equals, true, comment) - c.Assert(fi, IsNil) -} - -func (s *BasicSuite) TestRename(c *C) { - err := util.WriteFile(s.FS, "foo", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Rename("foo", "bar") - c.Assert(err, IsNil) - - foo, err := s.FS.Stat("foo") - c.Assert(foo, IsNil) - c.Assert(os.IsNotExist(err), Equals, true) - - bar, err := s.FS.Stat("bar") - c.Assert(err, IsNil) - c.Assert(bar, NotNil) -} - -func (s *BasicSuite) TestOpenAndWrite(c *C) { - err := util.WriteFile(s.FS, "foo", nil, 0644) - c.Assert(err, IsNil) - - foo, err := s.FS.Open("foo") - c.Assert(foo, NotNil) - c.Assert(err, IsNil) - - n, err := foo.Write([]byte("foo")) - c.Assert(err, NotNil) - c.Assert(n, Equals, 0) - - c.Assert(foo.Close(), IsNil) -} - -func (s *BasicSuite) TestOpenAndStat(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("foo"), 0644) - c.Assert(err, IsNil) - - foo, err := s.FS.Open("foo") - c.Assert(foo, NotNil) - c.Assert(foo.Name(), Equals, "foo") - c.Assert(err, IsNil) - c.Assert(foo.Close(), IsNil) - - stat, err := s.FS.Stat("foo") - c.Assert(stat, NotNil) - c.Assert(err, IsNil) - c.Assert(stat.Name(), Equals, "foo") - c.Assert(stat.Size(), Equals, int64(3)) -} - -func (s *BasicSuite) TestRemove(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - err = s.FS.Remove("foo") - c.Assert(err, IsNil) -} - -func (s *BasicSuite) TestRemoveNonExisting(c *C) { - err := s.FS.Remove("NON-EXISTING") - c.Assert(err, NotNil) - c.Assert(os.IsNotExist(err), Equals, true) -} - -func (s *BasicSuite) TestRemoveNotEmptyDir(c *C) { - err := util.WriteFile(s.FS, "foo", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Remove("no-exists") - c.Assert(err, NotNil) -} - -func (s *BasicSuite) TestJoin(c *C) { - c.Assert(s.FS.Join("foo", "bar"), Equals, fmt.Sprintf("foo%cbar", filepath.Separator)) -} - -func (s *BasicSuite) TestReadAtOnReadWrite(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - _, err = f.Write([]byte("abcdefg")) - c.Assert(err, IsNil) - - rf, ok := f.(io.ReaderAt) - c.Assert(ok, Equals, true) - - b := make([]byte, 3) - n, err := rf.ReadAt(b, 2) - c.Assert(err, IsNil) - c.Assert(n, Equals, 3) - c.Assert(string(b), Equals, "cde") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestReadAtOnReadOnly(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("abcdefg"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - rf, ok := f.(io.ReaderAt) - c.Assert(ok, Equals, true) - - b := make([]byte, 3) - n, err := rf.ReadAt(b, 2) - c.Assert(err, IsNil) - c.Assert(n, Equals, 3) - c.Assert(string(b), Equals, "cde") - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestReadAtEOF(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("TEST"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - b := make([]byte, 5) - n, err := f.ReadAt(b, 0) - c.Assert(err, Equals, io.EOF) - c.Assert(n, Equals, 4) - c.Assert(string(b), Equals, "TEST\x00") - - err = f.Close() - c.Assert(err, IsNil) -} - -func (s *BasicSuite) TestReadAtOffset(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("TEST"), 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - rf, ok := f.(io.ReaderAt) - c.Assert(ok, Equals, true) - - o, err := f.Seek(0, io.SeekCurrent) - c.Assert(err, IsNil) - c.Assert(o, Equals, int64(0)) - - b := make([]byte, 4) - n, err := rf.ReadAt(b, 0) - c.Assert(err, IsNil) - c.Assert(n, Equals, 4) - c.Assert(string(b), Equals, "TEST") - - o, err = f.Seek(0, io.SeekCurrent) - c.Assert(err, IsNil) - c.Assert(o, Equals, int64(0)) - - err = f.Close() - c.Assert(err, IsNil) -} - -func (s *BasicSuite) TestReadWriteLargeFile(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - size := 1 << 20 - - n, err := f.Write(bytes.Repeat([]byte("F"), size)) - c.Assert(err, IsNil) - c.Assert(n, Equals, size) - - c.Assert(f.Close(), IsNil) - - f, err = s.FS.Open("foo") - c.Assert(err, IsNil) - b, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(len(b), Equals, size) - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestWriteFile(c *C) { - err := util.WriteFile(s.FS, "foo", []byte("bar"), 0777) - c.Assert(err, IsNil) - - f, err := s.FS.Open("foo") - c.Assert(err, IsNil) - - wrote, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(wrote), DeepEquals, "bar") - - c.Assert(f.Close(), IsNil) -} - -func (s *BasicSuite) TestTruncate(c *C) { - f, err := s.FS.Create("foo") - c.Assert(err, IsNil) - - for _, sz := range []int64{4, 7, 2, 30, 0, 1} { - err = f.Truncate(sz) - c.Assert(err, IsNil) - - bs, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(len(bs), Equals, int(sz)) - - _, err = f.Seek(0, io.SeekStart) - c.Assert(err, IsNil) - } - - c.Assert(f.Close(), IsNil) -} diff --git a/test/basic_test.go b/test/basic_test.go new file mode 100644 index 0000000..b6a52ca --- /dev/null +++ b/test/basic_test.go @@ -0,0 +1,662 @@ +package test + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "testing" + + . "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" +) + +func eachBasicFS(t *testing.T, test func(t *testing.T, fs Basic)) { + for _, fs := range allFS(t.TempDir) { + t.Run(fmt.Sprintf("%T", fs), func(t *testing.T) { + test(t, fs) + }) + } +} + +func TestCreate(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + assert.Equal(t, "foo", f.Name()) + assert.NoError(t, f.Close()) + }) +} + +func TestCreateDepth(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("bar/foo") + assert.NoError(t, err) + assert.Equal(t, fs.Join("bar", "foo"), f.Name()) + assert.NoError(t, f.Close()) + }) +} + +func TestCreateDepthAbsolute(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("/bar/foo") + assert.NoError(t, err) + assert.Equal(t, fs.Join("bar", "foo"), f.Name()) + assert.NoError(t, f.Close()) + }) +} + +func TestCreateOverwrite(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + for i := 0; i < 3; i++ { + f, err := fs.Create("foo") + assert.NoError(t, err) + + l, err := f.Write([]byte(fmt.Sprintf("foo%d", i))) + assert.NoError(t, err) + assert.Equal(t, l, 4) + + err = f.Close() + assert.NoError(t, err) + } + + f, err := fs.Open("foo") + assert.NoError(t, err) + + wrote, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(wrote), "foo2") + assert.NoError(t, f.Close()) + }) +} + +func TestCreateAndClose(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + + _, err = f.Write([]byte("foo")) + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + f, err = fs.Open(f.Name()) + assert.NoError(t, err) + + wrote, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(wrote), "foo") + assert.NoError(t, f.Close()) + }) +} + +func TestOpen(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo") + assert.NoError(t, f.Close()) + + f, err = fs.Open("foo") + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo") + assert.NoError(t, f.Close()) + }) +} + +func TestOpenNotExists(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Open("not-exists") + assert.NotNil(t, err) + assert.Nil(t, f) + }) +} + +func TestOpenFile(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + defaultMode := os.FileMode(0666) + + f, err := fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) + assert.NoError(t, err) + testWriteClose(t, f, "foo1") + + // Truncate if it exists + f, err = fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testWriteClose(t, f, "foo1overwritten") + + // Read-only if it exists + f, err = fs.OpenFile("foo1", os.O_RDONLY, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testReadClose(t, f, "foo1overwritten") + + // Create when it does exist + f, err = fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testWriteClose(t, f, "bar") + + f, err = fs.OpenFile("foo1", os.O_RDONLY, defaultMode) + assert.NoError(t, err) + testReadClose(t, f, "bar") + }) +} + +func TestOpenFileNoTruncate(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + defaultMode := os.FileMode(0666) + + // Create when it does not exist + f, err := fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testWriteClose(t, f, "foo1") + + f, err = fs.OpenFile("foo1", os.O_RDONLY, defaultMode) + assert.NoError(t, err) + testReadClose(t, f, "foo1") + + // Create when it does exist + f, err = fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testWriteClose(t, f, "bar") + + f, err = fs.OpenFile("foo1", os.O_RDONLY, defaultMode) + assert.NoError(t, err) + testReadClose(t, f, "bar1") + }) +} + +func TestOpenFileAppend(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + defaultMode := os.FileMode(0666) + + f, err := fs.OpenFile("foo1", os.O_CREATE|os.O_WRONLY|os.O_APPEND, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testWriteClose(t, f, "foo1") + + f, err = fs.OpenFile("foo1", os.O_WRONLY|os.O_APPEND, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + testWriteClose(t, f, "bar1") + + f, err = fs.OpenFile("foo1", os.O_RDONLY, defaultMode) + assert.NoError(t, err) + testReadClose(t, f, "foo1bar1") + }) +} + +func TestOpenFileReadWrite(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + defaultMode := os.FileMode(0666) + + f, err := fs.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + + written, err := f.Write([]byte("foobar")) + assert.Equal(t, written, 6) + assert.NoError(t, err) + + _, err = f.Seek(0, io.SeekStart) + assert.NoError(t, err) + + written, err = f.Write([]byte("qux")) + assert.Equal(t, written, 3) + assert.NoError(t, err) + + _, err = f.Seek(0, io.SeekStart) + assert.NoError(t, err) + + testReadClose(t, f, "quxbar") + }) +} + +func TestOpenFileWithModes(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.OpenFile("foo", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, customMode) + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + fi, err := fs.Stat("foo") + assert.NoError(t, err) + assert.Equal(t, fi.Mode(), os.FileMode(customMode)) + }) +} + +func testWriteClose(t *testing.T, f File, content string) { + written, err := f.Write([]byte(content)) + assert.Equal(t, written, len(content)) + assert.NoError(t, err) + assert.NoError(t, f.Close()) +} + +func testReadClose(t *testing.T, f File, content string) { + read, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(read), content) + assert.NoError(t, f.Close()) +} + +func TestFileWrite(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + + n, err := f.Write([]byte("foo")) + assert.NoError(t, err) + assert.Equal(t, n, 3) + + f.Seek(0, io.SeekStart) + all, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(all), "foo") + assert.NoError(t, f.Close()) + }) +} + +func TestFileWriteClose(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + + assert.NoError(t, f.Close()) + + _, err = f.Write([]byte("foo")) + assert.NotNil(t, err) + }) +} + +func TestFileRead(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("foo"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + + all, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(all), "foo") + assert.NoError(t, f.Close()) + }) +} + +func TestFileClosed(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("foo"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + _, err = io.ReadAll(f) + assert.NotNil(t, err) + }) +} + +func TestFileNonRead(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("foo"), 0644) + assert.NoError(t, err) + + f, err := fs.OpenFile("foo", os.O_WRONLY, 0) + assert.NoError(t, err) + + _, err = io.ReadAll(f) + assert.NotNil(t, err) + + assert.NoError(t, f.Close()) + }) +} + +func TestFileSeekstart(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + testFileSeek(t, fs, 10, io.SeekStart) + }) +} + +func TestFileSeekCurrent(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + testFileSeek(t, fs, 5, io.SeekCurrent) + }) +} + +func TestFileSeekEnd(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + testFileSeek(t, fs, -26, io.SeekEnd) + }) +} + +func testFileSeek(t *testing.T, fs Basic, offset int64, whence int) { + err := util.WriteFile(fs, "foo", []byte("0123456789abcdefghijklmnopqrstuvwxyz"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + + some := make([]byte, 5) + _, err = f.Read(some) + assert.NoError(t, err) + assert.Equal(t, string(some), "01234") + + p, err := f.Seek(offset, whence) + assert.NoError(t, err) + assert.Equal(t, int(p), 10) + + all, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Len(t, all, 26) + assert.Equal(t, string(all), "abcdefghijklmnopqrstuvwxyz") + assert.NoError(t, f.Close()) +} + +func TestSeekToEndAndWrite(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + defaultMode := os.FileMode(0666) + + f, err := fs.OpenFile("foo1", os.O_CREATE|os.O_TRUNC|os.O_RDWR, defaultMode) + assert.NoError(t, err) + assert.Equal(t, f.Name(), "foo1") + + _, err = f.Seek(10, io.SeekEnd) + assert.NoError(t, err) + + n, err := f.Write([]byte(`TEST`)) + assert.NoError(t, err) + assert.Equal(t, n, 4) + + _, err = f.Seek(0, io.SeekStart) + assert.NoError(t, err) + + testReadClose(t, f, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00TEST") + }) +} + +func TestFileSeekClosed(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("foo"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + _, err = f.Seek(0, 0) + assert.NotNil(t, err) + }) +} + +func TestFileCloseTwice(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + + assert.NoError(t, f.Close()) + assert.Error(t, f.Close()) + }) +} + +func TestStat(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + util.WriteFile(fs, "foo/bar", []byte("foo"), customMode) + + fi, err := fs.Stat("foo/bar") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "bar") + assert.Equal(t, fi.Size(), int64(3)) + assert.Equal(t, fi.Mode(), customMode) + assert.Equal(t, fi.ModTime().IsZero(), false) + assert.Equal(t, fi.IsDir(), false) + }) +} + +func TestStatNonExistent(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + fi, err := fs.Stat("non-existent") + assert.ErrorIs(t, err, os.ErrNotExist) + assert.Nil(t, fi) + }) +} + +func TestRename(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", nil, 0644) + assert.NoError(t, err) + + err = fs.Rename("foo", "bar") + assert.NoError(t, err) + + foo, err := fs.Stat("foo") + assert.Nil(t, foo) + assert.ErrorIs(t, err, os.ErrNotExist) + + bar, err := fs.Stat("bar") + assert.NoError(t, err) + assert.NotNil(t, bar) + }) +} + +func TestOpenAndWrite(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", nil, 0644) + assert.NoError(t, err) + + foo, err := fs.Open("foo") + assert.NotNil(t, foo) + assert.NoError(t, err) + + n, err := foo.Write([]byte("foo")) + assert.NotNil(t, err) + assert.Equal(t, n, 0) + + assert.NoError(t, foo.Close()) + }) +} + +func TestOpenAndStat(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("foo"), 0644) + assert.NoError(t, err) + + foo, err := fs.Open("foo") + assert.NotNil(t, foo) + assert.Equal(t, "foo", foo.Name()) + assert.NoError(t, err) + assert.NoError(t, foo.Close()) + + stat, err := fs.Stat("foo") + assert.NotNil(t, stat) + assert.NoError(t, err) + assert.Equal(t, stat.Name(), "foo") + assert.Equal(t, stat.Size(), int64(3)) + }) +} + +func TestRemove(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + err = fs.Remove("foo") + assert.NoError(t, err) + }) +} + +func TestRemoveNonExisting(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := fs.Remove("NON-EXISTING") + assert.NotNil(t, err) + assert.ErrorIs(t, err, os.ErrNotExist) + }) +} + +func TestRemoveNotEmptyDir(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", nil, 0644) + assert.NoError(t, err) + + err = fs.Remove("no-exists") + assert.NotNil(t, err) + }) +} + +func TestJoin(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + assert.Equal(t, fs.Join("foo", "bar"), fmt.Sprintf("foo%cbar", filepath.Separator)) + }) +} + +func TestReadAtOnReadWrite(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + _, err = f.Write([]byte("abcdefg")) + assert.NoError(t, err) + + rf, ok := f.(io.ReaderAt) + assert.True(t, ok) + + b := make([]byte, 3) + n, err := rf.ReadAt(b, 2) + assert.NoError(t, err) + assert.Equal(t, n, 3) + assert.Equal(t, string(b), "cde") + assert.NoError(t, f.Close()) + }) +} + +func TestReadAtOnReadOnly(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("abcdefg"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + + rf, ok := f.(io.ReaderAt) + assert.True(t, ok) + + b := make([]byte, 3) + n, err := rf.ReadAt(b, 2) + assert.NoError(t, err) + assert.Equal(t, n, 3) + assert.Equal(t, string(b), "cde") + assert.NoError(t, f.Close()) + }) +} + +func TestReadAtEOF(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("TEST"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + + b := make([]byte, 5) + n, err := f.ReadAt(b, 0) + assert.ErrorIs(t, err, io.EOF) + assert.Equal(t, n, 4) + assert.Equal(t, string(b), "TEST\x00") + + err = f.Close() + assert.NoError(t, err) + }) +} + +func TestReadAtOffset(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("TEST"), 0644) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + + rf, ok := f.(io.ReaderAt) + assert.True(t, ok) + + o, err := f.Seek(0, io.SeekCurrent) + assert.NoError(t, err) + assert.Equal(t, o, int64(0)) + + b := make([]byte, 4) + n, err := rf.ReadAt(b, 0) + assert.NoError(t, err) + assert.Equal(t, n, 4) + assert.Equal(t, string(b), "TEST") + + o, err = f.Seek(0, io.SeekCurrent) + assert.NoError(t, err) + assert.Equal(t, o, int64(0)) + + err = f.Close() + assert.NoError(t, err) + }) +} + +func TestReadWriteLargeFile(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + + size := 1 << 20 + + n, err := f.Write(bytes.Repeat([]byte("F"), size)) + assert.NoError(t, err) + assert.Equal(t, n, size) + + assert.NoError(t, f.Close()) + + f, err = fs.Open("foo") + assert.NoError(t, err) + b, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, len(b), size) + assert.NoError(t, f.Close()) + }) +} + +func TestWriteFile(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + err := util.WriteFile(fs, "foo", []byte("bar"), 0777) + assert.NoError(t, err) + + f, err := fs.Open("foo") + assert.NoError(t, err) + + wrote, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(wrote), "bar") + + assert.NoError(t, f.Close()) + }) +} + +func TestTruncate(t *testing.T) { + eachBasicFS(t, func(t *testing.T, fs Basic) { + f, err := fs.Create("foo") + assert.NoError(t, err) + + for _, sz := range []int64{4, 7, 2, 30, 0, 1} { + err = f.Truncate(sz) + assert.NoError(t, err) + + bs, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, len(bs), int(sz)) + + _, err = f.Seek(0, io.SeekStart) + assert.NoError(t, err) + } + + assert.NoError(t, f.Close()) + }) +} diff --git a/test/chroot.go b/test/chroot.go deleted file mode 100644 index 563db63..0000000 --- a/test/chroot.go +++ /dev/null @@ -1,123 +0,0 @@ -package test - -import ( - "os" - - . "gopkg.in/check.v1" - . "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/util" -) - -// ChrootSuite is a convenient test suite to validate any implementation of -// billy.Chroot -type ChrootSuite struct { - FS interface { - Basic - Chroot - } -} - -func (s *ChrootSuite) TestCreateWithChroot(c *C) { - fs, _ := s.FS.Chroot("foo") - f, err := fs.Create("bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - c.Assert(f.Name(), Equals, "bar") - - f, err = s.FS.Open("foo/bar") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, s.FS.Join("foo", "bar")) - c.Assert(f.Close(), IsNil) -} - -func (s *ChrootSuite) TestOpenWithChroot(c *C) { - fs, _ := s.FS.Chroot("foo") - f, err := fs.Create("bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - c.Assert(f.Name(), Equals, "bar") - - f, err = fs.Open("bar") - c.Assert(err, IsNil) - c.Assert(f.Name(), Equals, "bar") - c.Assert(f.Close(), IsNil) -} - -func (s *ChrootSuite) TestOpenOutOffBoundary(c *C) { - err := util.WriteFile(s.FS, "bar", nil, 0644) - c.Assert(err, IsNil) - - fs, _ := s.FS.Chroot("foo") - f, err := fs.Open("../bar") - c.Assert(err, Equals, ErrCrossedBoundary) - c.Assert(f, IsNil) -} - -func (s *ChrootSuite) TestStatOutOffBoundary(c *C) { - err := util.WriteFile(s.FS, "bar", nil, 0644) - c.Assert(err, IsNil) - - fs, _ := s.FS.Chroot("foo") - f, err := fs.Stat("../bar") - c.Assert(err, Equals, ErrCrossedBoundary) - c.Assert(f, IsNil) -} - -func (s *ChrootSuite) TestStatWithChroot(c *C) { - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - // Some implementations detect directories based on a prefix - // for all files; it's easy to miss path separator handling there. - fi, err := s.FS.Stat("qu") - c.Assert(os.IsNotExist(err), Equals, true, Commentf("error: %s", err)) - c.Assert(fi, IsNil) - - fi, err = s.FS.Stat("qux") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "qux") - c.Assert(fi.IsDir(), Equals, true) - - qux, _ := s.FS.Chroot("qux") - - fi, err = qux.Stat("baz") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "baz") - c.Assert(fi.IsDir(), Equals, false) - - fi, err = qux.Stat("/baz") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "baz") - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *ChrootSuite) TestRenameOutOffBoundary(c *C) { - err := util.WriteFile(s.FS, "foo/foo", nil, 0644) - c.Assert(err, IsNil) - - err = util.WriteFile(s.FS, "bar", nil, 0644) - c.Assert(err, IsNil) - - fs, _ := s.FS.Chroot("foo") - err = fs.Rename("../bar", "foo") - c.Assert(err, Equals, ErrCrossedBoundary) - - err = fs.Rename("foo", "../bar") - c.Assert(err, Equals, ErrCrossedBoundary) -} - -func (s *ChrootSuite) TestRemoveOutOffBoundary(c *C) { - err := util.WriteFile(s.FS, "bar", nil, 0644) - c.Assert(err, IsNil) - - fs, _ := s.FS.Chroot("foo") - err = fs.Remove("../bar") - c.Assert(err, Equals, ErrCrossedBoundary) -} - -func (s *FilesystemSuite) TestRoot(c *C) { - c.Assert(s.FS.Root(), Not(Equals), "") -} diff --git a/test/chroot_test.go b/test/chroot_test.go new file mode 100644 index 0000000..1884bba --- /dev/null +++ b/test/chroot_test.go @@ -0,0 +1,145 @@ +package test + +import ( + "fmt" + "os" + "testing" + + . "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" +) + +type chrootFS interface { + Basic + Chroot +} + +func eachChrootFS(t *testing.T, test func(t *testing.T, fs chrootFS)) { + for _, fs := range allFS(t.TempDir) { + t.Run(fmt.Sprintf("%T", fs), func(t *testing.T) { + test(t, fs) + }) + } +} + +func TestCreateWithChroot(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + chroot, _ := fs.Chroot("foo") + f, err := chroot.Create("bar") + assert.Nil(t, err) + assert.Nil(t, f.Close()) + assert.Equal(t, f.Name(), "bar") + + f, err = fs.Open("foo/bar") + assert.Nil(t, err) + assert.Equal(t, f.Name(), fs.Join("foo", "bar")) + assert.Nil(t, f.Close()) + }) +} + +func TestOpenWithChroot(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + chroot, _ := fs.Chroot("foo") + f, err := chroot.Create("bar") + assert.Nil(t, err) + assert.Nil(t, f.Close()) + assert.Equal(t, f.Name(), "bar") + + f, err = chroot.Open("bar") + assert.Nil(t, err) + assert.Equal(t, f.Name(), "bar") + assert.Nil(t, f.Close()) + }) +} + +func TestOpenOutOffBoundary(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + err := util.WriteFile(fs, "bar", nil, 0644) + assert.Nil(t, err) + + chroot, _ := fs.Chroot("foo") + f, err := chroot.Open("../bar") + assert.Equal(t, err, ErrCrossedBoundary) + assert.Nil(t, f) + }) +} + +func TestStatOutOffBoundary(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + err := util.WriteFile(fs, "bar", nil, 0644) + assert.Nil(t, err) + + chroot, _ := fs.Chroot("foo") + f, err := chroot.Stat("../bar") + assert.Equal(t, err, ErrCrossedBoundary) + assert.Nil(t, f) + }) +} + +func TestStatWithChroot(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + files := []string{"foo", "bar", "qux/baz", "qux/qux"} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.Nil(t, err) + } + + // Some implementations detect directories based on a prefix + // for all files; it's easy to miss path separator handling there. + fi, err := fs.Stat("qu") + assert.ErrorIs(t, err, os.ErrNotExist) + assert.Nil(t, fi) + + fi, err = fs.Stat("qux") + assert.Nil(t, err) + assert.Equal(t, fi.Name(), "qux") + assert.Equal(t, fi.IsDir(), true) + + qux, _ := fs.Chroot("qux") + + fi, err = qux.Stat("baz") + assert.Nil(t, err) + assert.Equal(t, fi.Name(), "baz") + assert.Equal(t, fi.IsDir(), false) + + fi, err = qux.Stat("/baz") + assert.Nil(t, err) + assert.Equal(t, fi.Name(), "baz") + assert.Equal(t, fi.IsDir(), false) + }) +} + +func TestRenameOutOffBoundary(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + err := util.WriteFile(fs, "foo/foo", nil, 0644) + assert.Nil(t, err) + + err = util.WriteFile(fs, "bar", nil, 0644) + assert.Nil(t, err) + + chroot, _ := fs.Chroot("foo") + err = chroot.Rename("../bar", "foo") + assert.Equal(t, err, ErrCrossedBoundary) + + err = chroot.Rename("foo", "../bar") + assert.Equal(t, err, ErrCrossedBoundary) + }) +} + +func TestRemoveOutOffBoundary(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + err := util.WriteFile(fs, "bar", nil, 0644) + assert.Nil(t, err) + + chroot, _ := fs.Chroot("foo") + err = chroot.Remove("../bar") + assert.Equal(t, err, ErrCrossedBoundary) + }) +} + +func TestRoot(t *testing.T) { + eachChrootFS(t, func(t *testing.T, fs chrootFS) { + assert.NotEmpty(t, fs.Root()) + }) +} diff --git a/test/common_mem.go b/test/common_mem.go new file mode 100644 index 0000000..a5cb3ef --- /dev/null +++ b/test/common_mem.go @@ -0,0 +1,21 @@ +//go:build wasip1 || wasm || js + +package test + +import ( + "os" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" +) + +var ( + customMode os.FileMode = 0o600 + expectedSymlinkTarget = "/dir/file" +) + +func allFS(_ func() string) []billy.Filesystem { + return []billy.Filesystem{ + memfs.New(), + } +} diff --git a/test/common_posix.go b/test/common_posix.go index 010c844..b9e3965 100644 --- a/test/common_posix.go +++ b/test/common_posix.go @@ -1,11 +1,24 @@ -//go:build !windows && !wasip1 -// +build !windows,!wasip1 +//go:build !windows && !wasip1 && !js && !wasp +// +build !windows,!wasip1,!js,!wasp package test -import "os" +import ( + "os" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" + "github.com/go-git/go-billy/v5/osfs" +) var ( - customMode os.FileMode = 0755 + customMode os.FileMode = 0o755 expectedSymlinkTarget = "/dir/file" ) + +func allFS(tempDir func() string) []billy.Filesystem { + return []billy.Filesystem{ + osfs.New(tempDir(), osfs.WithChrootOS()), + memfs.New(), + } +} diff --git a/test/common_wasip1.go b/test/common_wasip1.go deleted file mode 100644 index 99951b2..0000000 --- a/test/common_wasip1.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build wasip1 -// +build wasip1 - -package test - -import "os" - -var ( - customMode os.FileMode = 0600 - expectedSymlinkTarget = "/dir/file" -) diff --git a/test/common_windows.go b/test/common_windows.go index 288ac0f..1e19feb 100644 --- a/test/common_windows.go +++ b/test/common_windows.go @@ -1,10 +1,24 @@ +//go:build windows // +build windows package test -import "os" +import ( + "os" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" + "github.com/go-git/go-billy/v5/osfs" +) var ( - customMode os.FileMode = 0666 + customMode os.FileMode = 0o666 expectedSymlinkTarget = "\\dir\\file" ) + +func allFS(tempDir func() string) []billy.Filesystem { + return []billy.Filesystem{ + osfs.New(tempDir(), osfs.WithChrootOS()), + memfs.New(), + } +} diff --git a/test/dir.go b/test/dir.go deleted file mode 100644 index 78ccff8..0000000 --- a/test/dir.go +++ /dev/null @@ -1,266 +0,0 @@ -package test - -import ( - "os" - "strconv" - - . "gopkg.in/check.v1" - . "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/util" -) - -// DirSuite is a convenient test suite to validate any implementation of -// billy.Dir -type DirSuite struct { - FS interface { - Basic - Dir - } -} - -func (s *DirSuite) TestMkdirAll(c *C) { - err := s.FS.MkdirAll("empty", os.FileMode(0755)) - c.Assert(err, IsNil) - - fi, err := s.FS.Stat("empty") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, true) -} - -func (s *DirSuite) TestMkdirAllNested(c *C) { - err := s.FS.MkdirAll("foo/bar/baz", os.FileMode(0755)) - c.Assert(err, IsNil) - - fi, err := s.FS.Stat("foo/bar/baz") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, true) - - fi, err = s.FS.Stat("foo/bar") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, true) - - fi, err = s.FS.Stat("foo") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, true) -} - -func (s *DirSuite) TestMkdirAllIdempotent(c *C) { - err := s.FS.MkdirAll("empty", 0755) - c.Assert(err, IsNil) - fi, err := s.FS.Stat("empty") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, true) - - // idempotent - err = s.FS.MkdirAll("empty", 0755) - c.Assert(err, IsNil) - fi, err = s.FS.Stat("empty") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, true) -} - -func (s *DirSuite) TestMkdirAllAndCreate(c *C) { - err := s.FS.MkdirAll("dir", os.FileMode(0755)) - c.Assert(err, IsNil) - - f, err := s.FS.Create("dir/bar/foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - fi, err := s.FS.Stat("dir/bar/foo") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *DirSuite) TestMkdirAllWithExistingFile(c *C) { - f, err := s.FS.Create("dir/foo") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - err = s.FS.MkdirAll("dir/foo", os.FileMode(0755)) - c.Assert(err, NotNil) - - fi, err := s.FS.Stat("dir/foo") - c.Assert(err, IsNil) - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *DirSuite) TestStatDir(c *C) { - s.FS.MkdirAll("foo/bar", 0755) - - fi, err := s.FS.Stat("foo/bar") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "bar") - c.Assert(fi.Mode().IsDir(), Equals, true) - c.Assert(fi.ModTime().IsZero(), Equals, false) - c.Assert(fi.IsDir(), Equals, true) -} - -func (s *BasicSuite) TestStatDeep(c *C) { - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - // Some implementations detect directories based on a prefix - // for all files; it's easy to miss path separator handling there. - fi, err := s.FS.Stat("qu") - c.Assert(os.IsNotExist(err), Equals, true, Commentf("error: %s", err)) - c.Assert(fi, IsNil) - - fi, err = s.FS.Stat("qux") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "qux") - c.Assert(fi.IsDir(), Equals, true) - - fi, err = s.FS.Stat("qux/baz") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "baz") - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *DirSuite) TestReadDir(c *C) { - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - info, err := s.FS.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 3) - - info, err = s.FS.ReadDir("/qux") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} - -func (s *DirSuite) TestReadDirNested(c *C) { - max := 100 - path := "/" - for i := 0; i <= max; i++ { - path = s.FS.Join(path, strconv.Itoa(i)) - } - - files := []string{s.FS.Join(path, "f1"), s.FS.Join(path, "f2")} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - path = "/" - for i := 0; i < max; i++ { - path = s.FS.Join(path, strconv.Itoa(i)) - info, err := s.FS.ReadDir(path) - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - } - - path = s.FS.Join(path, strconv.Itoa(max)) - info, err := s.FS.ReadDir(path) - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} - -func (s *DirSuite) TestReadDirWithMkDirAll(c *C) { - err := s.FS.MkdirAll("qux", 0755) - c.Assert(err, IsNil) - - files := []string{"qux/baz", "qux/qux"} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - info, err := s.FS.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - c.Assert(info[0].IsDir(), Equals, true) - - info, err = s.FS.ReadDir("/qux") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} - -func (s *DirSuite) TestReadDirFileInfo(c *C) { - err := util.WriteFile(s.FS, "foo", []byte{'F', 'O', 'O'}, 0644) - c.Assert(err, IsNil) - - info, err := s.FS.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - - c.Assert(info[0].Size(), Equals, int64(3)) - c.Assert(info[0].IsDir(), Equals, false) - c.Assert(info[0].Name(), Equals, "foo") -} - -func (s *DirSuite) TestReadDirFileInfoDirs(c *C) { - files := []string{"qux/baz/foo"} - for _, name := range files { - err := util.WriteFile(s.FS, name, []byte{'F', 'O', 'O'}, 0644) - c.Assert(err, IsNil) - } - - info, err := s.FS.ReadDir("qux") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - c.Assert(info[0].IsDir(), Equals, true) - c.Assert(info[0].Name(), Equals, "baz") - - info, err = s.FS.ReadDir("qux/baz") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - c.Assert(info[0].Size(), Equals, int64(3)) - c.Assert(info[0].IsDir(), Equals, false) - c.Assert(info[0].Name(), Equals, "foo") - c.Assert(info[0].Mode(), Not(Equals), 0) -} - -func (s *DirSuite) TestRenameToDir(c *C) { - err := util.WriteFile(s.FS, "foo", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Rename("foo", "bar/qux") - c.Assert(err, IsNil) - - old, err := s.FS.Stat("foo") - c.Assert(old, IsNil) - c.Assert(os.IsNotExist(err), Equals, true) - - dir, err := s.FS.Stat("bar") - c.Assert(dir, NotNil) - c.Assert(err, IsNil) - - file, err := s.FS.Stat("bar/qux") - c.Assert(file.Name(), Equals, "qux") - c.Assert(err, IsNil) -} - -func (s *DirSuite) TestRenameDir(c *C) { - err := s.FS.MkdirAll("foo", 0755) - c.Assert(err, IsNil) - - err = util.WriteFile(s.FS, "foo/bar", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Rename("foo", "bar") - c.Assert(err, IsNil) - - dirfoo, err := s.FS.Stat("foo") - c.Assert(dirfoo, IsNil) - c.Assert(os.IsNotExist(err), Equals, true) - - dirbar, err := s.FS.Stat("bar") - c.Assert(err, IsNil) - c.Assert(dirbar, NotNil) - - foo, err := s.FS.Stat("foo/bar") - c.Assert(os.IsNotExist(err), Equals, true) - c.Assert(foo, IsNil) - - bar, err := s.FS.Stat("bar/bar") - c.Assert(err, IsNil) - c.Assert(bar, NotNil) -} diff --git a/test/dir_test.go b/test/dir_test.go new file mode 100644 index 0000000..80050d6 --- /dev/null +++ b/test/dir_test.go @@ -0,0 +1,300 @@ +package test + +import ( + "fmt" + "os" + "strconv" + "testing" + + . "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" +) + +type dirFS interface { + Basic + Dir +} + +func eachDirFS(t *testing.T, test func(t *testing.T, fs dirFS)) { + for _, fs := range allFS(t.TempDir) { + t.Run(fmt.Sprintf("%T", fs), func(t *testing.T) { + test(t, fs) + }) + } +} + +func TestDir_MkdirAll(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := fs.MkdirAll("empty", os.FileMode(0755)) + assert.NoError(t, err) + + fi, err := fs.Stat("empty") + assert.NoError(t, err) + assert.True(t, fi.IsDir()) + }) +} + +func TestDir_MkdirAllNested(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := fs.MkdirAll("foo/bar/baz", os.FileMode(0755)) + assert.NoError(t, err) + + fi, err := fs.Stat("foo/bar/baz") + assert.NoError(t, err) + assert.True(t, fi.IsDir()) + + fi, err = fs.Stat("foo/bar") + assert.NoError(t, err) + assert.True(t, fi.IsDir()) + + fi, err = fs.Stat("foo") + assert.NoError(t, err) + assert.True(t, fi.IsDir()) + }) +} + +func TestDir_MkdirAllIdempotent(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := fs.MkdirAll("empty", 0755) + assert.NoError(t, err) + fi, err := fs.Stat("empty") + assert.NoError(t, err) + assert.True(t, fi.IsDir()) + + // idempotent + err = fs.MkdirAll("empty", 0755) + assert.NoError(t, err) + fi, err = fs.Stat("empty") + assert.NoError(t, err) + assert.True(t, fi.IsDir()) + }) +} + +func TestDir_MkdirAllAndCreate(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := fs.MkdirAll("dir", os.FileMode(0755)) + assert.NoError(t, err) + + f, err := fs.Create("dir/bar/foo") + assert.NoError(t, err) + assert.Nil(t, f.Close()) + + fi, err := fs.Stat("dir/bar/foo") + assert.NoError(t, err) + assert.False(t, fi.IsDir()) + }) +} + +func TestDir_MkdirAllWithExistingFile(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + f, err := fs.Create("dir/foo") + assert.NoError(t, err) + assert.Nil(t, f.Close()) + + err = fs.MkdirAll("dir/foo", os.FileMode(0755)) + assert.Error(t, err) + + fi, err := fs.Stat("dir/foo") + assert.NoError(t, err) + assert.False(t, fi.IsDir()) + }) +} + +func TestDir_StatDir(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + fs.MkdirAll("foo/bar", 0755) + + fi, err := fs.Stat("foo/bar") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "bar") + assert.Equal(t, fi.Mode().IsDir(), true) + assert.Equal(t, fi.ModTime().IsZero(), false) + assert.True(t, fi.IsDir()) + }) +} + +func TestDir_StatDeep(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + files := []string{"foo", "bar", "qux/baz", "qux/qux"} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.NoError(t, err) + } + + // Some implementations detect directories based on a prefix + // for all files; it's easy to miss path separator handling there. + fi, err := fs.Stat("qu") + assert.ErrorIs(t, err, os.ErrNotExist) + assert.Nil(t, fi) + + fi, err = fs.Stat("qux") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "qux") + assert.True(t, fi.IsDir()) + + fi, err = fs.Stat("qux/baz") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "baz") + assert.False(t, fi.IsDir()) + }) +} + +func TestDir_ReadDir(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + files := []string{"foo", "bar", "qux/baz", "qux/qux"} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.NoError(t, err) + } + + info, err := fs.ReadDir("/") + assert.NoError(t, err) + assert.Len(t, info, 3) + + info, err = fs.ReadDir("/qux") + assert.NoError(t, err) + assert.Len(t, info, 2) + }) +} + +func TestDir_ReadDirNested(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + max := 100 + path := "/" + for i := 0; i <= max; i++ { + path = fs.Join(path, strconv.Itoa(i)) + } + + files := []string{fs.Join(path, "f1"), fs.Join(path, "f2")} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.NoError(t, err) + } + + path = "/" + for i := 0; i < max; i++ { + path = fs.Join(path, strconv.Itoa(i)) + info, err := fs.ReadDir(path) + assert.NoError(t, err) + assert.Len(t, info, 1) + } + + path = fs.Join(path, strconv.Itoa(max)) + info, err := fs.ReadDir(path) + assert.NoError(t, err) + assert.Len(t, info, 2) + }) +} + +func TestDir_ReadDirWithMkDirAll(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := fs.MkdirAll("qux", 0755) + assert.NoError(t, err) + + files := []string{"qux/baz", "qux/qux"} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.NoError(t, err) + } + + info, err := fs.ReadDir("/") + assert.NoError(t, err) + assert.Len(t, info, 1) + assert.Equal(t, info[0].IsDir(), true) + + info, err = fs.ReadDir("/qux") + assert.NoError(t, err) + assert.Len(t, info, 2) + }) +} + +func TestDir_ReadDirFileInfo(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := util.WriteFile(fs, "foo", []byte{'F', 'O', 'O'}, 0644) + assert.NoError(t, err) + + info, err := fs.ReadDir("/") + assert.NoError(t, err) + assert.Len(t, info, 1) + + assert.Equal(t, info[0].Size(), int64(3)) + assert.Equal(t, info[0].IsDir(), false) + assert.Equal(t, info[0].Name(), "foo") + }) +} + +func TestDir_ReadDirFileInfoDirs(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + files := []string{"qux/baz/foo"} + for _, name := range files { + err := util.WriteFile(fs, name, []byte{'F', 'O', 'O'}, 0644) + assert.NoError(t, err) + } + + info, err := fs.ReadDir("qux") + assert.NoError(t, err) + assert.Len(t, info, 1) + assert.Equal(t, info[0].IsDir(), true) + assert.Equal(t, info[0].Name(), "baz") + + info, err = fs.ReadDir("qux/baz") + assert.NoError(t, err) + assert.Len(t, info, 1) + assert.Equal(t, info[0].Size(), int64(3)) + assert.Equal(t, info[0].IsDir(), false) + assert.Equal(t, info[0].Name(), "foo") + assert.NotEqual(t, info[0].Mode(), 0) + }) +} + +func TestDir_RenameToDir(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := util.WriteFile(fs, "foo", nil, 0644) + assert.NoError(t, err) + + err = fs.Rename("foo", "bar/qux") + assert.NoError(t, err) + + old, err := fs.Stat("foo") + assert.Nil(t, old) + assert.Equal(t, os.IsNotExist(err), true) + + dir, err := fs.Stat("bar") + assert.NotNil(t, dir) + assert.NoError(t, err) + + file, err := fs.Stat("bar/qux") + assert.Equal(t, file.Name(), "qux") + assert.NoError(t, err) + }) +} + +func TestDir_RenameDir(t *testing.T) { + eachDirFS(t, func(t *testing.T, fs dirFS) { + err := fs.MkdirAll("foo", 0755) + assert.NoError(t, err) + + err = util.WriteFile(fs, "foo/bar", nil, 0644) + assert.NoError(t, err) + + err = fs.Rename("foo", "bar") + assert.NoError(t, err) + + dirfoo, err := fs.Stat("foo") + assert.Nil(t, dirfoo) + assert.Equal(t, os.IsNotExist(err), true) + + dirbar, err := fs.Stat("bar") + assert.NoError(t, err) + assert.NotNil(t, dirbar) + + foo, err := fs.Stat("foo/bar") + assert.Equal(t, os.IsNotExist(err), true) + assert.Nil(t, foo) + + bar, err := fs.Stat("bar/bar") + assert.NoError(t, err) + assert.NotNil(t, bar) + }) +} diff --git a/test/fs.go b/test/fs.go deleted file mode 100644 index 82916dc..0000000 --- a/test/fs.go +++ /dev/null @@ -1,223 +0,0 @@ -package test - -import ( - "os" - "runtime" - - . "gopkg.in/check.v1" - . "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/util" -) - -// FilesystemSuite is a convenient test suite to validate any implementation of -// billy.Filesystem -type FilesystemSuite struct { - FS Filesystem - - BasicSuite - DirSuite - SymlinkSuite - TempFileSuite - ChrootSuite -} - -// NewFilesystemSuite returns a new FilesystemSuite based on the given fs. -func NewFilesystemSuite(fs Filesystem) FilesystemSuite { - s := FilesystemSuite{FS: fs} - s.BasicSuite.FS = s.FS - s.DirSuite.FS = s.FS - s.SymlinkSuite.FS = s.FS - s.TempFileSuite.FS = s.FS - s.ChrootSuite.FS = s.FS - - return s -} - -func (s *FilesystemSuite) TestSymlinkToDir(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := s.FS.MkdirAll("dir", 0755) - c.Assert(err, IsNil) - - err = s.FS.Symlink("dir", "link") - c.Assert(err, IsNil) - - fi, err := s.FS.Stat("link") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "link") - c.Assert(fi.IsDir(), Equals, true) -} - -func (s *FilesystemSuite) TestSymlinkReadDir(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "dir/file", []byte("foo"), 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("dir", "link") - c.Assert(err, IsNil) - - info, err := s.FS.ReadDir("link") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 1) - - c.Assert(info[0].Size(), Equals, int64(3)) - c.Assert(info[0].IsDir(), Equals, false) - c.Assert(info[0].Name(), Equals, "file") -} - -func (s *FilesystemSuite) TestCreateWithExistantDir(c *C) { - err := s.FS.MkdirAll("foo", 0644) - c.Assert(err, IsNil) - - f, err := s.FS.Create("foo") - c.Assert(err, NotNil) - c.Assert(f, IsNil) -} - -func (s *ChrootSuite) TestReadDirWithChroot(c *C) { - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - qux, _ := s.FS.Chroot("/qux") - - info, err := qux.(Filesystem).ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} - -func (s *FilesystemSuite) TestSymlinkWithChrootBasic(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - qux, _ := s.FS.Chroot("/qux") - - err := util.WriteFile(qux, "file", nil, 0644) - c.Assert(err, IsNil) - - err = qux.(Filesystem).Symlink("file", "link") - c.Assert(err, IsNil) - - fi, err := qux.Stat("link") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "link") - - fi, err = s.FS.Stat("qux/link") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "link") -} - -func (s *FilesystemSuite) TestSymlinkWithChrootCrossBounders(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - qux, _ := s.FS.Chroot("/qux") - util.WriteFile(s.FS, "file", []byte("foo"), customMode) - - err := qux.Symlink("../../file", "qux/link") - c.Assert(err, Equals, nil) - - fi, err := qux.Stat("qux/link") - c.Assert(fi, NotNil) - c.Assert(err, Equals, nil) -} - -func (s *FilesystemSuite) TestReadDirWithLink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - util.WriteFile(s.FS, "foo/bar", []byte("foo"), customMode) - s.FS.Symlink("bar", "foo/qux") - - info, err := s.FS.ReadDir("/foo") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} - -func (s *FilesystemSuite) TestRemoveAllNonExistent(c *C) { - c.Assert(util.RemoveAll(s.FS, "non-existent"), IsNil) -} - -func (s *FilesystemSuite) TestRemoveAllEmptyDir(c *C) { - c.Assert(s.FS.MkdirAll("empty", os.FileMode(0755)), IsNil) - c.Assert(util.RemoveAll(s.FS, "empty"), IsNil) - _, err := s.FS.Stat("empty") - c.Assert(err, NotNil) - c.Assert(os.IsNotExist(err), Equals, true) -} - -func (s *FilesystemSuite) TestRemoveAll(c *C) { - fnames := []string{ - "foo/1", - "foo/2", - "foo/bar/1", - "foo/bar/2", - "foo/bar/baz/1", - "foo/bar/baz/qux/1", - "foo/bar/baz/qux/2", - "foo/bar/baz/qux/3", - } - - for _, fname := range fnames { - err := util.WriteFile(s.FS, fname, nil, 0644) - c.Assert(err, IsNil) - } - - c.Assert(util.RemoveAll(s.FS, "foo"), IsNil) - - for _, fname := range fnames { - _, err := s.FS.Stat(fname) - comment := Commentf("not removed: %s %s", fname, err) - c.Assert(os.IsNotExist(err), Equals, true, comment) - } -} - -func (s *FilesystemSuite) TestRemoveAllRelative(c *C) { - fnames := []string{ - "foo/1", - "foo/2", - "foo/bar/1", - "foo/bar/2", - "foo/bar/baz/1", - "foo/bar/baz/qux/1", - "foo/bar/baz/qux/2", - "foo/bar/baz/qux/3", - } - - for _, fname := range fnames { - err := util.WriteFile(s.FS, fname, nil, 0644) - c.Assert(err, IsNil) - } - - c.Assert(util.RemoveAll(s.FS, "foo/bar/.."), IsNil) - - for _, fname := range fnames { - _, err := s.FS.Stat(fname) - comment := Commentf("not removed: %s %s", fname, err) - c.Assert(os.IsNotExist(err), Equals, true, comment) - } -} - -func (s *FilesystemSuite) TestReadDir(c *C) { - err := s.FS.MkdirAll("qux", 0755) - c.Assert(err, IsNil) - - files := []string{"foo", "bar", "qux/baz", "qux/qux"} - for _, name := range files { - err := util.WriteFile(s.FS, name, nil, 0644) - c.Assert(err, IsNil) - } - - info, err := s.FS.ReadDir("/") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 3) - - info, err = s.FS.ReadDir("/qux") - c.Assert(err, IsNil) - c.Assert(info, HasLen, 2) -} diff --git a/test/fs_test.go b/test/fs_test.go new file mode 100644 index 0000000..5b4a519 --- /dev/null +++ b/test/fs_test.go @@ -0,0 +1,231 @@ +package test + +import ( + "fmt" + "os" + "runtime" + "testing" + + . "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" +) + +func eachFS(t *testing.T, test func(t *testing.T, fs Filesystem)) { + for _, fs := range allFS(t.TempDir) { + t.Run(fmt.Sprintf("%T", fs), func(t *testing.T) { + test(t, fs) + }) + } +} + +func TestFS_SymlinkToDir(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + eachFS(t, func(t *testing.T, fs Filesystem) { + err := fs.MkdirAll("dir", 0755) + assert.NoError(t, err) + + err = fs.Symlink("dir", "link") + assert.NoError(t, err) + + fi, err := fs.Stat("link") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "link") + assert.True(t, fi.IsDir()) + }) +} + +func TestFS_SymlinkReadDir(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + eachFS(t, func(t *testing.T, fs Filesystem) { + err := util.WriteFile(fs, "dir/file", []byte("foo"), 0644) + assert.NoError(t, err) + + err = fs.Symlink("dir", "link") + assert.NoError(t, err) + + info, err := fs.ReadDir("link") + assert.NoError(t, err) + assert.Len(t, info, 1) + + assert.Equal(t, info[0].Size(), int64(3)) + assert.Equal(t, info[0].IsDir(), false) + assert.Equal(t, info[0].Name(), "file") + }) +} + +func TestFS_CreateWithExistantDir(t *testing.T) { + eachFS(t, func(t *testing.T, fs Filesystem) { + err := fs.MkdirAll("foo", 0644) + assert.NoError(t, err) + + f, err := fs.Create("foo") + assert.Error(t, err) + assert.Nil(t, f) + }) +} + +func TestFS_ReadDirWithChroot(t *testing.T) { + eachFS(t, func(t *testing.T, fs Filesystem) { + files := []string{"foo", "bar", "qux/baz", "qux/qux"} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.NoError(t, err) + } + + qux, _ := fs.Chroot("/qux") + + info, err := qux.(Filesystem).ReadDir("/") + assert.NoError(t, err) + assert.Len(t, info, 2) + }) +} + +func TestFS_SymlinkWithChrootBasic(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + eachFS(t, func(t *testing.T, fs Filesystem) { + qux, _ := fs.Chroot("/qux") + + err := util.WriteFile(qux, "file", nil, 0644) + assert.NoError(t, err) + + err = qux.(Filesystem).Symlink("file", "link") + assert.NoError(t, err) + + fi, err := qux.Stat("link") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "link") + + fi, err = fs.Stat("qux/link") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "link") + }) +} + +func TestFS_SymlinkWithChrootCrossBounders(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + eachFS(t, func(t *testing.T, fs Filesystem) { + qux, _ := fs.Chroot("/qux") + util.WriteFile(fs, "file", []byte("foo"), customMode) + + err := qux.Symlink("../../file", "qux/link") + assert.Equal(t, err, nil) + + fi, err := qux.Stat("qux/link") + assert.NotNil(t, fi) + assert.Equal(t, err, nil) + }) +} + +func TestFS_ReadDirWithLink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + eachFS(t, func(t *testing.T, fs Filesystem) { + util.WriteFile(fs, "foo/bar", []byte("foo"), customMode) + fs.Symlink("bar", "foo/qux") + + info, err := fs.ReadDir("/foo") + assert.NoError(t, err) + assert.Len(t, info, 2) + }) +} + +func TestFS_RemoveAllNonExistent(t *testing.T) { + eachFS(t, func(t *testing.T, fs Filesystem) { + assert.NoError(t, util.RemoveAll(fs, "non-existent")) + }) +} + +func TestFS_RemoveAllEmptyDir(t *testing.T) { + eachFS(t, func(t *testing.T, fs Filesystem) { + assert.NoError(t, fs.MkdirAll("empty", os.FileMode(0755))) + assert.NoError(t, util.RemoveAll(fs, "empty")) + _, err := fs.Stat("empty") + assert.Error(t, err) + assert.Equal(t, os.IsNotExist(err), true) + }) +} + +func TestFS_RemoveAll(t *testing.T) { + fnames := []string{ + "foo/1", + "foo/2", + "foo/bar/1", + "foo/bar/2", + "foo/bar/baz/1", + "foo/bar/baz/qux/1", + "foo/bar/baz/qux/2", + "foo/bar/baz/qux/3", + } + + eachFS(t, func(t *testing.T, fs Filesystem) { + for _, fname := range fnames { + err := util.WriteFile(fs, fname, nil, 0644) + assert.NoError(t, err) + } + + assert.NoError(t, util.RemoveAll(fs, "foo")) + + for _, fname := range fnames { + _, err := fs.Stat(fname) + assert.ErrorIsf(t, err, os.ErrNotExist, "not removed: %s %s", fname, err) + } + }) +} + +func TestFS_RemoveAllRelative(t *testing.T) { + fnames := []string{ + "foo/1", + "foo/2", + "foo/bar/1", + "foo/bar/2", + "foo/bar/baz/1", + "foo/bar/baz/qux/1", + "foo/bar/baz/qux/2", + "foo/bar/baz/qux/3", + } + + eachFS(t, func(t *testing.T, fs Filesystem) { + for _, fname := range fnames { + err := util.WriteFile(fs, fname, nil, 0644) + assert.NoError(t, err) + } + + assert.NoError(t, util.RemoveAll(fs, "foo/bar/..")) + + for _, fname := range fnames { + _, err := fs.Stat(fname) + assert.ErrorIsf(t, err, os.ErrNotExist, "not removed: %s %s", fname, err) + } + }) +} + +func TestFS_ReadDir(t *testing.T) { + eachFS(t, func(t *testing.T, fs Filesystem) { + err := fs.MkdirAll("qux", 0755) + assert.NoError(t, err) + + files := []string{"foo", "bar", "qux/baz", "qux/qux"} + for _, name := range files { + err := util.WriteFile(fs, name, nil, 0644) + assert.NoError(t, err) + } + + info, err := fs.ReadDir("/") + assert.NoError(t, err) + assert.Len(t, info, 3) + + info, err = fs.ReadDir("/qux") + assert.NoError(t, err) + assert.Len(t, info, 2) + }) +} diff --git a/test/symlink.go b/test/symlink.go deleted file mode 100644 index 72b1c69..0000000 --- a/test/symlink.go +++ /dev/null @@ -1,276 +0,0 @@ -package test - -import ( - "io/ioutil" - "os" - "runtime" - - . "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/util" - . "gopkg.in/check.v1" -) - -// SymlinkSuite is a convenient test suite to validate any implementation of -// billy.Symlink -type SymlinkSuite struct { - FS interface { - Basic - Symlink - } -} - -func (s *SymlinkSuite) TestSymlink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "file", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("file", "link") - c.Assert(err, IsNil) - - fi, err := s.FS.Stat("link") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "link") -} - -func (s *SymlinkSuite) TestSymlinkCrossDirs(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "foo/file", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("../foo/file", "bar/link") - c.Assert(err, IsNil) - - fi, err := s.FS.Stat("bar/link") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "link") -} - -func (s *SymlinkSuite) TestSymlinkNested(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "file", []byte("hello world!"), 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("file", "linkA") - c.Assert(err, IsNil) - - err = s.FS.Symlink("linkA", "linkB") - c.Assert(err, IsNil) - - fi, err := s.FS.Stat("linkB") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "linkB") - c.Assert(fi.Size(), Equals, int64(12)) -} - -func (s *SymlinkSuite) TestSymlinkWithNonExistentdTarget(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := s.FS.Symlink("file", "link") - c.Assert(err, IsNil) - - _, err = s.FS.Stat("link") - c.Assert(os.IsNotExist(err), Equals, true) -} - -func (s *SymlinkSuite) TestSymlinkWithExistingLink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "link", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("file", "link") - c.Assert(err, Not(IsNil)) -} - -func (s *SymlinkSuite) TestOpenWithSymlinkToRelativePath(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "dir/file", []byte("foo"), 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("file", "dir/link") - c.Assert(err, IsNil) - - f, err := s.FS.Open("dir/link") - c.Assert(err, IsNil) - - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(all), Equals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *SymlinkSuite) TestOpenWithSymlinkToAbsolutePath(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - if runtime.GOOS == "wasip1" { - c.Skip("skipping on wasip1") - } - err := util.WriteFile(s.FS, "dir/file", []byte("foo"), 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("/dir/file", "dir/link") - c.Assert(err, IsNil) - - f, err := s.FS.Open("dir/link") - c.Assert(err, IsNil) - - all, err := ioutil.ReadAll(f) - c.Assert(err, IsNil) - c.Assert(string(all), Equals, "foo") - c.Assert(f.Close(), IsNil) -} - -func (s *SymlinkSuite) TestReadlink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "file", nil, 0644) - c.Assert(err, IsNil) - - _, err = s.FS.Readlink("file") - c.Assert(err, Not(IsNil)) -} - -func (s *SymlinkSuite) TestReadlinkWithRelativePath(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "dir/file", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("file", "dir/link") - c.Assert(err, IsNil) - - oldname, err := s.FS.Readlink("dir/link") - c.Assert(err, IsNil) - c.Assert(oldname, Equals, "file") -} - -func (s *SymlinkSuite) TestReadlinkWithAbsolutePath(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - if runtime.GOOS == "wasip1" { - c.Skip("skipping on wasip1") - } - err := util.WriteFile(s.FS, "dir/file", nil, 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("/dir/file", "dir/link") - c.Assert(err, IsNil) - - oldname, err := s.FS.Readlink("dir/link") - c.Assert(err, IsNil) - c.Assert(oldname, Equals, expectedSymlinkTarget) -} - -func (s *SymlinkSuite) TestReadlinkWithNonExistentTarget(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := s.FS.Symlink("file", "link") - c.Assert(err, IsNil) - - oldname, err := s.FS.Readlink("link") - c.Assert(err, IsNil) - c.Assert(oldname, Equals, "file") -} - -func (s *SymlinkSuite) TestReadlinkWithNonExistentLink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - _, err := s.FS.Readlink("link") - c.Assert(os.IsNotExist(err), Equals, true) -} - -func (s *SymlinkSuite) TestStatLink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - util.WriteFile(s.FS, "foo/bar", []byte("foo"), customMode) - s.FS.Symlink("bar", "foo/qux") - - fi, err := s.FS.Stat("foo/qux") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "qux") - c.Assert(fi.Size(), Equals, int64(3)) - c.Assert(fi.Mode(), Equals, customMode) - c.Assert(fi.ModTime().IsZero(), Equals, false) - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *SymlinkSuite) TestLstat(c *C) { - util.WriteFile(s.FS, "foo/bar", []byte("foo"), customMode) - - fi, err := s.FS.Lstat("foo/bar") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "bar") - c.Assert(fi.Size(), Equals, int64(3)) - c.Assert(fi.Mode()&os.ModeSymlink != 0, Equals, false) - c.Assert(fi.ModTime().IsZero(), Equals, false) - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *SymlinkSuite) TestLstatLink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - util.WriteFile(s.FS, "foo/bar", []byte("fosddddaaao"), customMode) - s.FS.Symlink("bar", "foo/qux") - - fi, err := s.FS.Lstat("foo/qux") - c.Assert(err, IsNil) - c.Assert(fi.Name(), Equals, "qux") - c.Assert(fi.Mode()&os.ModeSymlink != 0, Equals, true) - c.Assert(fi.ModTime().IsZero(), Equals, false) - c.Assert(fi.IsDir(), Equals, false) -} - -func (s *SymlinkSuite) TestRenameWithSymlink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := s.FS.Symlink("file", "link") - c.Assert(err, IsNil) - - err = s.FS.Rename("link", "newlink") - c.Assert(err, IsNil) - - _, err = s.FS.Readlink("newlink") - c.Assert(err, IsNil) -} - -func (s *SymlinkSuite) TestRemoveWithSymlink(c *C) { - if runtime.GOOS == "plan9" { - c.Skip("skipping on Plan 9; symlinks are not supported") - } - err := util.WriteFile(s.FS, "file", []byte("foo"), 0644) - c.Assert(err, IsNil) - - err = s.FS.Symlink("file", "link") - c.Assert(err, IsNil) - - err = s.FS.Remove("link") - c.Assert(err, IsNil) - - _, err = s.FS.Readlink("link") - c.Assert(os.IsNotExist(err), Equals, true) - - _, err = s.FS.Stat("link") - c.Assert(os.IsNotExist(err), Equals, true) - - _, err = s.FS.Stat("file") - c.Assert(err, IsNil) -} diff --git a/test/symlink_test.go b/test/symlink_test.go new file mode 100644 index 0000000..11c4099 --- /dev/null +++ b/test/symlink_test.go @@ -0,0 +1,336 @@ +package test + +import ( + "fmt" + "io" + "os" + "runtime" + "testing" + + . "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" +) + +type symlinkFS interface { + Basic + Symlink +} + +func eachSymlinkFS(t *testing.T, test func(t *testing.T, fs symlinkFS)) { + for _, fs := range allFS(t.TempDir) { + t.Run(fmt.Sprintf("%T", fs), func(t *testing.T) { + test(t, fs) + }) + } +} + +func TestSymlink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "file", nil, 0644) + assert.NoError(t, err) + + err = fs.Symlink("file", "link") + assert.NoError(t, err) + + fi, err := fs.Lstat("link") + assert.NoError(t, err) + assert.Equal(t, "link", fi.Name()) + + fi, err = fs.Stat("link") + assert.NoError(t, err) + assert.Equal(t, "link", fi.Name()) + }) +} + +func TestSymlinkCrossDirs(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "foo/file", nil, 0644) + assert.NoError(t, err) + + err = fs.Symlink("../foo/file", "bar/link") + assert.NoError(t, err) + + fi, err := fs.Stat("bar/link") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "link") + }) +} + +func TestSymlinkNested(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "file", []byte("hello world!"), 0644) + assert.NoError(t, err) + + err = fs.Symlink("file", "linkA") + assert.NoError(t, err) + + err = fs.Symlink("linkA", "linkB") + assert.NoError(t, err) + + fi, err := fs.Stat("linkB") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "linkB") + assert.Equal(t, fi.Size(), int64(12)) + }) +} + +func TestSymlinkWithNonExistentdTarget(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := fs.Symlink("file", "link") + assert.NoError(t, err) + + _, err = fs.Stat("link") + assert.Equal(t, os.IsNotExist(err), true) + }) +} + +func TestSymlinkWithExistingLink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "link", nil, 0644) + assert.NoError(t, err) + + err = fs.Symlink("file", "link") + assert.ErrorIs(t, err, os.ErrExist) + }) +} + +func TestOpenWithSymlinkToRelativePath(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "dir/file", []byte("foo"), 0644) + assert.NoError(t, err) + + err = fs.Symlink("file", "dir/link") + assert.NoError(t, err) + + f, err := fs.Open("dir/link") + assert.NoError(t, err) + + all, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(all), "foo") + assert.Nil(t, f.Close()) + }) +} + +func TestOpenWithSymlinkToAbsolutePath(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + if runtime.GOOS == "wasip1" { + t.Skip("skipping on wasip1") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "dir/file", []byte("foo"), 0644) + assert.NoError(t, err) + + err = fs.Symlink("/dir/file", "dir/link") + assert.NoError(t, err) + + f, err := fs.Open("dir/link") + assert.NoError(t, err) + + all, err := io.ReadAll(f) + assert.NoError(t, err) + assert.Equal(t, string(all), "foo") + assert.Nil(t, f.Close()) + }) +} + +func TestReadlink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "file", nil, 0644) + assert.NoError(t, err) + + _, err = fs.Readlink("file") + assert.Error(t, err) + }) +} + +func TestReadlinkWithRelativePath(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "dir/file", nil, 0644) + assert.NoError(t, err) + + err = fs.Symlink("file", "dir/link") + assert.NoError(t, err) + + oldname, err := fs.Readlink("dir/link") + assert.NoError(t, err) + assert.Equal(t, oldname, "file") + }) +} + +func TestReadlinkWithAbsolutePath(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + if runtime.GOOS == "wasip1" { + t.Skip("skipping on wasip1") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "dir/file", nil, 0644) + assert.NoError(t, err) + + err = fs.Symlink("/dir/file", "dir/link") + assert.NoError(t, err) + + oldname, err := fs.Readlink("dir/link") + assert.NoError(t, err) + assert.Equal(t, oldname, expectedSymlinkTarget) + }) +} + +func TestReadlinkWithNonExistentTarget(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := fs.Symlink("file", "link") + assert.NoError(t, err) + + oldname, err := fs.Readlink("link") + assert.NoError(t, err) + assert.Equal(t, oldname, "file") + }) +} + +func TestReadlinkWithNonExistentLink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + _, err := fs.Readlink("link") + assert.Equal(t, os.IsNotExist(err), true) + }) +} + +func TestStatLink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + util.WriteFile(fs, "foo/bar", []byte("foo"), customMode) + fs.Symlink("bar", "foo/qux") + + fi, err := fs.Stat("foo/qux") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "qux") + assert.Equal(t, fi.Size(), int64(3)) + assert.Equal(t, fi.Mode(), customMode) + assert.Equal(t, fi.ModTime().IsZero(), false) + assert.Equal(t, fi.IsDir(), false) + }) +} + +func TestLstat(t *testing.T) { + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + util.WriteFile(fs, "foo/bar", []byte("foo"), customMode) + + fi, err := fs.Lstat("foo/bar") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "bar") + assert.Equal(t, fi.Size(), int64(3)) + assert.Equal(t, fi.Mode()&os.ModeSymlink != 0, false) + assert.Equal(t, fi.ModTime().IsZero(), false) + assert.Equal(t, fi.IsDir(), false) + }) +} + +func TestLstatLink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + util.WriteFile(fs, "foo/bar", []byte("fosddddaaao"), customMode) + fs.Symlink("bar", "foo/qux") + + fi, err := fs.Lstat("foo/qux") + assert.NoError(t, err) + assert.Equal(t, fi.Name(), "qux") + assert.Equal(t, fi.Mode()&os.ModeSymlink != 0, true) + assert.Equal(t, fi.ModTime().IsZero(), false) + assert.Equal(t, fi.IsDir(), false) + }) +} + +func TestRenameWithSymlink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := fs.Symlink("file", "link") + assert.NoError(t, err) + + err = fs.Rename("link", "newlink") + assert.NoError(t, err) + + _, err = fs.Readlink("newlink") + assert.NoError(t, err) + }) +} + +func TestRemoveWithSymlink(t *testing.T) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on Plan 9; symlinks are not supported") + } + + eachSymlinkFS(t, func(t *testing.T, fs symlinkFS) { + err := util.WriteFile(fs, "file", []byte("foo"), 0644) + assert.NoError(t, err) + + err = fs.Symlink("file", "link") + assert.NoError(t, err) + + err = fs.Remove("link") + assert.NoError(t, err) + + _, err = fs.Readlink("link") + assert.Equal(t, os.IsNotExist(err), true) + + _, err = fs.Stat("link") + assert.Equal(t, os.IsNotExist(err), true) + + _, err = fs.Stat("file") + assert.NoError(t, err) + }) +} diff --git a/test/tempfile.go b/test/tempfile.go deleted file mode 100644 index 5a6d56d..0000000 --- a/test/tempfile.go +++ /dev/null @@ -1,94 +0,0 @@ -package test - -import ( - "strings" - - . "gopkg.in/check.v1" - "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/util" -) - -// TempFileSuite is a convenient test suite to validate any implementation of -// billy.TempFile -type TempFileSuite struct { - FS interface { - billy.Basic - billy.TempFile - } -} - -func (s *TempFileSuite) TestTempFile(c *C) { - f, err := s.FS.TempFile("", "bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - c.Assert(strings.Index(f.Name(), "bar"), Not(Equals), -1) -} - -func (s *TempFileSuite) TestTempFileWithPath(c *C) { - f, err := s.FS.TempFile("foo", "bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - c.Assert(strings.HasPrefix(f.Name(), s.FS.Join("foo", "bar")), Equals, true) -} - -func (s *TempFileSuite) TestTempFileFullWithPath(c *C) { - f, err := s.FS.TempFile("/foo", "bar") - c.Assert(err, IsNil) - c.Assert(f.Close(), IsNil) - - c.Assert(strings.Index(f.Name(), s.FS.Join("foo", "bar")), Not(Equals), -1) -} - -func (s *TempFileSuite) TestRemoveTempFile(c *C) { - f, err := s.FS.TempFile("test-dir", "test-prefix") - c.Assert(err, IsNil) - - fn := f.Name() - c.Assert(f.Close(), IsNil) - c.Assert(s.FS.Remove(fn), IsNil) -} - -func (s *TempFileSuite) TestRenameTempFile(c *C) { - f, err := s.FS.TempFile("test-dir", "test-prefix") - c.Assert(err, IsNil) - - fn := f.Name() - c.Assert(f.Close(), IsNil) - c.Assert(s.FS.Rename(fn, "other-path"), IsNil) -} - -func (s *TempFileSuite) TestTempFileMany(c *C) { - for i := 0; i < 1024; i++ { - var fs []billy.File - - for j := 0; j < 100; j++ { - f, err := s.FS.TempFile("test-dir", "test-prefix") - c.Assert(err, IsNil) - fs = append(fs, f) - } - - for _, f := range fs { - c.Assert(f.Close(), IsNil) - c.Assert(s.FS.Remove(f.Name()), IsNil) - } - } -} - -func (s *TempFileSuite) TestTempFileManyWithUtil(c *C) { - for i := 0; i < 1024; i++ { - var fs []billy.File - - for j := 0; j < 100; j++ { - f, err := util.TempFile(s.FS, "test-dir", "test-prefix") - c.Assert(err, IsNil) - fs = append(fs, f) - } - - for _, f := range fs { - c.Assert(f.Close(), IsNil) - c.Assert(s.FS.Remove(f.Name()), IsNil) - } - } -} diff --git a/test/tempfile_test.go b/test/tempfile_test.go new file mode 100644 index 0000000..bb3dcda --- /dev/null +++ b/test/tempfile_test.go @@ -0,0 +1,114 @@ +package test + +import ( + "fmt" + "strings" + "testing" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" +) + +type tempFS interface { + billy.Basic + billy.TempFile +} + +func eachTempFS(t *testing.T, test func(t *testing.T, fs tempFS)) { + for _, fs := range allFS(t.TempDir) { + t.Run(fmt.Sprintf("%T", fs), func(t *testing.T) { + test(t, fs) + }) + } +} + +func TestTempFile(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + f, err := fs.TempFile("", "bar") + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + assert.NotEqual(t, strings.Index(f.Name(), "bar"), -1) + }) +} + +func TestTempFileWithPath(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + f, err := fs.TempFile("foo", "bar") + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + assert.True(t, strings.HasPrefix(f.Name(), fs.Join("foo", "bar"))) + }) +} + +func TestTempFileFullWithPath(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + f, err := fs.TempFile("/foo", "bar") + assert.NoError(t, err) + assert.NoError(t, f.Close()) + + assert.NotEqual(t, strings.Index(f.Name(), fs.Join("foo", "bar")), -1) + }) +} + +func TestRemoveTempFile(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + f, err := fs.TempFile("test-dir", "test-prefix") + assert.NoError(t, err) + + fn := f.Name() + assert.NoError(t, f.Close()) + assert.NoError(t, fs.Remove(fn)) + }) +} + +func TestRenameTempFile(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + f, err := fs.TempFile("test-dir", "test-prefix") + assert.NoError(t, err) + + fn := f.Name() + assert.NoError(t, f.Close()) + assert.NoError(t, fs.Rename(fn, "other-path")) + }) +} + +func TestTempFileMany(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + for i := 0; i < 1024; i++ { + var files []billy.File + + for j := 0; j < 100; j++ { + f, err := fs.TempFile("test-dir", "test-prefix") + assert.NoError(t, err) + files = append(files, f) + } + + for _, f := range files { + assert.NoError(t, f.Close()) + assert.NoError(t, fs.Remove(f.Name())) + } + } + }) +} + +func TestTempFileManyWithUtil(t *testing.T) { + eachTempFS(t, func(t *testing.T, fs tempFS) { + for i := 0; i < 1024; i++ { + var files []billy.File + + for j := 0; j < 100; j++ { + f, err := util.TempFile(fs, "test-dir", "test-prefix") + assert.NoError(t, err) + files = append(files, f) + } + + for _, f := range files { + assert.NoError(t, f.Close()) + assert.NoError(t, fs.Remove(f.Name())) + } + } + }) +} diff --git a/util/glob_test.go b/util/glob_test.go index 2cd73ae..d6ed9e0 100644 --- a/util/glob_test.go +++ b/util/glob_test.go @@ -5,30 +5,26 @@ import ( "sort" "testing" - . "gopkg.in/check.v1" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-billy/v5/util" + "github.com/stretchr/testify/assert" ) -func Test(t *testing.T) { TestingT(t) } - -var _ = Suite(&UtilSuite{}) - -type UtilSuite struct{} - -func (s *UtilSuite) TestCreate(c *C) { +func TestCreate(t *testing.T) { fs := memfs.New() - util.WriteFile(fs, "foo/qux", nil, 0644) - util.WriteFile(fs, "foo/bar", nil, 0644) - util.WriteFile(fs, "foo/baz/foo", nil, 0644) + util.WriteFile(fs, "foo/qux", nil, 0o644) + util.WriteFile(fs, "foo/bar", nil, 0o644) + util.WriteFile(fs, "foo/baz/foo", nil, 0o644) names, err := util.Glob(fs, "*/b*") - c.Assert(err, IsNil) - c.Assert(names, HasLen, 2) + assert := assert.New(t) + assert.NoError(err) + assert.Len(names, 2) + sort.Strings(names) - c.Assert(names, DeepEquals, []string{ + + assert.Equal(names, []string{ filepath.Join("foo", "bar"), filepath.Join("foo", "baz"), }) - } diff --git a/util/walk_test.go b/util/walk_test.go index 7cd80d8..f8b9307 100644 --- a/util/walk_test.go +++ b/util/walk_test.go @@ -2,111 +2,115 @@ package util_test import ( "errors" - "fmt" "os" "path/filepath" - "reflect" "testing" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-billy/v5/util" - . "gopkg.in/check.v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -type WalkSuite struct{} - -func TestWalk(t *testing.T) { TestingT(t) } - -var _ = Suite(&WalkSuite{}) var targetSubfolder = filepath.FromSlash("path/to/some/subfolder") -func (s *WalkSuite) TestWalkCanSkipTopDirectory(c *C) { +func TestWalkCanSkipTopDirectory(t *testing.T) { filesystem := memfs.New() - c.Assert(util.Walk(filesystem, "/root/that/does/not/exist", func(path string, info os.FileInfo, err error) error { return filepath.SkipDir }), IsNil) + err := util.Walk(filesystem, "/root/that/does/not/exist", func(path string, info os.FileInfo, err error) error { return filepath.SkipDir }) + + assert.NoError(t, err) } -func (s *WalkSuite) TestWalkReturnsAnErrorWhenRootDoesNotExist(c *C) { +func TestWalkReturnsAnErrorWhenRootDoesNotExist(t *testing.T) { filesystem := memfs.New() - c.Assert(util.Walk(filesystem, "/root/that/does/not/exist", func(path string, info os.FileInfo, err error) error { return err }), NotNil) + err := util.Walk(filesystem, "/root/that/does/not/exist", func(path string, info os.FileInfo, err error) error { return err }) + + assert.Error(t, err) } -func (s *WalkSuite) TestWalkOnPlainFile(c *C) { +func TestWalkOnPlainFile(t *testing.T) { filesystem := memfs.New() - createFile(c, filesystem, "./README.md") + createFile(t, filesystem, "./README.md") discoveredPaths := []string{} - c.Assert(util.Walk(filesystem, "./README.md", func(path string, info os.FileInfo, err error) error { + + err := util.Walk(filesystem, "./README.md", func(path string, info os.FileInfo, err error) error { discoveredPaths = append(discoveredPaths, path) return nil - }), IsNil) - c.Assert(discoveredPaths, DeepEquals, []string{"./README.md"}) + }) + assert.NoError(t, err) + assert.Equal(t, []string{"./README.md"}, discoveredPaths) } -func (s *WalkSuite) TestWalkOnExistingFolder(c *C) { +func TestWalkOnExistingFolder(t *testing.T) { filesystem := memfs.New() - createFile(c, filesystem, "path/to/some/subfolder/that/contain/file") - createFile(c, filesystem, "path/to/some/file") + createFile(t, filesystem, "path/to/some/subfolder/that/contain/file") + createFile(t, filesystem, "path/to/some/file") discoveredPaths := []string{} - c.Assert(util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { + err := util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { discoveredPaths = append(discoveredPaths, path) return nil - }), IsNil) - c.Assert(discoveredPaths, Contains, "path") - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/file")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder/that")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder/that/contain")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) + }) + assert.NoError(t, err) + + assert.Contains(t, discoveredPaths, "path") + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/file")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) } -func (s *WalkSuite) TestWalkCanSkipFolder(c *C) { +func TestWalkCanSkipFolder(t *testing.T) { filesystem := memfs.New() - createFile(c, filesystem, "path/to/some/subfolder/that/contain/file") - createFile(c, filesystem, "path/to/some/file") + createFile(t, filesystem, "path/to/some/subfolder/that/contain/file") + createFile(t, filesystem, "path/to/some/file") discoveredPaths := []string{} - c.Assert(util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { + err := util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { discoveredPaths = append(discoveredPaths, path) if path == targetSubfolder { return filepath.SkipDir } return nil - }), IsNil) - c.Assert(discoveredPaths, Contains, "path") - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/file")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that/contain")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) + }) + assert.NoError(t, err) + assert.Contains(t, discoveredPaths, "path") + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/file")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) } -func (s *WalkSuite) TestWalkStopsOnError(c *C) { +func TestWalkStopsOnError(t *testing.T) { filesystem := memfs.New() - createFile(c, filesystem, "path/to/some/subfolder/that/contain/file") - createFile(c, filesystem, "path/to/some/file") + createFile(t, filesystem, "path/to/some/subfolder/that/contain/file") + createFile(t, filesystem, "path/to/some/file") discoveredPaths := []string{} - c.Assert(util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { + err := util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { discoveredPaths = append(discoveredPaths, path) if path == targetSubfolder { return errors.New("uncaught error") } return nil - }), NotNil) - c.Assert(discoveredPaths, Contains, "path") - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/file")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that/contain")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) + }) + assert.Error(t, err) + assert.Contains(t, discoveredPaths, "path") + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/file")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) } -func (s *WalkSuite) TestWalkForwardsStatErrors(c *C) { +func TestWalkForwardsStatErrors(t *testing.T) { memFilesystem := memfs.New() filesystem := &fnFs{ Filesystem: memFilesystem, @@ -118,32 +122,32 @@ func (s *WalkSuite) TestWalkForwardsStatErrors(c *C) { }, } - createFile(c, filesystem, "path/to/some/subfolder/that/contain/file") - createFile(c, filesystem, "path/to/some/file") + createFile(t, filesystem, "path/to/some/subfolder/that/contain/file") + createFile(t, filesystem, "path/to/some/file") discoveredPaths := []string{} - c.Assert(util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { + err := util.Walk(filesystem, "path", func(path string, info os.FileInfo, err error) error { discoveredPaths = append(discoveredPaths, path) if path == targetSubfolder { - c.Assert(err, NotNil) + assert.Error(t, err) } return err - }), NotNil) - c.Assert(discoveredPaths, Contains, "path") - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/file")) - c.Assert(discoveredPaths, Contains, filepath.FromSlash("path/to/some/subfolder")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that/contain")) - c.Assert(discoveredPaths, NotContain, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) + }) + assert.Error(t, err) + assert.Contains(t, discoveredPaths, "path") + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/file")) + assert.Contains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain")) + assert.NotContains(t, discoveredPaths, filepath.FromSlash("path/to/some/subfolder/that/contain/file")) } -func createFile(c *C, filesystem billy.Filesystem, path string) { +func createFile(t *testing.T, filesystem billy.Filesystem, path string) { fd, err := filesystem.Create(path) - c.Assert(err, IsNil) - if err != nil { - fd.Close() - } + + require.NoError(t, err) + fd.Close() } type fnFs struct { @@ -157,39 +161,3 @@ func (f *fnFs) Lstat(path string) (os.FileInfo, error) { } return nil, errors.New("not implemented") } - -type containsChecker struct { - *CheckerInfo -} - -func (checker *containsChecker) Check(params []interface{}, names []string) (result bool, err string) { - defer func() { - if v := recover(); v != nil { - result = false - err = fmt.Sprint(v) - } - }() - - value := reflect.ValueOf(params[0]) - result = false - err = fmt.Sprintf("%v does not contain %v", params[0], params[1]) - switch value.Kind() { - case reflect.Array, reflect.Slice: - for i := 0; i < value.Len(); i++ { - r := reflect.DeepEqual(value.Index(i).Interface(), params[1]) - if r { - result = true - err = "" - } - } - default: - return false, "obtained value type is not iterable" - } - return -} - -var Contains Checker = &containsChecker{ - &CheckerInfo{Name: "Contains", Params: []string{"obtained", "expected"}}, -} - -var NotContain Checker = Not(Contains)