github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/gadget/internal/mkfs_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package internal_test
    21  
    22  import (
    23  	"bytes"
    24  	"io"
    25  	"os"
    26  	"path/filepath"
    27  	"testing"
    28  
    29  	. "gopkg.in/check.v1"
    30  
    31  	"github.com/snapcore/snapd/gadget/internal"
    32  	"github.com/snapcore/snapd/testutil"
    33  )
    34  
    35  func TestRun(t *testing.T) { TestingT(t) }
    36  
    37  type mkfsSuite struct {
    38  	testutil.BaseTest
    39  }
    40  
    41  var _ = Suite(&mkfsSuite{})
    42  
    43  func (m *mkfsSuite) SetUpTest(c *C) {
    44  	m.BaseTest.SetUpTest(c)
    45  
    46  	// fakeroot, mkfs.ext4, mkfs.vfat and mcopy are commonly installed in
    47  	// the host system, set up some overrides so that we avoid calling the
    48  	// host tools
    49  	cmdFakeroot := testutil.MockCommand(c, "fakeroot", "echo 'override in test' ; exit 1")
    50  	m.AddCleanup(cmdFakeroot.Restore)
    51  
    52  	cmdMkfsExt4 := testutil.MockCommand(c, "mkfs.ext4", "echo 'override in test' ; exit 1")
    53  	m.AddCleanup(cmdMkfsExt4.Restore)
    54  
    55  	cmdMkfsVfat := testutil.MockCommand(c, "mkfs.vfat", "echo 'override in test'; exit 1")
    56  	m.AddCleanup(cmdMkfsVfat.Restore)
    57  
    58  	cmdMcopy := testutil.MockCommand(c, "mcopy", "echo 'override in test'; exit 1")
    59  	m.AddCleanup(cmdMcopy.Restore)
    60  }
    61  
    62  func (m *mkfsSuite) TestMkfsExt4Happy(c *C) {
    63  	cmd := testutil.MockCommand(c, "fakeroot", "")
    64  	defer cmd.Restore()
    65  
    66  	err := internal.MkfsWithContent("ext4", "foo.img", "my-label", "contents", 0, 0)
    67  	c.Assert(err, IsNil)
    68  	c.Check(cmd.Calls(), DeepEquals, [][]string{
    69  		{
    70  			"fakeroot",
    71  			"mkfs.ext4",
    72  			"-d", "contents",
    73  			"-L", "my-label",
    74  			"foo.img",
    75  		},
    76  	})
    77  
    78  	cmd.ForgetCalls()
    79  
    80  	// empty label
    81  	err = internal.MkfsWithContent("ext4", "foo.img", "", "contents", 0, 0)
    82  	c.Assert(err, IsNil)
    83  	c.Check(cmd.Calls(), DeepEquals, [][]string{
    84  		{
    85  			"fakeroot",
    86  			"mkfs.ext4",
    87  			"-d", "contents",
    88  			"foo.img",
    89  		},
    90  	})
    91  
    92  	cmd.ForgetCalls()
    93  
    94  	// no content
    95  	err = internal.Mkfs("ext4", "foo.img", "my-label", 0, 0)
    96  	c.Assert(err, IsNil)
    97  	c.Check(cmd.Calls(), DeepEquals, [][]string{
    98  		{
    99  			"fakeroot",
   100  			"mkfs.ext4",
   101  			"-L", "my-label",
   102  			"foo.img",
   103  		},
   104  	})
   105  
   106  }
   107  
   108  func (m *mkfsSuite) TestMkfsExt4WithSize(c *C) {
   109  	cmd := testutil.MockCommand(c, "fakeroot", "")
   110  	defer cmd.Restore()
   111  
   112  	err := internal.MkfsWithContent("ext4", "foo.img", "my-label", "contents", 250*1024*1024, 0)
   113  	c.Assert(err, IsNil)
   114  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   115  		{
   116  			"fakeroot",
   117  			"mkfs.ext4",
   118  			"-d", "contents",
   119  			"-L", "my-label",
   120  			"foo.img",
   121  		},
   122  	})
   123  
   124  	cmd.ForgetCalls()
   125  
   126  	// empty label
   127  	err = internal.MkfsWithContent("ext4", "foo.img", "", "contents", 32*1024*1024, 0)
   128  	c.Assert(err, IsNil)
   129  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   130  		{
   131  			"fakeroot",
   132  			"mkfs.ext4",
   133  			"-b", "1024",
   134  			"-d", "contents",
   135  			"foo.img",
   136  		},
   137  	})
   138  
   139  	cmd.ForgetCalls()
   140  
   141  	// with sector size of 512
   142  	err = internal.MkfsWithContent("ext4", "foo.img", "", "contents", 32*1024*1024, 512)
   143  	c.Assert(err, IsNil)
   144  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   145  		{
   146  			"fakeroot",
   147  			"mkfs.ext4",
   148  			"-b", "1024",
   149  			"-d", "contents",
   150  			"foo.img",
   151  		},
   152  	})
   153  
   154  	cmd.ForgetCalls()
   155  
   156  	// with sector size of 4096
   157  	err = internal.MkfsWithContent("ext4", "foo.img", "", "contents", 32*1024*1024, 4096)
   158  	c.Assert(err, IsNil)
   159  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   160  		{
   161  			"fakeroot",
   162  			"mkfs.ext4",
   163  			"-b", "4096",
   164  			"-d", "contents",
   165  			"foo.img",
   166  		},
   167  	})
   168  
   169  	cmd.ForgetCalls()
   170  
   171  }
   172  
   173  func (m *mkfsSuite) TestMkfsExt4Error(c *C) {
   174  	cmd := testutil.MockCommand(c, "fakeroot", "echo 'command failed'; exit 1")
   175  	defer cmd.Restore()
   176  
   177  	err := internal.MkfsWithContent("ext4", "foo.img", "my-label", "contents", 0, 0)
   178  	c.Assert(err, ErrorMatches, "command failed")
   179  }
   180  
   181  func (m *mkfsSuite) TestMkfsVfatHappySimple(c *C) {
   182  	// no contents, should not fail
   183  	d := c.MkDir()
   184  
   185  	cmd := testutil.MockCommand(c, "mkfs.vfat", "")
   186  	defer cmd.Restore()
   187  
   188  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 0, 0)
   189  	c.Assert(err, IsNil)
   190  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   191  		{
   192  			"mkfs.vfat",
   193  			"-S", "512",
   194  			"-s", "1",
   195  			"-F", "32",
   196  			"-n", "my-label",
   197  			"foo.img",
   198  		},
   199  	})
   200  
   201  	cmd.ForgetCalls()
   202  
   203  	// empty label
   204  	err = internal.MkfsWithContent("vfat", "foo.img", "", d, 0, 0)
   205  	c.Assert(err, IsNil)
   206  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   207  		{
   208  			"mkfs.vfat",
   209  			"-S", "512",
   210  			"-s", "1",
   211  			"-F", "32",
   212  			"foo.img",
   213  		},
   214  	})
   215  
   216  	cmd.ForgetCalls()
   217  
   218  	// no content
   219  	err = internal.Mkfs("vfat", "foo.img", "my-label", 0, 0)
   220  	c.Assert(err, IsNil)
   221  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   222  		{
   223  			"mkfs.vfat",
   224  			"-S", "512",
   225  			"-s", "1",
   226  			"-F", "32",
   227  			"-n", "my-label",
   228  			"foo.img",
   229  		},
   230  	})
   231  }
   232  
   233  func (m *mkfsSuite) TestMkfsVfatWithSize(c *C) {
   234  	d := c.MkDir()
   235  
   236  	cmd := testutil.MockCommand(c, "mkfs.vfat", "")
   237  	defer cmd.Restore()
   238  
   239  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 32*1024*1024, 0)
   240  	c.Assert(err, IsNil)
   241  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   242  		{
   243  			"mkfs.vfat",
   244  			"-S", "512",
   245  			"-s", "1",
   246  			"-F", "32",
   247  			"-n", "my-label",
   248  			"foo.img",
   249  		},
   250  	})
   251  
   252  	cmd.ForgetCalls()
   253  
   254  	// with sector size of 512
   255  	err = internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 32*1024*1024, 512)
   256  	c.Assert(err, IsNil)
   257  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   258  		{
   259  			"mkfs.vfat",
   260  			"-S", "512",
   261  			"-s", "1",
   262  			"-F", "32",
   263  			"-n", "my-label",
   264  			"foo.img",
   265  		},
   266  	})
   267  
   268  	cmd.ForgetCalls()
   269  
   270  	// with sector size of 4096
   271  	err = internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 32*1024*1024, 4096)
   272  	c.Assert(err, IsNil)
   273  	c.Check(cmd.Calls(), DeepEquals, [][]string{
   274  		{
   275  			"mkfs.vfat",
   276  			"-S", "4096",
   277  			"-s", "1",
   278  			"-F", "32",
   279  			"-n", "my-label",
   280  			"foo.img",
   281  		},
   282  	})
   283  
   284  }
   285  
   286  func (m *mkfsSuite) TestMkfsVfatHappyContents(c *C) {
   287  	d := c.MkDir()
   288  	makeSizedFile(c, filepath.Join(d, "foo"), 128, []byte("foo foo foo"))
   289  	makeSizedFile(c, filepath.Join(d, "bar/bar-content"), 128, []byte("bar bar bar"))
   290  
   291  	cmdMkfs := testutil.MockCommand(c, "mkfs.vfat", "")
   292  	defer cmdMkfs.Restore()
   293  
   294  	cmdMcopy := testutil.MockCommand(c, "mcopy", "")
   295  	defer cmdMcopy.Restore()
   296  
   297  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 0, 0)
   298  	c.Assert(err, IsNil)
   299  	c.Assert(cmdMkfs.Calls(), HasLen, 1)
   300  
   301  	c.Assert(cmdMcopy.Calls(), DeepEquals, [][]string{
   302  		{"mcopy", "-s", "-i", "foo.img", filepath.Join(d, "bar"), filepath.Join(d, "foo"), "::"},
   303  	})
   304  }
   305  
   306  func (m *mkfsSuite) TestMkfsVfatErrorSimpleFail(c *C) {
   307  	d := c.MkDir()
   308  
   309  	cmd := testutil.MockCommand(c, "mkfs.vfat", "echo 'failed'; false")
   310  	defer cmd.Restore()
   311  
   312  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 0, 0)
   313  	c.Assert(err, ErrorMatches, "failed")
   314  }
   315  
   316  func (m *mkfsSuite) TestMkfsVfatErrorUnreadableDir(c *C) {
   317  	cmd := testutil.MockCommand(c, "mkfs.vfat", "")
   318  	defer cmd.Restore()
   319  
   320  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", "dir-does-not-exist", 0, 0)
   321  	c.Assert(err, ErrorMatches, "cannot list directory contents: .* no such file or directory")
   322  	c.Assert(cmd.Calls(), HasLen, 1)
   323  }
   324  
   325  func (m *mkfsSuite) TestMkfsVfatErrorInMcopy(c *C) {
   326  	d := c.MkDir()
   327  	makeSizedFile(c, filepath.Join(d, "foo"), 128, []byte("foo foo foo"))
   328  
   329  	cmdMkfs := testutil.MockCommand(c, "mkfs.vfat", "")
   330  	defer cmdMkfs.Restore()
   331  
   332  	cmdMcopy := testutil.MockCommand(c, "mcopy", "echo 'hard fail'; exit 1")
   333  	defer cmdMcopy.Restore()
   334  
   335  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", d, 0, 0)
   336  	c.Assert(err, ErrorMatches, "cannot populate vfat filesystem with contents: hard fail")
   337  	c.Assert(cmdMkfs.Calls(), HasLen, 1)
   338  	c.Assert(cmdMcopy.Calls(), HasLen, 1)
   339  }
   340  
   341  func (m *mkfsSuite) TestMkfsVfatHappyNoContents(c *C) {
   342  	cmdMkfs := testutil.MockCommand(c, "mkfs.vfat", "")
   343  	defer cmdMkfs.Restore()
   344  
   345  	cmdMcopy := testutil.MockCommand(c, "mcopy", "")
   346  	defer cmdMcopy.Restore()
   347  
   348  	err := internal.MkfsWithContent("vfat", "foo.img", "my-label", "", 0, 0)
   349  	c.Assert(err, IsNil)
   350  	c.Assert(cmdMkfs.Calls(), HasLen, 1)
   351  	// mcopy was not called
   352  	c.Assert(cmdMcopy.Calls(), HasLen, 0)
   353  }
   354  
   355  func (m *mkfsSuite) TestMkfsInvalidFs(c *C) {
   356  	err := internal.MkfsWithContent("no-fs", "foo.img", "my-label", "", 0, 0)
   357  	c.Assert(err, ErrorMatches, `cannot create unsupported filesystem "no-fs"`)
   358  
   359  	err = internal.Mkfs("no-fs", "foo.img", "my-label", 0, 0)
   360  	c.Assert(err, ErrorMatches, `cannot create unsupported filesystem "no-fs"`)
   361  }
   362  
   363  func makeSizedFile(c *C, path string, size int64, content []byte) {
   364  	err := os.MkdirAll(filepath.Dir(path), 0755)
   365  	c.Assert(err, IsNil)
   366  
   367  	f, err := os.Create(path)
   368  	c.Assert(err, IsNil)
   369  	defer f.Close()
   370  	if size != 0 {
   371  		err = f.Truncate(size)
   372  		c.Assert(err, IsNil)
   373  	}
   374  	if content != nil {
   375  		_, err := io.Copy(f, bytes.NewReader(content))
   376  		c.Assert(err, IsNil)
   377  	}
   378  }