github.com/ethanhsieh/snapd@v0.0.0-20210615102523-3db9b8e4edc5/usersession/autostart/autostart_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2018 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 autostart_test 21 22 import ( 23 "io/ioutil" 24 "os" 25 "os/user" 26 "path" 27 "path/filepath" 28 "strings" 29 "testing" 30 31 . "gopkg.in/check.v1" 32 33 "github.com/snapcore/snapd/dirs" 34 "github.com/snapcore/snapd/snap" 35 "github.com/snapcore/snapd/snap/snaptest" 36 "github.com/snapcore/snapd/testutil" 37 "github.com/snapcore/snapd/usersession/autostart" 38 ) 39 40 func Test(t *testing.T) { TestingT(t) } 41 42 type autostartSuite struct { 43 dir string 44 autostartDir string 45 userDir string 46 userCurrentRestore func() 47 } 48 49 var _ = Suite(&autostartSuite{}) 50 51 func (s *autostartSuite) SetUpTest(c *C) { 52 s.dir = c.MkDir() 53 dirs.SetRootDir(s.dir) 54 snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {}) 55 56 s.userDir = path.Join(s.dir, "home") 57 s.autostartDir = path.Join(s.userDir, ".config", "autostart") 58 s.userCurrentRestore = autostart.MockUserCurrent(func() (*user.User, error) { 59 return &user.User{HomeDir: s.userDir}, nil 60 }) 61 62 err := os.MkdirAll(s.autostartDir, 0755) 63 c.Assert(err, IsNil) 64 } 65 66 func (s *autostartSuite) TearDownTest(c *C) { 67 s.dir = c.MkDir() 68 dirs.SetRootDir("/") 69 if s.userCurrentRestore != nil { 70 s.userCurrentRestore() 71 } 72 } 73 74 func (s *autostartSuite) TestLoadAutostartDesktopFile(c *C) { 75 allGood := `[Desktop Entry] 76 Exec=foo --bar 77 ` 78 allGoodWithFlags := `[Desktop Entry] 79 Exec=foo --bar "%%p" %U %D +%s %% 80 ` 81 noExec := `[Desktop Entry] 82 Type=Application 83 ` 84 emptyExec := `[Desktop Entry] 85 Exec= 86 ` 87 onlySpacesExec := `[Desktop Entry] 88 Exec= 89 ` 90 hidden := `[Desktop Entry] 91 Exec=foo --bar 92 Hidden=true 93 ` 94 hiddenFalse := `[Desktop Entry] 95 Exec=foo --bar 96 Hidden=false 97 ` 98 justGNOME := `[Desktop Entry] 99 Exec=foo --bar 100 OnlyShowIn=GNOME; 101 ` 102 notInGNOME := `[Desktop Entry] 103 Exec=foo --bar 104 NotShownIn=GNOME; 105 ` 106 notInGNOMEAndKDE := `[Desktop Entry] 107 Exec=foo --bar 108 NotShownIn=GNOME;KDE; 109 ` 110 hiddenGNOMEextension := `[Desktop Entry] 111 Exec=foo --bar 112 X-GNOME-Autostart-enabled=false 113 ` 114 GNOMEextension := `[Desktop Entry] 115 Exec=foo --bar 116 X-GNOME-Autostart-enabled=true 117 ` 118 119 for i, tc := range []struct { 120 in string 121 out string 122 err string 123 current string 124 }{{ 125 in: allGood, 126 out: "foo --bar", 127 }, { 128 in: noExec, 129 err: "Exec not found or invalid", 130 }, { 131 in: emptyExec, 132 err: "Exec not found or invalid", 133 }, { 134 in: onlySpacesExec, 135 err: "Exec not found or invalid", 136 }, { 137 in: allGoodWithFlags, 138 out: `foo --bar "%p" + %`, 139 }, { 140 in: hidden, 141 err: `desktop file is hidden`, 142 }, { 143 in: hiddenFalse, 144 out: `foo --bar`, 145 }, { 146 in: justGNOME, 147 out: "foo --bar", 148 current: "GNOME", 149 }, { 150 in: justGNOME, 151 current: "KDE", 152 err: `current desktop \["KDE"\] not included in \["GNOME"\]`, 153 }, { 154 in: notInGNOME, 155 current: "GNOME", 156 err: `current desktop \["GNOME"\] excluded by \["GNOME"\]`, 157 }, { 158 in: notInGNOME, 159 current: "KDE", 160 out: "foo --bar", 161 }, { 162 in: notInGNOMEAndKDE, 163 current: "XFCE", 164 out: "foo --bar", 165 }, { 166 in: hiddenGNOMEextension, 167 current: "KDE", 168 out: "foo --bar", 169 }, { 170 in: hiddenGNOMEextension, 171 current: "GNOME", 172 err: `desktop file is hidden by X-GNOME-Autostart-enabled extension`, 173 }, { 174 in: GNOMEextension, 175 current: "GNOME", 176 out: "foo --bar", 177 }, { 178 in: GNOMEextension, 179 current: "KDE", 180 out: "foo --bar", 181 }} { 182 c.Logf("tc %d", i) 183 184 path := filepath.Join(c.MkDir(), "foo.desktop") 185 err := ioutil.WriteFile(path, []byte(tc.in), 0644) 186 c.Assert(err, IsNil) 187 188 run := func() { 189 defer autostart.MockCurrentDesktop(tc.current)() 190 191 cmd, err := autostart.LoadAutostartDesktopFile(path) 192 if tc.err != "" { 193 c.Check(cmd, Equals, "") 194 c.Check(err, ErrorMatches, tc.err) 195 } else { 196 c.Check(err, IsNil) 197 c.Check(cmd, Equals, tc.out) 198 } 199 } 200 run() 201 } 202 } 203 204 var mockYaml = `name: snapname 205 version: 1.0 206 apps: 207 foo: 208 command: run-app 209 autostart: foo-stable.desktop 210 ` 211 212 func (s *autostartSuite) TestTryAutostartAppValid(c *C) { 213 si := snaptest.MockSnapCurrent(c, mockYaml, &snap.SideInfo{Revision: snap.R("x2")}) 214 215 appWrapperPath := si.Apps["foo"].WrapperPath() 216 217 appCmd := testutil.MockCommand(c, appWrapperPath, "") 218 defer appCmd.Restore() 219 220 fooDesktopFile := filepath.Join(s.autostartDir, "foo-stable.desktop") 221 writeFile(c, fooDesktopFile, 222 []byte(`[Desktop Entry] 223 Exec=this-is-ignored -a -b --foo="a b c" -z "dev" 224 `)) 225 226 cmd, err := autostart.AutostartCmd("snapname", fooDesktopFile) 227 c.Assert(err, IsNil) 228 c.Assert(cmd.Path, Equals, appWrapperPath) 229 230 err = cmd.Start() 231 c.Assert(err, IsNil) 232 cmd.Wait() 233 234 c.Assert(appCmd.Calls(), DeepEquals, 235 [][]string{ 236 { 237 filepath.Base(appWrapperPath), 238 "-a", 239 "-b", 240 "--foo=a b c", 241 "-z", 242 "dev", 243 }, 244 }) 245 } 246 247 func (s *autostartSuite) TestTryAutostartAppNoMatchingApp(c *C) { 248 snaptest.MockSnapCurrent(c, mockYaml, &snap.SideInfo{Revision: snap.R("x2")}) 249 250 fooDesktopFile := filepath.Join(s.autostartDir, "foo-no-match.desktop") 251 writeFile(c, fooDesktopFile, 252 []byte(`[Desktop Entry] 253 Exec=this-is-ignored -a -b --foo="a b c" -z "dev" 254 `)) 255 256 cmd, err := autostart.AutostartCmd("snapname", fooDesktopFile) 257 c.Assert(cmd, IsNil) 258 c.Assert(err, ErrorMatches, `cannot match desktop file with snap snapname applications`) 259 } 260 261 func (s *autostartSuite) TestTryAutostartAppNoSnap(c *C) { 262 fooDesktopFile := filepath.Join(s.autostartDir, "foo-stable.desktop") 263 writeFile(c, fooDesktopFile, 264 []byte(`[Desktop Entry] 265 Exec=this-is-ignored -a -b --foo="a b c" -z "dev" 266 `)) 267 268 cmd, err := autostart.AutostartCmd("snapname", fooDesktopFile) 269 c.Assert(cmd, IsNil) 270 c.Assert(err, ErrorMatches, `cannot find current revision for snap snapname.*`) 271 } 272 273 func (s *autostartSuite) TestTryAutostartAppBadExec(c *C) { 274 snaptest.MockSnapCurrent(c, mockYaml, &snap.SideInfo{Revision: snap.R("x2")}) 275 276 fooDesktopFile := filepath.Join(s.autostartDir, "foo-stable.desktop") 277 writeFile(c, fooDesktopFile, 278 []byte(`[Desktop Entry] 279 Foo=bar 280 `)) 281 282 cmd, err := autostart.AutostartCmd("snapname", fooDesktopFile) 283 c.Assert(cmd, IsNil) 284 c.Assert(err, ErrorMatches, `cannot determine startup command for application foo in snap snapname: Exec not found or invalid`) 285 } 286 287 func writeFile(c *C, path string, content []byte) { 288 err := os.MkdirAll(filepath.Dir(path), 0755) 289 c.Assert(err, IsNil) 290 err = ioutil.WriteFile(path, content, 0644) 291 c.Assert(err, IsNil) 292 } 293 294 func (s *autostartSuite) TestTryAutostartMany(c *C) { 295 var mockYamlTemplate = `name: {snap} 296 version: 1.0 297 apps: 298 foo: 299 command: run-app 300 autostart: foo-stable.desktop 301 ` 302 303 snaptest.MockSnapCurrent(c, strings.Replace(mockYamlTemplate, "{snap}", "a-foo", -1), 304 &snap.SideInfo{Revision: snap.R("x2")}) 305 snaptest.MockSnapCurrent(c, strings.Replace(mockYamlTemplate, "{snap}", "b-foo", -1), 306 &snap.SideInfo{Revision: snap.R("x2")}) 307 writeFile(c, filepath.Join(s.userDir, "snap/a-foo/current/.config/autostart/foo-stable.desktop"), 308 []byte(`[Desktop Entry] 309 Foo=bar 310 `)) 311 writeFile(c, filepath.Join(s.userDir, "snap/b-foo/current/.config/autostart/no-match.desktop"), 312 []byte(`[Desktop Entry] 313 Exec=no-snap 314 `)) 315 writeFile(c, filepath.Join(s.userDir, "snap/c-foo/current/.config/autostart/no-snap.desktop"), 316 []byte(`[Desktop Entry] 317 Exec=no-snap 318 `)) 319 320 err := autostart.AutostartSessionApps() 321 c.Assert(err, NotNil) 322 c.Check(err, ErrorMatches, `- "foo-stable.desktop": cannot determine startup command for application foo in snap a-foo: Exec not found or invalid 323 - "no-match.desktop": cannot match desktop file with snap b-foo applications 324 - "no-snap.desktop": cannot find current revision for snap c-foo: readlink.*no such file or directory 325 `) 326 }