github.com/rigado/snapd@v2.42.5-go-mod+incompatible/snap/pack/pack_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014-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 pack_test 21 22 import ( 23 "fmt" 24 "io/ioutil" 25 "os" 26 "os/exec" 27 "path/filepath" 28 "regexp" 29 "strings" 30 "testing" 31 32 . "gopkg.in/check.v1" 33 34 "github.com/snapcore/snapd/dirs" 35 "github.com/snapcore/snapd/snap" 36 "github.com/snapcore/snapd/snap/pack" 37 "github.com/snapcore/snapd/snap/squashfs" 38 "github.com/snapcore/snapd/testutil" 39 ) 40 41 func Test(t *testing.T) { TestingT(t) } 42 43 type packSuite struct { 44 testutil.BaseTest 45 } 46 47 var _ = Suite(&packSuite{}) 48 49 func (s *packSuite) SetUpTest(c *C) { 50 s.BaseTest.SetUpTest(c) 51 s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 52 53 // chdir into a tempdir 54 pwd, err := os.Getwd() 55 c.Assert(err, IsNil) 56 s.AddCleanup(func() { os.Chdir(pwd) }) 57 err = os.Chdir(c.MkDir()) 58 c.Assert(err, IsNil) 59 60 // use fake root 61 dirs.SetRootDir(c.MkDir()) 62 } 63 64 func (s *packSuite) TearDownTest(c *C) { 65 s.BaseTest.TearDownTest(c) 66 } 67 68 func makeExampleSnapSourceDir(c *C, snapYamlContent string) string { 69 tempdir := c.MkDir() 70 c.Assert(os.Chmod(tempdir, 0755), IsNil) 71 72 // use meta/snap.yaml 73 metaDir := filepath.Join(tempdir, "meta") 74 err := os.Mkdir(metaDir, 0755) 75 c.Assert(err, IsNil) 76 err = ioutil.WriteFile(filepath.Join(metaDir, "snap.yaml"), []byte(snapYamlContent), 0644) 77 c.Assert(err, IsNil) 78 79 const helloBinContent = `#!/bin/sh 80 printf "hello world" 81 ` 82 83 // an example binary 84 binDir := filepath.Join(tempdir, "bin") 85 err = os.Mkdir(binDir, 0755) 86 c.Assert(err, IsNil) 87 err = ioutil.WriteFile(filepath.Join(binDir, "hello-world"), []byte(helloBinContent), 0755) 88 c.Assert(err, IsNil) 89 90 // unusual permissions for dir 91 tmpDir := filepath.Join(tempdir, "tmp") 92 err = os.Mkdir(tmpDir, 0755) 93 c.Assert(err, IsNil) 94 // avoid umask 95 err = os.Chmod(tmpDir, 01777) 96 c.Assert(err, IsNil) 97 98 // and file 99 someFile := filepath.Join(tempdir, "file-with-perm") 100 err = ioutil.WriteFile(someFile, []byte(""), 0666) 101 c.Assert(err, IsNil) 102 err = os.Chmod(someFile, 0666) 103 c.Assert(err, IsNil) 104 105 // an example symlink 106 err = os.Symlink("bin/hello-world", filepath.Join(tempdir, "symlink")) 107 c.Assert(err, IsNil) 108 109 return tempdir 110 } 111 112 func (s *packSuite) TestPackNoManifestFails(c *C) { 113 sourceDir := makeExampleSnapSourceDir(c, "{name: hello, version: 0}") 114 c.Assert(os.Remove(filepath.Join(sourceDir, "meta", "snap.yaml")), IsNil) 115 _, err := pack.Snap(sourceDir, "", "") 116 c.Assert(err, ErrorMatches, `.*/meta/snap\.yaml: no such file or directory`) 117 } 118 119 func (s *packSuite) TestPackMissingAppFails(c *C) { 120 sourceDir := makeExampleSnapSourceDir(c, `name: hello 121 version: 0 122 apps: 123 foo: 124 command: bin/hello-world 125 `) 126 c.Assert(os.Remove(filepath.Join(sourceDir, "bin", "hello-world")), IsNil) 127 _, err := pack.Snap(sourceDir, "", "") 128 c.Assert(err, Equals, snap.ErrMissingPaths) 129 } 130 131 func (s *packSuite) TestValidateMissingAppFailsWithErrMissingPaths(c *C) { 132 sourceDir := makeExampleSnapSourceDir(c, `name: hello 133 version: 0 134 apps: 135 foo: 136 command: bin/hello-world 137 `) 138 c.Assert(os.Remove(filepath.Join(sourceDir, "bin", "hello-world")), IsNil) 139 err := pack.CheckSkeleton(sourceDir) 140 c.Assert(err, Equals, snap.ErrMissingPaths) 141 } 142 143 func (s *packSuite) TestPackExcludesBackups(c *C) { 144 sourceDir := makeExampleSnapSourceDir(c, "{name: hello, version: 0}") 145 target := c.MkDir() 146 // add a backup file 147 c.Assert(ioutil.WriteFile(filepath.Join(sourceDir, "foo~"), []byte("hi"), 0755), IsNil) 148 snapfile, err := pack.Snap(sourceDir, c.MkDir(), "") 149 c.Assert(err, IsNil) 150 c.Assert(squashfs.New(snapfile).Unpack("*", target), IsNil) 151 152 cmd := exec.Command("diff", "-qr", sourceDir, target) 153 cmd.Env = append(cmd.Env, "LANG=C") 154 out, err := cmd.Output() 155 c.Check(err, NotNil) 156 c.Check(string(out), Matches, `(?m)Only in \S+: foo~`) 157 } 158 159 func (s *packSuite) TestPackExcludesTopLevelDEBIAN(c *C) { 160 sourceDir := makeExampleSnapSourceDir(c, "{name: hello, version: 0}") 161 target := c.MkDir() 162 // add a toplevel DEBIAN 163 c.Assert(os.MkdirAll(filepath.Join(sourceDir, "DEBIAN", "foo"), 0755), IsNil) 164 // and a non-toplevel DEBIAN 165 c.Assert(os.MkdirAll(filepath.Join(sourceDir, "bar", "DEBIAN", "baz"), 0755), IsNil) 166 snapfile, err := pack.Snap(sourceDir, c.MkDir(), "") 167 c.Assert(err, IsNil) 168 c.Assert(squashfs.New(snapfile).Unpack("*", target), IsNil) 169 cmd := exec.Command("diff", "-qr", sourceDir, target) 170 cmd.Env = append(cmd.Env, "LANG=C") 171 out, err := cmd.Output() 172 c.Check(err, NotNil) 173 c.Check(string(out), Matches, `(?m)Only in \S+: DEBIAN`) 174 // but *only one* DEBIAN is skipped 175 c.Check(strings.Count(string(out), "Only in"), Equals, 1) 176 } 177 178 func (s *packSuite) TestPackExcludesWholeDirs(c *C) { 179 sourceDir := makeExampleSnapSourceDir(c, "{name: hello, version: 0}") 180 target := c.MkDir() 181 // add a file inside a skipped dir 182 c.Assert(os.Mkdir(filepath.Join(sourceDir, ".bzr"), 0755), IsNil) 183 c.Assert(ioutil.WriteFile(filepath.Join(sourceDir, ".bzr", "foo"), []byte("hi"), 0755), IsNil) 184 snapfile, err := pack.Snap(sourceDir, c.MkDir(), "") 185 c.Assert(err, IsNil) 186 c.Assert(squashfs.New(snapfile).Unpack("*", target), IsNil) 187 out, _ := exec.Command("find", sourceDir).Output() 188 c.Check(string(out), Not(Equals), "") 189 cmd := exec.Command("diff", "-qr", sourceDir, target) 190 cmd.Env = append(cmd.Env, "LANG=C") 191 out, err = cmd.Output() 192 c.Check(err, NotNil) 193 c.Check(string(out), Matches, `(?m)Only in \S+: \.bzr`) 194 } 195 196 func (s *packSuite) TestDebArchitecture(c *C) { 197 c.Check(pack.DebArchitecture(&snap.Info{Architectures: []string{"foo"}}), Equals, "foo") 198 c.Check(pack.DebArchitecture(&snap.Info{Architectures: []string{"foo", "bar"}}), Equals, "multi") 199 c.Check(pack.DebArchitecture(&snap.Info{Architectures: nil}), Equals, "all") 200 } 201 202 func (s *packSuite) TestPackSimple(c *C) { 203 sourceDir := makeExampleSnapSourceDir(c, `name: hello 204 version: 1.0.1 205 architectures: ["i386", "amd64"] 206 integration: 207 app: 208 apparmor-profile: meta/hello.apparmor 209 `) 210 211 outputDir := filepath.Join(c.MkDir(), "output") 212 absSnapFile := filepath.Join(c.MkDir(), "foo.snap") 213 214 type T struct { 215 outputDir, filename, expected string 216 } 217 218 table := []T{ 219 // no output dir, no filename -> default in . 220 {"", "", "hello_1.0.1_multi.snap"}, 221 // no output dir, relative filename -> filename in . 222 {"", "foo.snap", "foo.snap"}, 223 // no putput dir, absolute filename -> absolute filename 224 {"", absSnapFile, absSnapFile}, 225 // output dir, no filename -> default in outputdir 226 {outputDir, "", filepath.Join(outputDir, "hello_1.0.1_multi.snap")}, 227 // output dir, relative filename -> filename in outputDir 228 {filepath.Join(outputDir, "inner"), "../foo.snap", filepath.Join(outputDir, "foo.snap")}, 229 // output dir, absolute filename -> absolute filename 230 {outputDir, absSnapFile, absSnapFile}, 231 } 232 233 for i, t := range table { 234 comm := Commentf("%d", i) 235 resultSnap, err := pack.Snap(sourceDir, t.outputDir, t.filename) 236 c.Assert(err, IsNil, comm) 237 238 // check that there is result 239 _, err = os.Stat(resultSnap) 240 c.Assert(err, IsNil, comm) 241 c.Assert(resultSnap, Equals, t.expected, comm) 242 243 // check that the content looks sane 244 output, err := exec.Command("unsquashfs", "-ll", resultSnap).CombinedOutput() 245 c.Assert(err, IsNil, comm) 246 for _, needle := range []string{ 247 "meta/snap.yaml", 248 "bin/hello-world", 249 "symlink -> bin/hello-world", 250 } { 251 expr := fmt.Sprintf(`(?ms).*%s.*`, regexp.QuoteMeta(needle)) 252 c.Assert(string(output), Matches, expr, comm) 253 } 254 } 255 256 }