github.com/anonymouse64/snapd@v0.0.0-20210824153203-04c4c42d842d/usersession/userd/settings_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017-2020 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 userd_test 21 22 import ( 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 27 "github.com/godbus/dbus" 28 . "gopkg.in/check.v1" 29 30 "github.com/snapcore/snapd/dirs" 31 "github.com/snapcore/snapd/release" 32 "github.com/snapcore/snapd/testutil" 33 "github.com/snapcore/snapd/usersession/userd" 34 "github.com/snapcore/snapd/usersession/userd/ui" 35 ) 36 37 type settingsSuite struct { 38 testutil.BaseTest 39 40 settings *userd.Settings 41 mockXdgSettings *testutil.MockCmd 42 } 43 44 var _ = Suite(&settingsSuite{}) 45 46 func (s *settingsSuite) SetUpTest(c *C) { 47 s.BaseTest.SetUpTest(c) 48 49 dirs.SetRootDir(c.MkDir()) 50 s.AddCleanup(func() { dirs.SetRootDir("/") }) 51 s.AddCleanup(release.MockOnClassic(true)) 52 53 s.AddCleanup(userd.MockSnapFromSender(func(*dbus.Conn, dbus.Sender) (string, error) { 54 return "some-snap", nil 55 })) 56 57 s.settings = &userd.Settings{} 58 s.mockXdgSettings = testutil.MockCommand(c, "xdg-settings", ` 59 case "$1" in 60 get) 61 case "$2" in 62 default-web-browser) 63 echo "some-snap_foo.desktop" 64 ;; 65 default-url-scheme-handler) 66 echo "some-snap_ircclient.desktop" 67 ;; 68 *) 69 echo "mock called with unsupported arguments: $*" 70 exit 1 71 ;; 72 esac 73 ;; 74 set) 75 case "$2" in 76 default-web-browser) 77 # nothing to do 78 ;; 79 default-url-scheme-handler) 80 if [ "$3" = "irc2" ]; then 81 echo "fail" 82 exit 1 83 fi 84 # nothing to do 85 ;; 86 *) 87 echo "mock called with unsupported arguments: $*" 88 exit 1 89 ;; 90 esac 91 ;; 92 check) 93 case "$2" in 94 default-web-browser) 95 if [ "$3" = "some-snap_foo.desktop" ]; then 96 echo "yes" 97 else 98 echo "no" 99 fi 100 ;; 101 default-url-scheme-handler) 102 if [ "$3" = "irc" ] && [ "$4" = "some-snap_ircclient.desktop" ]; then 103 echo "yes" 104 else 105 echo "no" 106 fi 107 ;; 108 esac 109 ;; 110 *) 111 echo "mock called with unsupported argument: $1" 112 exit 1 113 ;; 114 esac 115 `) 116 s.AddCleanup(s.mockXdgSettings.Restore) 117 } 118 119 func mockUIcommands(c *C, script string) func() { 120 mockZenity := testutil.MockCommand(c, "zenity", script) 121 mockKDialog := testutil.MockCommand(c, "kdialog", script) 122 return func() { 123 mockZenity.Restore() 124 mockKDialog.Restore() 125 } 126 } 127 128 func (s *settingsSuite) TestGetUnhappy(c *C) { 129 for _, t := range []struct { 130 setting string 131 errMatcher string 132 }{ 133 {"random-setting", `invalid setting "random-setting"`}, 134 {"invälid", `invalid setting "invälid"`}, 135 {"", `invalid setting ""`}, 136 } { 137 _, err := s.settings.Get(t.setting, ":some-dbus-sender") 138 c.Assert(err, ErrorMatches, t.errMatcher) 139 c.Assert(s.mockXdgSettings.Calls(), IsNil) 140 } 141 } 142 143 func (s *settingsSuite) TestGetHappy(c *C) { 144 defaultBrowser, err := s.settings.Get("default-web-browser", ":some-dbus-sender") 145 c.Assert(err, IsNil) 146 c.Check(defaultBrowser, Equals, "foo.desktop") 147 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 148 {"xdg-settings", "get", "default-web-browser"}, 149 }) 150 } 151 152 func (s *settingsSuite) TestCheckInvalidSetting(c *C) { 153 _, err := s.settings.Check("random-setting", "foo.desktop", ":some-dbus-sender") 154 c.Assert(err, ErrorMatches, `invalid setting "random-setting"`) 155 c.Assert(s.mockXdgSettings.Calls(), IsNil) 156 } 157 158 func (s *settingsSuite) TestCheckIsDefault(c *C) { 159 isDefault, err := s.settings.Check("default-web-browser", "foo.desktop", ":some-dbus-sender") 160 c.Assert(err, IsNil) 161 c.Check(isDefault, Equals, "yes") 162 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 163 {"xdg-settings", "check", "default-web-browser", "some-snap_foo.desktop"}, 164 }) 165 } 166 167 func (s *settingsSuite) TestCheckIsDefaultUrlScheme(c *C) { 168 isDefault, err := s.settings.CheckSub("default-url-scheme-handler", "irc", "ircclient.desktop", ":some-dbus-sender") 169 c.Assert(err, IsNil) 170 c.Check(isDefault, Equals, "yes") 171 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 172 {"xdg-settings", "check", "default-url-scheme-handler", "irc", "some-snap_ircclient.desktop"}, 173 }) 174 } 175 176 func (s *settingsSuite) TestCheckNoDefault(c *C) { 177 isDefault, err := s.settings.Check("default-web-browser", "bar.desktop", ":some-dbus-sender") 178 c.Assert(err, IsNil) 179 c.Check(isDefault, Equals, "no") 180 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 181 {"xdg-settings", "check", "default-web-browser", "some-snap_bar.desktop"}, 182 }) 183 } 184 185 func (s *settingsSuite) TestCheckNoDefaultUrlScheme(c *C) { 186 isDefault, err := s.settings.CheckSub("default-url-scheme-handler", "irc", "bar.desktop", ":some-dbus-sender") 187 c.Assert(err, IsNil) 188 c.Check(isDefault, Equals, "no") 189 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 190 {"xdg-settings", "check", "default-url-scheme-handler", "irc", "some-snap_bar.desktop"}, 191 }) 192 } 193 194 func (s *settingsSuite) TestNotThisSnap(c *C) { 195 mockXdgSettings := testutil.MockCommand(c, "xdg-settings", ` 196 if [ "$1" = "get" ] && [ "$2" = "default-web-browser" ]; then 197 echo "other-snap_foo.desktop" 198 exit 0 199 fi 200 if [ "$1" = "get" ] && [ "$2" = "default-url-scheme-handler" ] && [ "$3" = "irc" ]; then 201 echo "other-snap_foo-irc.desktop" 202 exit 0 203 fi 204 205 echo "mock called with unsupported argument: $1" 206 exit 1 207 `) 208 defer mockXdgSettings.Restore() 209 210 defaultBrowser, err := s.settings.Get("default-web-browser", ":some-dbus-sender") 211 c.Assert(err, IsNil) 212 c.Check(defaultBrowser, Equals, "NOT-THIS-SNAP.desktop") 213 c.Check(mockXdgSettings.Calls(), DeepEquals, [][]string{ 214 {"xdg-settings", "get", "default-web-browser"}, 215 }) 216 217 mockXdgSettings.ForgetCalls() 218 219 defaultSchemeHandler, err := s.settings.GetSub("default-url-scheme-handler", "irc", ":some-dbus-sender") 220 c.Assert(err, IsNil) 221 c.Check(defaultSchemeHandler, Equals, "NOT-THIS-SNAP.desktop") 222 c.Check(mockXdgSettings.Calls(), DeepEquals, [][]string{ 223 {"xdg-settings", "get", "default-url-scheme-handler", "irc"}, 224 }) 225 } 226 227 func (s *settingsSuite) TestSetInvalidSetting(c *C) { 228 err := s.settings.Set("random-setting", "foo.desktop", ":some-dbus-sender") 229 c.Assert(err, ErrorMatches, `invalid setting "random-setting"`) 230 c.Assert(s.mockXdgSettings.Calls(), IsNil) 231 } 232 233 func (s *settingsSuite) TestSetInvalidValue(c *C) { 234 err := s.settings.Set("default-web-browser", "foo", ":some-dbus-sender") 235 c.Assert(err, ErrorMatches, `cannot set "default-web-browser" setting to invalid value "foo"`) 236 c.Assert(s.mockXdgSettings.Calls(), IsNil) 237 } 238 239 func (s *settingsSuite) TestSetSubInvalidSetting(c *C) { 240 err := s.settings.SetSub("random-setting", "subprop", "foo.desktop", ":some-dbus-sender") 241 c.Assert(err, ErrorMatches, `invalid setting "random-setting"`) 242 c.Assert(s.mockXdgSettings.Calls(), IsNil) 243 } 244 245 func (s *settingsSuite) TestSetSubInvalidValue(c *C) { 246 err := s.settings.SetSub("default-url-scheme-handler", "irc", "foo", ":some-dbus-sender") 247 c.Assert(err, ErrorMatches, `cannot set "default-url-scheme-handler" subproperty "irc" setting to invalid value "foo"`) 248 c.Assert(s.mockXdgSettings.Calls(), IsNil) 249 } 250 251 func (s *settingsSuite) testSetUserDeclined(c *C) { 252 df := filepath.Join(dirs.SnapDesktopFilesDir, "some-snap_bar.desktop") 253 err := os.MkdirAll(filepath.Dir(df), 0755) 254 c.Assert(err, IsNil) 255 err = ioutil.WriteFile(df, nil, 0644) 256 c.Assert(err, IsNil) 257 258 err = s.settings.Set("default-web-browser", "bar.desktop", ":some-dbus-sender") 259 c.Assert(err, ErrorMatches, `cannot change configuration: user declined change`) 260 c.Check(s.mockXdgSettings.Calls(), IsNil) 261 // FIXME: this needs PR#4342 262 /* 263 c.Check(mockZenity.Calls(), DeepEquals, [][]string{ 264 {"zenity", "--question", "--text=Allow changing setting \"default-web-browser\" to \"bar.desktop\" ?"}, 265 }) 266 */ 267 } 268 269 func (s *settingsSuite) TestSetUserDeclinedKDialog(c *C) { 270 // force zenity exec missing 271 restoreZenity := ui.MockHasZenityExecutable(func() bool { return false }) 272 restoreCmds := mockUIcommands(c, "false") 273 defer func() { 274 restoreZenity() 275 restoreCmds() 276 }() 277 278 s.testSetUserDeclined(c) 279 } 280 281 func (s *settingsSuite) TestSetUserDeclinedZenity(c *C) { 282 // force kdialog exec missing 283 restoreKDialog := ui.MockHasKDialogExecutable(func() bool { return false }) 284 restoreCmds := mockUIcommands(c, "false") 285 defer func() { 286 restoreKDialog() 287 restoreCmds() 288 }() 289 290 s.testSetUserDeclined(c) 291 } 292 293 func (s *settingsSuite) testSetUserAccepts(c *C) { 294 df := filepath.Join(dirs.SnapDesktopFilesDir, "some-snap_foo.desktop") 295 err := os.MkdirAll(filepath.Dir(df), 0755) 296 c.Assert(err, IsNil) 297 err = ioutil.WriteFile(df, nil, 0644) 298 c.Assert(err, IsNil) 299 300 err = s.settings.Set("default-web-browser", "foo.desktop", ":some-dbus-sender") 301 c.Assert(err, IsNil) 302 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 303 {"xdg-settings", "set", "default-web-browser", "some-snap_foo.desktop"}, 304 }) 305 // FIXME: this needs PR#4342 306 /* 307 c.Check(mockZenity.Calls(), DeepEquals, [][]string{ 308 {"zenity", "--question", "--text=Allow changing setting \"default-web-browser\" to \"foo.desktop\" ?"}, 309 }) 310 */ 311 } 312 313 func (s *settingsSuite) testSetUserAcceptsURLScheme(c *C) { 314 df := filepath.Join(dirs.SnapDesktopFilesDir, "some-snap_ircclient.desktop") 315 err := os.MkdirAll(filepath.Dir(df), 0755) 316 c.Assert(err, IsNil) 317 err = ioutil.WriteFile(df, nil, 0644) 318 c.Assert(err, IsNil) 319 320 err = s.settings.SetSub("default-url-scheme-handler", "irc", "ircclient.desktop", ":some-dbus-sender") 321 c.Assert(err, IsNil) 322 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 323 {"xdg-settings", "set", "default-url-scheme-handler", "irc", "some-snap_ircclient.desktop"}, 324 }) 325 } 326 327 func (s *settingsSuite) TestSetUserAcceptsZenity(c *C) { 328 // force kdialog exec missing 329 restoreKDialog := ui.MockHasKDialogExecutable(func() bool { return false }) 330 restoreCmds := mockUIcommands(c, "true") 331 defer func() { 332 restoreKDialog() 333 restoreCmds() 334 }() 335 336 s.testSetUserAccepts(c) 337 } 338 339 func (s *settingsSuite) TestSetUserAcceptsZenityUrlScheme(c *C) { 340 // force kdialog exec missing 341 restoreKDialog := ui.MockHasKDialogExecutable(func() bool { return false }) 342 restoreCmds := mockUIcommands(c, "true") 343 defer func() { 344 restoreKDialog() 345 restoreCmds() 346 }() 347 348 s.testSetUserAcceptsURLScheme(c) 349 } 350 351 func (s *settingsSuite) TestSetUserAcceptsKDialog(c *C) { 352 // force zenity exec missing 353 restoreZenity := ui.MockHasZenityExecutable(func() bool { return false }) 354 restoreCmds := mockUIcommands(c, "true") 355 defer func() { 356 restoreZenity() 357 restoreCmds() 358 }() 359 360 s.testSetUserAccepts(c) 361 } 362 363 func (s *settingsSuite) TestSetUserAcceptsKDialogUrlScheme(c *C) { 364 // force zenity exec missing 365 restoreZenity := ui.MockHasZenityExecutable(func() bool { return false }) 366 restoreCmds := mockUIcommands(c, "true") 367 defer func() { 368 restoreZenity() 369 restoreCmds() 370 }() 371 372 s.testSetUserAcceptsURLScheme(c) 373 } 374 375 func (s *settingsSuite) TestSetUserAcceptsZenityUrlSchemeXdgSettingsError(c *C) { 376 // force kdialog exec missing 377 restoreKDialog := ui.MockHasKDialogExecutable(func() bool { return false }) 378 restoreCmds := mockUIcommands(c, "true") 379 defer func() { 380 restoreKDialog() 381 restoreCmds() 382 }() 383 384 df := filepath.Join(dirs.SnapDesktopFilesDir, "some-snap_ircclient.desktop") 385 err := os.MkdirAll(filepath.Dir(df), 0755) 386 c.Assert(err, IsNil) 387 err = ioutil.WriteFile(df, nil, 0644) 388 c.Assert(err, IsNil) 389 390 err = s.settings.SetSub("default-url-scheme-handler", "irc2", "ircclient.desktop", ":some-dbus-sender") 391 c.Assert(err, ErrorMatches, `cannot set "default-url-scheme-handler" subproperty "irc2" setting: fail`) 392 c.Check(s.mockXdgSettings.Calls(), DeepEquals, [][]string{ 393 {"xdg-settings", "set", "default-url-scheme-handler", "irc2", "some-snap_ircclient.desktop"}, 394 }) 395 } 396 397 func (s *settingsSuite) TestFailsOnUbuntuCore(c *C) { 398 restore := release.MockOnClassic(false) 399 defer restore() 400 401 _, err := s.settings.Check("default-web-browser", "foo.desktop", ":some-dbus-sender") 402 c.Check(err, ErrorMatches, "not supported on Ubuntu Core") 403 404 _, err = s.settings.CheckSub("default-url-scheme-handler", "irc", "bar.desktop", ":some-dbus-sender") 405 c.Check(err, ErrorMatches, "not supported on Ubuntu Core") 406 407 _, err = s.settings.Get("default-web-browser", ":some-dbus-sender") 408 c.Check(err, ErrorMatches, "not supported on Ubuntu Core") 409 410 _, err = s.settings.GetSub("default-url-scheme-handler", "irc", ":some-dbus-sender") 411 c.Check(err, ErrorMatches, "not supported on Ubuntu Core") 412 413 err = s.settings.Set("default-web-browser", "foo.desktop", ":some-dbus-sender") 414 c.Check(err, ErrorMatches, "not supported on Ubuntu Core") 415 err = s.settings.SetSub("default-url-scheme-handler", "irc", "ircclient.desktop", ":some-dbus-sender") 416 c.Check(err, ErrorMatches, "not supported on Ubuntu Core") 417 418 c.Check(s.mockXdgSettings.Calls(), HasLen, 0) 419 }