github.com/ethanhsieh/snapd@v0.0.0-20210615102523-3db9b8e4edc5/snap/snaptest/snaptest_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 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 snaptest_test
    21  
    22  import (
    23  	"os"
    24  	"path/filepath"
    25  	"testing"
    26  
    27  	. "gopkg.in/check.v1"
    28  
    29  	"github.com/snapcore/snapd/dirs"
    30  	"github.com/snapcore/snapd/snap"
    31  	"github.com/snapcore/snapd/snap/snapfile"
    32  	"github.com/snapcore/snapd/snap/snaptest"
    33  	"github.com/snapcore/snapd/snap/squashfs"
    34  	"github.com/snapcore/snapd/testutil"
    35  )
    36  
    37  func TestSnapTest(t *testing.T) { TestingT(t) }
    38  
    39  const sampleYaml = `
    40  name: sample
    41  version: 1
    42  apps:
    43   app:
    44     command: foo
    45  plugs:
    46   network:
    47    interface: network
    48  `
    49  
    50  type snapTestSuite struct{}
    51  
    52  var _ = Suite(&snapTestSuite{})
    53  
    54  func (s *snapTestSuite) SetUpTest(c *C) {
    55  	dirs.SetRootDir(c.MkDir())
    56  }
    57  
    58  func (s *snapTestSuite) TearDownTest(c *C) {
    59  	dirs.SetRootDir("")
    60  }
    61  
    62  func (s *snapTestSuite) TestMockSnap(c *C) {
    63  	snapInfo := snaptest.MockSnap(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
    64  	// Data from YAML is used
    65  	c.Check(snapInfo.InstanceName(), Equals, "sample")
    66  	// Data from SideInfo is used
    67  	c.Check(snapInfo.Revision, Equals, snap.R(42))
    68  	// The YAML is placed on disk
    69  	c.Check(filepath.Join(dirs.SnapMountDir, "sample", "42", "meta", "snap.yaml"),
    70  		testutil.FileEquals, sampleYaml)
    71  
    72  	// More
    73  	c.Check(snapInfo.Apps["app"].Command, Equals, "foo")
    74  	c.Check(snapInfo.Plugs["network"].Interface, Equals, "network")
    75  }
    76  
    77  func (s *snapTestSuite) TestMockSnapInstance(c *C) {
    78  	snapInfo := snaptest.MockSnapInstance(c, "sample_instance", sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
    79  	// Data from YAML and parameters is used
    80  	c.Check(snapInfo.InstanceName(), Equals, "sample_instance")
    81  	c.Check(snapInfo.SnapName(), Equals, "sample")
    82  	c.Check(snapInfo.InstanceKey, Equals, "instance")
    83  
    84  	// Data from SideInfo is used
    85  	c.Check(snapInfo.Revision, Equals, snap.R(42))
    86  	// The YAML is placed on disk
    87  	c.Check(filepath.Join(dirs.SnapMountDir, "sample_instance", "42", "meta", "snap.yaml"),
    88  		testutil.FileEquals, sampleYaml)
    89  
    90  	// More
    91  	c.Check(snapInfo.Apps["app"].Command, Equals, "foo")
    92  	c.Check(snapInfo.Plugs["network"].Interface, Equals, "network")
    93  }
    94  
    95  func (s *snapTestSuite) TestMockSnapCurrent(c *C) {
    96  	snapInfo := snaptest.MockSnapCurrent(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
    97  	// Data from YAML is used
    98  	c.Check(snapInfo.InstanceName(), Equals, "sample")
    99  	// Data from SideInfo is used
   100  	c.Check(snapInfo.Revision, Equals, snap.R(42))
   101  	// The YAML is placed on disk
   102  	c.Check(filepath.Join(dirs.SnapMountDir, "sample", "42", "meta", "snap.yaml"),
   103  		testutil.FileEquals, sampleYaml)
   104  	link, err := os.Readlink(filepath.Join(dirs.SnapMountDir, "sample", "current"))
   105  	c.Check(err, IsNil)
   106  	c.Check(link, Equals, "42")
   107  }
   108  
   109  func (s *snapTestSuite) TestMockSnapInstanceCurrent(c *C) {
   110  	snapInfo := snaptest.MockSnapInstanceCurrent(c, "sample_instance", sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
   111  	// Data from YAML and parameters is used
   112  	c.Check(snapInfo.InstanceName(), Equals, "sample_instance")
   113  	c.Check(snapInfo.SnapName(), Equals, "sample")
   114  	c.Check(snapInfo.InstanceKey, Equals, "instance")
   115  	// Data from SideInfo is used
   116  	c.Check(snapInfo.Revision, Equals, snap.R(42))
   117  	// The YAML is placed on disk
   118  	c.Check(filepath.Join(dirs.SnapMountDir, "sample_instance", "42", "meta", "snap.yaml"),
   119  		testutil.FileEquals, sampleYaml)
   120  	link, err := os.Readlink(filepath.Join(dirs.SnapMountDir, "sample_instance", "current"))
   121  	c.Check(err, IsNil)
   122  	c.Check(link, Equals, filepath.Join(dirs.SnapMountDir, "sample_instance", "42"))
   123  }
   124  
   125  func (s *snapTestSuite) TestMockInfo(c *C) {
   126  	snapInfo := snaptest.MockInfo(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)})
   127  	// Data from YAML is used
   128  	c.Check(snapInfo.InstanceName(), Equals, "sample")
   129  	// Data from SideInfo is used
   130  	c.Check(snapInfo.Revision, Equals, snap.R(42))
   131  	// The YAML is *not* placed on disk
   132  	_, err := os.Stat(filepath.Join(dirs.SnapMountDir, "sample", "42", "meta", "snap.yaml"))
   133  	c.Assert(os.IsNotExist(err), Equals, true)
   134  	// More
   135  	c.Check(snapInfo.Apps["app"].Command, Equals, "foo")
   136  	c.Check(snapInfo.Plugs["network"].Interface, Equals, "network")
   137  }
   138  
   139  func (s *snapTestSuite) TestMockInvalidInfo(c *C) {
   140  	snapInfo := snaptest.MockInvalidInfo(c, sampleYaml+"\nslots:\n network:\n", &snap.SideInfo{Revision: snap.R(42)})
   141  	// Data from YAML is used
   142  	c.Check(snapInfo.InstanceName(), Equals, "sample")
   143  	// Data from SideInfo is used
   144  	c.Check(snapInfo.Revision, Equals, snap.R(42))
   145  	// The YAML is *not* placed on disk
   146  	_, err := os.Stat(filepath.Join(dirs.SnapMountDir, "sample", "42", "meta", "snap.yaml"))
   147  	c.Assert(os.IsNotExist(err), Equals, true)
   148  	// More
   149  	c.Check(snapInfo.Apps["app"].Command, Equals, "foo")
   150  	c.Check(snapInfo.Plugs["network"].Interface, Equals, "network")
   151  	c.Check(snapInfo.Slots["network"].Interface, Equals, "network")
   152  	// They info object is not valid
   153  	c.Check(snap.Validate(snapInfo), ErrorMatches, `cannot have plug and slot with the same name: "network"`)
   154  }
   155  
   156  func (s *snapTestSuite) TestRenameSlot(c *C) {
   157  	snapInfo := snaptest.MockInfo(c, `name: core
   158  type: os
   159  version: 0
   160  slots:
   161    old:
   162      interface: interface
   163    slot:
   164      interface: interface
   165  plugs:
   166    plug:
   167      interface: interface
   168  apps:
   169    app:
   170  hooks:
   171    configure:
   172  `, nil)
   173  
   174  	// Rename "old" to "plug"
   175  	err := snaptest.RenameSlot(snapInfo, "old", "plug")
   176  	c.Assert(err, ErrorMatches, `cannot rename slot "old" to "plug": existing plug with that name`)
   177  
   178  	// Rename "old" to "slot"
   179  	err = snaptest.RenameSlot(snapInfo, "old", "slot")
   180  	c.Assert(err, ErrorMatches, `cannot rename slot "old" to "slot": existing slot with that name`)
   181  
   182  	// Rename "old" to "bad name"
   183  	err = snaptest.RenameSlot(snapInfo, "old", "bad name")
   184  	c.Assert(err, ErrorMatches, `cannot rename slot "old" to "bad name": invalid slot name: "bad name"`)
   185  
   186  	// Rename "old" to "new"
   187  	err = snaptest.RenameSlot(snapInfo, "old", "new")
   188  	c.Assert(err, IsNil)
   189  
   190  	// Check that there's no trace of the old slot name.
   191  	c.Assert(snapInfo.Slots["old"], IsNil)
   192  	c.Assert(snapInfo.Slots["new"], NotNil)
   193  	c.Assert(snapInfo.Slots["new"].Name, Equals, "new")
   194  	c.Assert(snapInfo.Apps["app"].Slots["old"], IsNil)
   195  	c.Assert(snapInfo.Apps["app"].Slots["new"], DeepEquals, snapInfo.Slots["new"])
   196  	c.Assert(snapInfo.Hooks["configure"].Slots["old"], IsNil)
   197  	c.Assert(snapInfo.Hooks["configure"].Slots["new"], DeepEquals, snapInfo.Slots["new"])
   198  
   199  	// Rename "old" to "new" (again)
   200  	err = snaptest.RenameSlot(snapInfo, "old", "new")
   201  	c.Assert(err, ErrorMatches, `cannot rename slot "old" to "new": no such slot`)
   202  
   203  }
   204  
   205  func (s *snapTestSuite) TestMockSnapWithFiles(c *C) {
   206  	snapInfo := snaptest.MockSnapWithFiles(c, sampleYaml, &snap.SideInfo{Revision: snap.R(42)}, [][]string{
   207  		{"foo/bar", "bar"},
   208  		{"bar", "not foo"},
   209  		{"meta/gadget.yaml", "gadget yaml\nmulti line"},
   210  	})
   211  	// Data from YAML is used
   212  	c.Check(snapInfo.InstanceName(), Equals, "sample")
   213  	// Data from SideInfo is used
   214  	c.Check(snapInfo.Revision, Equals, snap.R(42))
   215  	c.Check(filepath.Join(snapInfo.MountDir(), "bar"), testutil.FileEquals, "not foo")
   216  	c.Check(filepath.Join(snapInfo.MountDir(), "foo/bar"), testutil.FileEquals, "bar")
   217  	c.Check(filepath.Join(snapInfo.MountDir(), "meta/gadget.yaml"), testutil.FileEquals, "gadget yaml\nmulti line")
   218  }
   219  
   220  func (s *snapTestSuite) TestMockContainerMinimal(c *C) {
   221  	cont := snaptest.MockContainer(c, nil)
   222  	err := snap.ValidateContainer(cont, &snap.Info{}, nil)
   223  	c.Check(err, IsNil)
   224  }
   225  
   226  func (s *snapTestSuite) TestMockContainer(c *C) {
   227  	defer snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})()
   228  
   229  	const snapYaml = `name: gadget
   230  type: gadget
   231  version: 1.0`
   232  	const gadgetYaml = `defaults:
   233  `
   234  	cont := snaptest.MockContainer(c, [][]string{
   235  		{"meta/snap.yaml", snapYaml},
   236  		{"meta/gadget.yaml", gadgetYaml},
   237  	})
   238  
   239  	info, err := snap.ReadInfoFromSnapFile(cont, nil)
   240  	c.Assert(err, IsNil)
   241  	c.Check(info.SnapName(), Equals, "gadget")
   242  	err = snap.ValidateContainer(cont, info, nil)
   243  	c.Assert(err, IsNil)
   244  	readGadgetYaml, err := cont.ReadFile("meta/gadget.yaml")
   245  	c.Assert(err, IsNil)
   246  	c.Check(readGadgetYaml, DeepEquals, []byte(gadgetYaml))
   247  }
   248  
   249  func (s *snapTestSuite) TestMakeSnapFileAndDir(c *C) {
   250  	files := [][]string{
   251  		{"canary", "canary"},
   252  		{"foo", "foo"},
   253  	}
   254  	info := snaptest.MakeSnapFileAndDir(c, sampleYaml, files, &snap.SideInfo{
   255  		Revision: snap.R(3),
   256  	})
   257  	c.Check(filepath.Join(info.MountDir(), "canary"), testutil.FileEquals, "canary")
   258  	c.Assert(info.MountFile(), testutil.FilePresent)
   259  	c.Check(squashfs.FileHasSquashfsHeader(info.MountFile()), Equals, true)
   260  	f, err := snapfile.Open(info.MountFile())
   261  	c.Assert(err, IsNil)
   262  	can, err := f.ReadFile("canary")
   263  	c.Assert(err, IsNil)
   264  	c.Check(can, DeepEquals, []byte("canary"))
   265  }