github.com/hugh712/snapd@v0.0.0-20200910133618-1a99902bd583/gadget/validate_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 gadget_test
    21  
    22  import (
    23  	"fmt"
    24  	"os"
    25  	"path/filepath"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"github.com/snapcore/snapd/gadget"
    30  )
    31  
    32  type validateGadgetTestSuite struct {
    33  	dir string
    34  }
    35  
    36  var _ = Suite(&validateGadgetTestSuite{})
    37  
    38  func (s *validateGadgetTestSuite) SetUpTest(c *C) {
    39  	s.dir = c.MkDir()
    40  }
    41  
    42  func (s *validateGadgetTestSuite) TestValidateMissingRawContent(c *C) {
    43  	var gadgetYamlContent = `
    44  volumes:
    45    pc:
    46      bootloader: grub
    47      structure:
    48        - name: foo
    49          type: DA,21686148-6449-6E6F-744E-656564454649
    50          size: 1M
    51          offset: 1M
    52          content:
    53            - image: foo.img
    54  
    55  `
    56  	makeSizedFile(c, filepath.Join(s.dir, "meta/gadget.yaml"), 0, []byte(gadgetYamlContent))
    57  
    58  	err := gadget.Validate(s.dir, nil)
    59  	c.Assert(err, ErrorMatches, `invalid layout of volume "pc": cannot lay out structure #0 \("foo"\): content "foo.img": stat .*/foo.img: no such file or directory`)
    60  }
    61  
    62  func (s *validateGadgetTestSuite) TestValidateMultiVolumeContent(c *C) {
    63  	var gadgetYamlContent = `
    64  volumes:
    65    first:
    66      bootloader: grub
    67      structure:
    68        - name: first-foo
    69          type: DA,21686148-6449-6E6F-744E-656564454649
    70          size: 1M
    71          content:
    72            - image: first.img
    73    second:
    74      structure:
    75        - name: second-foo
    76          type: DA,21686148-6449-6E6F-744E-656564454649
    77          size: 1M
    78          content:
    79            - image: second.img
    80  
    81  `
    82  	makeSizedFile(c, filepath.Join(s.dir, "meta/gadget.yaml"), 0, []byte(gadgetYamlContent))
    83  	// only content for the first volume
    84  	makeSizedFile(c, filepath.Join(s.dir, "first.img"), 1, nil)
    85  
    86  	err := gadget.Validate(s.dir, nil)
    87  	c.Assert(err, ErrorMatches, `invalid layout of volume "second": cannot lay out structure #0 \("second-foo"\): content "second.img": stat .*/second.img: no such file or directory`)
    88  }
    89  
    90  func (s *validateGadgetTestSuite) TestValidateBorkedMeta(c *C) {
    91  	var gadgetYamlContent = `
    92  volumes:
    93    borked:
    94      bootloader: bleh
    95      structure:
    96        - name: first-foo
    97          type: DA,21686148-6449-6E6F-744E-656564454649
    98          size: 1M
    99  
   100  `
   101  	makeSizedFile(c, filepath.Join(s.dir, "meta/gadget.yaml"), 0, []byte(gadgetYamlContent))
   102  
   103  	err := gadget.Validate(s.dir, nil)
   104  	c.Assert(err, ErrorMatches, `invalid gadget metadata: bootloader must be one of .*`)
   105  }
   106  
   107  func (s *validateGadgetTestSuite) TestValidateFilesystemContent(c *C) {
   108  	var gadgetYamlContent = `
   109  volumes:
   110    bad:
   111      bootloader: grub
   112      structure:
   113        - name: bad-struct
   114          type: DA,21686148-6449-6E6F-744E-656564454649
   115          size: 1M
   116          filesystem: ext4
   117          content:
   118            - source: foo/
   119              target: /
   120  
   121  `
   122  	makeSizedFile(c, filepath.Join(s.dir, "meta/gadget.yaml"), 0, []byte(gadgetYamlContent))
   123  
   124  	err := gadget.Validate(s.dir, nil)
   125  	c.Assert(err, ErrorMatches, `invalid volume "bad": structure #0 \("bad-struct"\), content source:foo/: source path does not exist`)
   126  
   127  	// make it a file, which conflicts with foo/ as 'source'
   128  	fooPath := filepath.Join(s.dir, "foo")
   129  	makeSizedFile(c, fooPath, 1, nil)
   130  	err = gadget.Validate(s.dir, nil)
   131  	c.Assert(err, ErrorMatches, `invalid volume "bad": structure #0 \("bad-struct"\), content source:foo/: cannot specify trailing / for a source which is not a directory`)
   132  
   133  	// make it a directory
   134  	err = os.Remove(fooPath)
   135  	c.Assert(err, IsNil)
   136  	err = os.Mkdir(fooPath, 0755)
   137  	c.Assert(err, IsNil)
   138  	// validate should no longer complain
   139  	err = gadget.Validate(s.dir, nil)
   140  	c.Assert(err, IsNil)
   141  }
   142  
   143  func (s *validateGadgetTestSuite) TestValidateClassic(c *C) {
   144  	var gadgetYamlContent = `
   145  # on classic this can be empty
   146  `
   147  	makeSizedFile(c, filepath.Join(s.dir, "meta/gadget.yaml"), 0, []byte(gadgetYamlContent))
   148  
   149  	err := gadget.Validate(s.dir, nil)
   150  	c.Assert(err, IsNil)
   151  
   152  	err = gadget.Validate(s.dir, &modelConstraints{classic: true})
   153  	c.Assert(err, IsNil)
   154  
   155  	err = gadget.Validate(s.dir, &modelConstraints{classic: false})
   156  	c.Assert(err, ErrorMatches, "invalid gadget metadata: bootloader not declared in any volume")
   157  }
   158  
   159  func (s *validateGadgetTestSuite) TestValidateSystemSeedRoleTwice(c *C) {
   160  
   161  	for _, role := range []string{"system-seed", "system-data", "system-boot"} {
   162  		gadgetYamlContent := fmt.Sprintf(`
   163  volumes:
   164    pc:
   165      bootloader: grub
   166      structure:
   167        - name: foo
   168          type: DA,21686148-6449-6E6F-744E-656564454649
   169          size: 1M
   170          role: %[1]s
   171        - name: bar
   172          type: DA,21686148-6449-6E6F-744E-656564454649
   173          size: 1M
   174          role: %[1]s
   175  `, role)
   176  		makeSizedFile(c, filepath.Join(s.dir, "meta/gadget.yaml"), 0, []byte(gadgetYamlContent))
   177  		err := gadget.Validate(s.dir, nil)
   178  		c.Assert(err, ErrorMatches, fmt.Sprintf(`invalid gadget metadata: invalid volume "pc": cannot have more than one partition with %s role`, role))
   179  	}
   180  }