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