github.com/stolowski/snapd@v0.0.0-20210407085831-115137ce5a22/dirs/dirs_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 dirs_test 21 22 import ( 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "testing" 27 28 . "gopkg.in/check.v1" 29 30 "github.com/snapcore/snapd/dirs" 31 "github.com/snapcore/snapd/release" 32 ) 33 34 // Hook up check.v1 into the "go test" runner 35 func Test(t *testing.T) { TestingT(t) } 36 37 var _ = Suite(&DirsTestSuite{}) 38 39 type DirsTestSuite struct{} 40 41 func (s *DirsTestSuite) TestStripRootDir(c *C) { 42 dirs.SetRootDir("/") 43 // strip does nothing if the default (empty) root directory is used 44 c.Check(dirs.StripRootDir("/foo/bar"), Equals, "/foo/bar") 45 // strip only works on absolute paths 46 c.Check(func() { dirs.StripRootDir("relative") }, Panics, `supplied path is not absolute "relative"`) 47 // with an alternate root 48 dirs.SetRootDir("/alt/") 49 defer dirs.SetRootDir("") 50 // strip behaves as expected, returning absolute paths without the prefix 51 c.Check(dirs.StripRootDir("/alt/foo/bar"), Equals, "/foo/bar") 52 // strip only works on paths that begin with the global root directory 53 c.Check(func() { dirs.StripRootDir("/other/foo/bar") }, Panics, `supplied path is not related to global root "/other/foo/bar"`) 54 } 55 56 func (s *DirsTestSuite) TestClassicConfinementSupport(c *C) { 57 // Ensure that we have a distribution as base which supports classic confinement 58 reset := release.MockReleaseInfo(&release.OS{ID: "ubuntu"}) 59 defer reset() 60 dirs.SetRootDir("/") 61 c.Check(dirs.SupportsClassicConfinement(), Equals, true) 62 63 dirs.SnapMountDir = "/alt" 64 defer dirs.SetRootDir("/") 65 c.Check(dirs.SupportsClassicConfinement(), Equals, false) 66 } 67 68 func (s *DirsTestSuite) TestClassicConfinementSymlinkWorkaround(c *C) { 69 restore := release.MockReleaseInfo(&release.OS{ID: "fedora"}) 70 defer restore() 71 72 altRoot := c.MkDir() 73 dirs.SetRootDir(altRoot) 74 defer dirs.SetRootDir("/") 75 c.Check(dirs.SupportsClassicConfinement(), Equals, false) 76 d := filepath.Join(altRoot, "/var/lib/snapd/snap") 77 os.MkdirAll(d, 0755) 78 os.Symlink(d, filepath.Join(altRoot, "snap")) 79 c.Check(dirs.SupportsClassicConfinement(), Equals, true) 80 } 81 82 func (s *DirsTestSuite) TestClassicConfinementSupportOnSpecificDistributions(c *C) { 83 // the test changes RootDir, restore correct one when retuning 84 defer dirs.SetRootDir("/") 85 86 for _, t := range []struct { 87 ID string 88 IDLike []string 89 Expected bool 90 }{ 91 {"fedora", nil, false}, 92 {"rhel", []string{"fedora"}, false}, 93 {"centos", []string{"fedora"}, false}, 94 {"ubuntu", []string{"debian"}, true}, 95 {"debian", nil, true}, 96 {"suse", nil, true}, 97 {"yocto", nil, true}, 98 {"arch", []string{"archlinux"}, false}, 99 {"archlinux", nil, false}, 100 } { 101 reset := release.MockReleaseInfo(&release.OS{ID: t.ID, IDLike: t.IDLike}) 102 defer reset() 103 104 // make a new root directory each time to isolate the test from 105 // local filesystem state and any previous test runs 106 dirs.SetRootDir(c.MkDir()) 107 c.Check(dirs.SupportsClassicConfinement(), Equals, t.Expected, Commentf("unexpected result for %v", t.ID)) 108 } 109 } 110 111 func (s *DirsTestSuite) TestInsideBaseSnap(c *C) { 112 d := c.MkDir() 113 114 snapYaml := filepath.Join(d, "snap.yaml") 115 restore := dirs.MockMetaSnapPath(snapYaml) 116 defer restore() 117 118 inside, err := dirs.IsInsideBaseSnap() 119 c.Assert(err, IsNil) 120 c.Assert(inside, Equals, false) 121 122 err = ioutil.WriteFile(snapYaml, []byte{}, 0755) 123 c.Assert(err, IsNil) 124 125 inside, err = dirs.IsInsideBaseSnap() 126 c.Assert(err, IsNil) 127 c.Assert(inside, Equals, true) 128 } 129 130 func (s *DirsTestSuite) TestCompleteShPath(c *C) { 131 dirs.SetRootDir(c.MkDir()) 132 defer dirs.SetRootDir("") 133 134 // old-style in-core complete.sh 135 c.Check(dirs.CompleteShPath(""), Equals, filepath.Join(dirs.SnapMountDir, "core/current/usr/lib/snapd/complete.sh")) 136 // new-style in-host complete.sh 137 c.Check(dirs.CompleteShPath("x"), Equals, filepath.Join(dirs.DistroLibExecDir, "complete.sh")) 138 // new-style in-snapd complete.sh 139 c.Check(os.MkdirAll(filepath.Join(dirs.SnapMountDir, "snapd/current/usr/lib/snapd"), 0755), IsNil) 140 c.Check(dirs.CompleteShPath("x"), Equals, filepath.Join(dirs.SnapMountDir, "snapd/current/usr/lib/snapd/complete.sh")) 141 } 142 143 func (s *DirsTestSuite) TestIsCompleteShSymlink(c *C) { 144 dirs.SetRootDir(c.MkDir()) 145 defer dirs.SetRootDir("") 146 147 tests := map[string]string{ 148 filepath.Join(dirs.GlobalRootDir, "no-base"): filepath.Join(dirs.SnapMountDir, "core/current/usr/lib/snapd/complete.sh"), 149 filepath.Join(dirs.GlobalRootDir, "no-snapd"): filepath.Join(dirs.DistroLibExecDir, "complete.sh"), 150 filepath.Join(dirs.GlobalRootDir, "base-and-snapd"): filepath.Join(dirs.SnapMountDir, "snapd/current/usr/lib/snapd/complete.sh"), 151 } 152 for target, d := range tests { 153 c.Check(os.Symlink(d, target), IsNil) 154 c.Check(dirs.IsCompleteShSymlink(target), Equals, true) 155 } 156 c.Check(dirs.IsCompleteShSymlink("/etc/passwd"), Equals, false) 157 c.Check(dirs.IsCompleteShSymlink("/does-not-exist"), Equals, false) 158 } 159 160 func (s *DirsTestSuite) TestUnder(c *C) { 161 dirs.SetRootDir("/nowhere") 162 defer dirs.SetRootDir("") 163 164 rootdir := "/other-root" 165 166 c.Check(dirs.SnapBlobDirUnder(rootdir), Equals, "/other-root/var/lib/snapd/snaps") 167 c.Check(dirs.SnapSeedDirUnder(rootdir), Equals, "/other-root/var/lib/snapd/seed") 168 } 169 170 func (s *DirsTestSuite) TestAddRootDirCallback(c *C) { 171 dirs.SetRootDir("/") 172 173 someVar := filepath.Join(dirs.GlobalRootDir, "my", "path") 174 // also test that derived vars work to be updated this way as well 175 someDerivedVar := filepath.Join(dirs.SnapDataDir, "other", "mnt") 176 177 // register a callback 178 dirs.AddRootDirCallback(func(rootdir string) { 179 someVar = filepath.Join(rootdir, "my", "path") 180 // the var derived from rootdir was also updated before the callback is 181 // run for simplicity 182 someDerivedVar = filepath.Join(dirs.SnapDataDir, "other", "mnt") 183 }) 184 185 // change root dir 186 dirs.SetRootDir("/hello") 187 188 // ensure our local vars were updated 189 c.Assert(someVar, Equals, filepath.Join("/hello", "my", "path")) 190 c.Assert(someDerivedVar, Equals, filepath.Join("/hello", "var", "snap", "other", "mnt")) 191 } 192 193 func (s *DirsTestSuite) TestLibexecdirOpenSUSETW(c *C) { 194 restore := release.MockReleaseInfo(&release.OS{ID: "opensuse-tumbleweed", VersionID: "20200820"}) 195 defer restore() 196 dirs.SetRootDir("/") 197 c.Check(dirs.DistroLibExecDir, Equals, "/usr/lib/snapd") 198 199 restore = release.MockReleaseInfo(&release.OS{ID: "opensuse-tumbleweed", VersionID: "20200826"}) 200 defer restore() 201 dirs.SetRootDir("/") 202 c.Check(dirs.DistroLibExecDir, Equals, "/usr/libexec/snapd") 203 204 restore = release.MockReleaseInfo(&release.OS{ID: "opensuse-tumbleweed", VersionID: "20200901"}) 205 defer restore() 206 dirs.SetRootDir("/") 207 c.Check(dirs.DistroLibExecDir, Equals, "/usr/libexec/snapd") 208 }