github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap/cmd_auto_import_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 main_test 21 22 import ( 23 "fmt" 24 "io/ioutil" 25 "net/http" 26 "os" 27 "path/filepath" 28 29 . "gopkg.in/check.v1" 30 31 snap "github.com/snapcore/snapd/cmd/snap" 32 "github.com/snapcore/snapd/dirs" 33 "github.com/snapcore/snapd/logger" 34 "github.com/snapcore/snapd/osutil" 35 "github.com/snapcore/snapd/release" 36 "github.com/snapcore/snapd/snap/snaptest" 37 "github.com/snapcore/snapd/testutil" 38 ) 39 40 func makeMockMountInfo(c *C, content string) string { 41 fn := filepath.Join(c.MkDir(), "mountinfo") 42 err := ioutil.WriteFile(fn, []byte(content), 0644) 43 c.Assert(err, IsNil) 44 return fn 45 } 46 47 func (s *SnapSuite) TestAutoImportAssertsHappy(c *C) { 48 restore := release.MockOnClassic(false) 49 defer restore() 50 51 fakeAssertData := []byte("my-assertion") 52 53 n := 0 54 total := 2 55 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 56 switch n { 57 case 0: 58 c.Check(r.Method, Equals, "POST") 59 c.Check(r.URL.Path, Equals, "/v2/assertions") 60 postData, err := ioutil.ReadAll(r.Body) 61 c.Assert(err, IsNil) 62 c.Check(postData, DeepEquals, fakeAssertData) 63 fmt.Fprintln(w, `{"type": "sync", "result": {"ready": true, "status": "Done"}}`) 64 n++ 65 case 1: 66 c.Check(r.Method, Equals, "POST") 67 c.Check(r.URL.Path, Equals, "/v2/users") 68 postData, err := ioutil.ReadAll(r.Body) 69 c.Assert(err, IsNil) 70 c.Check(string(postData), Equals, `{"action":"create","automatic":true}`) 71 72 fmt.Fprintln(w, `{"type": "sync", "result": [{"username": "foo"}]}`) 73 n++ 74 default: 75 c.Fatalf("unexpected request: %v (expected %d got %d)", r, total, n) 76 } 77 78 }) 79 80 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 81 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 82 c.Assert(err, IsNil) 83 84 mockMountInfoFmt := ` 85 24 0 8:18 / %s rw,relatime shared:1 - ext4 /dev/sdb2 rw,errors=remount-ro,data=ordered` 86 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 87 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 88 defer restore() 89 90 logbuf, restore := logger.MockLogger() 91 defer restore() 92 93 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 94 c.Assert(err, IsNil) 95 c.Assert(rest, DeepEquals, []string{}) 96 c.Check(s.Stdout(), Equals, `created user "foo"`+"\n") 97 // matches because we may get a: 98 // "WARNING: cannot create syslog logger\n" 99 // in the output 100 c.Check(logbuf.String(), Matches, fmt.Sprintf("(?ms).*imported %s\n", fakeAssertsFn)) 101 c.Check(n, Equals, total) 102 } 103 104 func (s *SnapSuite) TestAutoImportAssertsNotImportedFromLoop(c *C) { 105 restore := release.MockOnClassic(false) 106 defer restore() 107 108 fakeAssertData := []byte("bad-assertion") 109 110 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 111 // assertion is ignored, nothing is posted to this endpoint 112 panic("not reached") 113 }) 114 115 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 116 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 117 c.Assert(err, IsNil) 118 119 mockMountInfoFmtWithLoop := ` 120 24 0 8:18 / %s rw,relatime shared:1 - squashfs /dev/loop1 rw,errors=remount-ro,data=ordered` 121 content := fmt.Sprintf(mockMountInfoFmtWithLoop, filepath.Dir(fakeAssertsFn)) 122 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 123 defer restore() 124 125 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 126 c.Assert(err, IsNil) 127 c.Assert(rest, DeepEquals, []string{}) 128 c.Check(s.Stdout(), Equals, "") 129 c.Check(s.Stderr(), Equals, "") 130 } 131 132 func (s *SnapSuite) TestAutoImportCandidatesHappy(c *C) { 133 dirs := make([]string, 4) 134 args := make([]interface{}, len(dirs)) 135 files := make([]string, len(dirs)) 136 for i := range dirs { 137 dirs[i] = c.MkDir() 138 args[i] = dirs[i] 139 files[i] = filepath.Join(dirs[i], "auto-import.assert") 140 err := ioutil.WriteFile(files[i], nil, 0644) 141 c.Assert(err, IsNil) 142 } 143 144 mockMountInfoFmtWithLoop := ` 145 too short 146 24 0 8:18 / %[1]s rw,relatime foo ext3 /dev/meep2 no,separator 147 24 0 8:18 / %[2]s rw,relatime - ext3 /dev/meep2 rw,errors=remount-ro,data=ordered 148 24 0 8:18 / %[3]s rw,relatime opt:1 - ext4 /dev/meep3 rw,errors=remount-ro,data=ordered 149 24 0 8:18 / %[4]s rw,relatime opt:1 opt:2 - ext2 /dev/meep1 rw,errors=remount-ro,data=ordered 150 ` 151 152 content := fmt.Sprintf(mockMountInfoFmtWithLoop, args...) 153 restore := snap.MockMountInfoPath(makeMockMountInfo(c, content)) 154 defer restore() 155 156 l, err := snap.AutoImportCandidates() 157 c.Check(err, IsNil) 158 c.Check(l, DeepEquals, files[1:]) 159 } 160 161 func (s *SnapSuite) TestAutoImportAssertsHappyNotOnClassic(c *C) { 162 restore := release.MockOnClassic(true) 163 defer restore() 164 165 fakeAssertData := []byte("my-assertion") 166 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 167 c.Errorf("auto-import on classic is disabled, but something tried to do a %q with %s", r.Method, r.URL.Path) 168 }) 169 170 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 171 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 172 c.Assert(err, IsNil) 173 174 mockMountInfoFmt := ` 175 24 0 8:18 / %s rw,relatime shared:1 - ext4 /dev/sdb2 rw,errors=remount-ro,data=ordered` 176 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 177 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 178 defer restore() 179 180 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 181 c.Assert(err, IsNil) 182 c.Assert(rest, DeepEquals, []string{}) 183 c.Check(s.Stdout(), Equals, "") 184 c.Check(s.Stderr(), Equals, "auto-import is disabled on classic\n") 185 } 186 187 func (s *SnapSuite) TestAutoImportIntoSpool(c *C) { 188 restore := release.MockOnClassic(false) 189 defer restore() 190 191 logbuf, restore := logger.MockLogger() 192 defer restore() 193 194 fakeAssertData := []byte("good-assertion") 195 196 // ensure we can not connect 197 snap.ClientConfig.BaseURL = "can-not-connect-to-this-url" 198 199 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 200 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 201 c.Assert(err, IsNil) 202 203 mockMountInfoFmt := ` 204 24 0 8:18 / %s rw,relatime shared:1 - squashfs /dev/sc1 rw,errors=remount-ro,data=ordered` 205 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 206 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 207 defer restore() 208 209 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 210 c.Assert(err, IsNil) 211 c.Assert(rest, DeepEquals, []string{}) 212 c.Check(s.Stdout(), Equals, "") 213 // matches because we may get a: 214 // "WARNING: cannot create syslog logger\n" 215 // in the output 216 c.Check(logbuf.String(), Matches, "(?ms).*queuing for later.*\n") 217 218 files, err := ioutil.ReadDir(dirs.SnapAssertsSpoolDir) 219 c.Assert(err, IsNil) 220 c.Check(files, HasLen, 1) 221 c.Check(files[0].Name(), Equals, "iOkaeet50rajLvL-0Qsf2ELrTdn3XIXRIBlDewcK02zwRi3_TJlUOTl9AaiDXmDn.assert") 222 } 223 224 func (s *SnapSuite) TestAutoImportFromSpoolHappy(c *C) { 225 restore := release.MockOnClassic(false) 226 defer restore() 227 228 fakeAssertData := []byte("my-assertion") 229 230 n := 0 231 total := 2 232 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 233 switch n { 234 case 0: 235 c.Check(r.Method, Equals, "POST") 236 c.Check(r.URL.Path, Equals, "/v2/assertions") 237 postData, err := ioutil.ReadAll(r.Body) 238 c.Assert(err, IsNil) 239 c.Check(postData, DeepEquals, fakeAssertData) 240 fmt.Fprintln(w, `{"type": "sync", "result": {"ready": true, "status": "Done"}}`) 241 n++ 242 case 1: 243 c.Check(r.Method, Equals, "POST") 244 c.Check(r.URL.Path, Equals, "/v2/users") 245 postData, err := ioutil.ReadAll(r.Body) 246 c.Assert(err, IsNil) 247 c.Check(string(postData), Equals, `{"action":"create","automatic":true}`) 248 249 fmt.Fprintln(w, `{"type": "sync", "result": [{"username": "foo"}]}`) 250 n++ 251 default: 252 c.Fatalf("unexpected request: %v (expected %d got %d)", r, total, n) 253 } 254 255 }) 256 257 fakeAssertsFn := filepath.Join(dirs.SnapAssertsSpoolDir, "1234343") 258 err := os.MkdirAll(filepath.Dir(fakeAssertsFn), 0755) 259 c.Assert(err, IsNil) 260 err = ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 261 c.Assert(err, IsNil) 262 263 logbuf, restore := logger.MockLogger() 264 defer restore() 265 266 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 267 c.Assert(err, IsNil) 268 c.Assert(rest, DeepEquals, []string{}) 269 c.Check(s.Stdout(), Equals, `created user "foo"`+"\n") 270 // matches because we may get a: 271 // "WARNING: cannot create syslog logger\n" 272 // in the output 273 c.Check(logbuf.String(), Matches, fmt.Sprintf("(?ms).*imported %s\n", fakeAssertsFn)) 274 c.Check(n, Equals, total) 275 276 c.Check(osutil.FileExists(fakeAssertsFn), Equals, false) 277 } 278 279 func (s *SnapSuite) TestAutoImportIntoSpoolUnhappyTooBig(c *C) { 280 restore := release.MockOnClassic(false) 281 defer restore() 282 283 _, restoreLogger := logger.MockLogger() 284 defer restoreLogger() 285 286 // fake data is bigger than the default assertion limit 287 fakeAssertData := make([]byte, 641*1024) 288 289 // ensure we can not connect 290 snap.ClientConfig.BaseURL = "can-not-connect-to-this-url" 291 292 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 293 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 294 c.Assert(err, IsNil) 295 296 mockMountInfoFmt := ` 297 24 0 8:18 / %s rw,relatime shared:1 - squashfs /dev/sc1 rw,errors=remount-ro,data=ordered` 298 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 299 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 300 defer restore() 301 302 _, err = snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 303 c.Assert(err, ErrorMatches, "cannot queue .*, file size too big: 656384") 304 } 305 306 func (s *SnapSuite) TestAutoImportUnhappyInInstallMode(c *C) { 307 restore := release.MockOnClassic(false) 308 defer restore() 309 310 _, restoreLogger := logger.MockLogger() 311 defer restoreLogger() 312 313 mockProcCmdlinePath := filepath.Join(c.MkDir(), "cmdline") 314 err := ioutil.WriteFile(mockProcCmdlinePath, []byte("foo=bar snapd_recovery_mode=install snapd_recovery_system=20191118"), 0644) 315 c.Assert(err, IsNil) 316 317 restore = osutil.MockProcCmdline(mockProcCmdlinePath) 318 defer restore() 319 320 _, err = snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 321 c.Assert(err, IsNil) 322 c.Check(s.Stdout(), Equals, "") 323 c.Check(s.Stderr(), Equals, "auto-import is disabled in install-mode\n") 324 } 325 326 var mountStatic = []string{"mount", "-t", "ext4,vfat", "-o", "ro", "--make-private"} 327 328 func (s *SnapSuite) TestAutoImportFromRemovable(c *C) { 329 restore := release.MockOnClassic(false) 330 defer restore() 331 332 _, restoreLogger := logger.MockLogger() 333 defer restoreLogger() 334 335 rootdir := c.MkDir() 336 dirs.SetRootDir(rootdir) 337 338 var umounts []string 339 restore = snap.MockSyscallUmount(func(p string, _ int) error { 340 umounts = append(umounts, p) 341 return nil 342 }) 343 defer restore() 344 345 var tmpdirIdx int 346 restore = snap.MockIoutilTempDir(func(where string, p string) (string, error) { 347 c.Check(where, Equals, "") 348 tmpdirIdx++ 349 return filepath.Join(rootdir, fmt.Sprintf("/tmp/%s%d", p, tmpdirIdx)), nil 350 }) 351 defer restore() 352 353 mountCmd := testutil.MockCommand(c, "mount", "") 354 defer mountCmd.Restore() 355 356 snaptest.PopulateDir(rootdir, [][]string{ 357 // removable without partitions 358 {"sys/block/sdremovable/removable", "1\n"}, 359 // fixed disk 360 {"sys/block/sdfixed/removable", "0\n"}, 361 // removable with partitions 362 {"sys/block/sdpart/removable", "1\n"}, 363 {"sys/block/sdpart/sdpart1/partition", "1\n"}, 364 {"sys/block/sdpart/sdpart2/partition", "0\n"}, 365 {"sys/block/sdpart/sdpart3/partition", "1\n"}, 366 // removable but subdevices are not partitions? 367 {"sys/block/sdother/removable", "1\n"}, 368 {"sys/block/sdother/sdother1/partition", "0\n"}, 369 }) 370 371 // do not mock mountinfo contents, we just want to observe whether we 372 // try to mount and umount the right stuff 373 374 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 375 c.Assert(err, IsNil) 376 c.Check(s.Stdout(), Equals, "") 377 c.Check(s.Stderr(), Equals, "") 378 c.Check(mountCmd.Calls(), DeepEquals, [][]string{ 379 append(mountStatic, "/dev/sdpart1", filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-1")), 380 append(mountStatic, "/dev/sdpart3", filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-2")), 381 append(mountStatic, "/dev/sdremovable", filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-3")), 382 }) 383 c.Check(umounts, DeepEquals, []string{ 384 filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-3"), 385 filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-2"), 386 filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-1"), 387 }) 388 } 389 390 func (s *SnapSuite) TestAutoImportNoRemovable(c *C) { 391 restore := release.MockOnClassic(false) 392 defer restore() 393 394 rootdir := c.MkDir() 395 dirs.SetRootDir(rootdir) 396 397 var umounts []string 398 restore = snap.MockSyscallUmount(func(p string, _ int) error { 399 return fmt.Errorf("unexpected call") 400 }) 401 defer restore() 402 403 mountCmd := testutil.MockCommand(c, "mount", "exit 1") 404 defer mountCmd.Restore() 405 406 snaptest.PopulateDir(rootdir, [][]string{ 407 // fixed disk 408 {"sys/block/sdfixed/removable", "0\n"}, 409 // removable but subdevices are not partitions? 410 {"sys/block/sdother/removable", "1\n"}, 411 {"sys/block/sdother/sdother1/partition", "0\n"}, 412 }) 413 414 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 415 c.Assert(err, IsNil) 416 c.Check(s.Stdout(), Equals, "") 417 c.Check(s.Stderr(), Equals, "") 418 c.Check(mountCmd.Calls(), HasLen, 0) 419 c.Check(umounts, HasLen, 0) 420 } 421 422 func (s *SnapSuite) TestAutoImportFromMount(c *C) { 423 restore := release.MockOnClassic(false) 424 defer restore() 425 426 _, restoreLogger := logger.MockLogger() 427 defer restoreLogger() 428 429 mountCmd := testutil.MockCommand(c, "mount", "") 430 431 rootdir := c.MkDir() 432 dirs.SetRootDir(rootdir) 433 434 var umounts []string 435 restore = snap.MockSyscallUmount(func(p string, _ int) error { 436 c.Assert(umounts, HasLen, 0) 437 umounts = append(umounts, p) 438 return nil 439 }) 440 defer restore() 441 442 var tmpdircalls int 443 restore = snap.MockIoutilTempDir(func(where string, p string) (string, error) { 444 c.Check(where, Equals, "") 445 c.Assert(tmpdircalls, Equals, 0) 446 tmpdircalls++ 447 return filepath.Join(rootdir, fmt.Sprintf("/tmp/%s1", p)), nil 448 }) 449 defer restore() 450 451 // do not mock mountinfo contents, we just want to observe whether we 452 // try to mount and umount the right stuff 453 454 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import", "--mount", "/dev/foobar"}) 455 c.Assert(err, IsNil) 456 c.Check(s.Stdout(), Equals, "") 457 c.Check(s.Stderr(), Equals, "") 458 c.Check(mountCmd.Calls(), DeepEquals, [][]string{ 459 append(mountStatic, "/dev/foobar", filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-1")), 460 }) 461 c.Check(umounts, DeepEquals, []string{ 462 filepath.Join(rootdir, "/tmp/snapd-auto-import-mount-1"), 463 }) 464 } 465 466 func (s *SnapSuite) TestAutoImportUC20CandidatesIgnoresSystemPartitions(c *C) { 467 468 mountDirs := []string{ 469 "/writable/system-data/var/lib/snapd/seed", 470 "/var/lib/snapd/seed", 471 "/run/mnt/ubuntu-boot", 472 "/run/mnt/ubuntu-seed", 473 "/run/mnt/ubuntu-data", 474 "/mnt/real-device", 475 } 476 477 rootDir := c.MkDir() 478 dirs.SetRootDir(rootDir) 479 defer func() { dirs.SetRootDir("") }() 480 481 args := make([]interface{}, 0, len(mountDirs)+1) 482 args = append(args, dirs.GlobalRootDir) 483 // pretend there are auto-import.asserts on all of them 484 for _, dir := range mountDirs { 485 args = append(args, dir) 486 file := filepath.Join(rootDir, dir, "auto-import.assert") 487 c.Assert(os.MkdirAll(filepath.Dir(file), 0755), IsNil) 488 c.Assert(ioutil.WriteFile(file, nil, 0644), IsNil) 489 } 490 491 mockMountInfoFmtWithLoop := ` 492 24 0 8:18 / %[1]s%[2]s rw,relatime foo ext3 /dev/meep2 no,separator 493 24 0 8:18 / %[1]s%[3]s rw,relatime - ext3 /dev/meep2 rw,errors=remount-ro,data=ordered 494 24 0 8:18 / %[1]s%[4]s rw,relatime opt:1 - ext4 /dev/meep3 rw,errors=remount-ro,data=ordered 495 24 0 8:18 / %[1]s%[5]s rw,relatime opt:1 opt:2 - ext2 /dev/meep4 rw,errors=remount-ro,data=ordered 496 24 0 8:18 / %[1]s%[6]s rw,relatime opt:1 opt:2 - ext2 /dev/meep5 rw,errors=remount-ro,data=ordered 497 24 0 8:18 / %[1]s%[7]s rw,relatime opt:1 opt:2 - ext2 /dev/meep78 rw,errors=remount-ro,data=ordered 498 ` 499 500 content := fmt.Sprintf(mockMountInfoFmtWithLoop, args...) 501 restore := snap.MockMountInfoPath(makeMockMountInfo(c, content)) 502 defer restore() 503 504 l, err := snap.AutoImportCandidates() 505 c.Check(err, IsNil) 506 507 // only device should be the /mnt/real-device one 508 c.Check(l, DeepEquals, []string{filepath.Join(rootDir, "/mnt/real-device", "auto-import.assert")}) 509 } 510 511 func (s *SnapSuite) TestAutoImportAssertsManagedEmptyReply(c *C) { 512 restore := release.MockOnClassic(false) 513 defer restore() 514 515 _, restore = logger.MockLogger() 516 defer restore() 517 518 fakeAssertData := []byte("my-assertion") 519 520 n := 0 521 total := 2 522 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 523 switch n { 524 case 0: 525 c.Check(r.Method, Equals, "POST") 526 c.Check(r.URL.Path, Equals, "/v2/assertions") 527 postData, err := ioutil.ReadAll(r.Body) 528 c.Assert(err, IsNil) 529 c.Check(postData, DeepEquals, fakeAssertData) 530 fmt.Fprintln(w, `{"type": "sync", "result": {"ready": true, "status": "Done"}}`) 531 n++ 532 case 1: 533 c.Check(r.Method, Equals, "POST") 534 c.Check(r.URL.Path, Equals, "/v2/users") 535 postData, err := ioutil.ReadAll(r.Body) 536 c.Assert(err, IsNil) 537 c.Check(string(postData), Equals, `{"action":"create","automatic":true}`) 538 539 fmt.Fprintln(w, `{"type": "sync", "result": []}`) 540 n++ 541 default: 542 c.Fatalf("unexpected request: %v (expected %d got %d)", r, total, n) 543 } 544 545 }) 546 547 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 548 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 549 c.Assert(err, IsNil) 550 551 mockMountInfoFmt := ` 552 24 0 8:18 / %s rw,relatime shared:1 - ext4 /dev/sdb2 rw,errors=remount-ro,data=ordered` 553 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 554 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 555 defer restore() 556 557 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 558 c.Assert(err, IsNil) 559 c.Assert(rest, DeepEquals, []string{}) 560 c.Check(s.Stdout(), Equals, ``) 561 c.Check(n, Equals, total) 562 }