github.com/rigado/snapd@v2.42.5-go-mod+incompatible/snap/info_snap_yaml_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 snap_test 21 22 import ( 23 "regexp" 24 "testing" 25 "time" 26 27 . "gopkg.in/check.v1" 28 29 "github.com/snapcore/snapd/snap" 30 "github.com/snapcore/snapd/strutil" 31 "github.com/snapcore/snapd/timeout" 32 33 "github.com/snapcore/snapd/testutil" 34 ) 35 36 // Hook up check.v1 into the "go test" runner 37 func Test(t *testing.T) { TestingT(t) } 38 39 type InfoSnapYamlTestSuite struct { 40 testutil.BaseTest 41 } 42 43 var _ = Suite(&InfoSnapYamlTestSuite{}) 44 45 var mockYaml = []byte(`name: foo 46 version: 1.0 47 type: app 48 `) 49 50 func (s *InfoSnapYamlTestSuite) SetUpTest(c *C) { 51 s.BaseTest.SetUpTest(c) 52 s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 53 } 54 55 func (s *InfoSnapYamlTestSuite) TearDownTest(c *C) { 56 s.BaseTest.TearDownTest(c) 57 } 58 59 func (s *InfoSnapYamlTestSuite) TestSimple(c *C) { 60 info, err := snap.InfoFromSnapYaml(mockYaml) 61 c.Assert(err, IsNil) 62 c.Assert(info.InstanceName(), Equals, "foo") 63 c.Assert(info.Version, Equals, "1.0") 64 c.Assert(info.GetType(), Equals, snap.TypeApp) 65 c.Assert(info.Epoch, DeepEquals, snap.E("0")) 66 } 67 68 func (s *InfoSnapYamlTestSuite) TestSnapdTypeAddedByMagic(c *C) { 69 info, err := snap.InfoFromSnapYaml([]byte(`name: snapd 70 version: 1.0`)) 71 c.Assert(err, IsNil) 72 c.Assert(info.InstanceName(), Equals, "snapd") 73 c.Assert(info.Version, Equals, "1.0") 74 c.Assert(info.GetType(), Equals, snap.TypeSnapd) 75 } 76 77 func (s *InfoSnapYamlTestSuite) TestFail(c *C) { 78 _, err := snap.InfoFromSnapYaml([]byte("random-crap")) 79 c.Assert(err, ErrorMatches, "(?m)cannot parse snap.yaml:.*") 80 } 81 82 type YamlSuite struct { 83 restore func() 84 testutil.BaseTest 85 } 86 87 var _ = Suite(&YamlSuite{}) 88 89 func (s *YamlSuite) SetUpTest(c *C) { 90 s.BaseTest.SetUpTest(c) 91 s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 92 hookType := snap.NewHookType(regexp.MustCompile(".*")) 93 s.restore = snap.MockSupportedHookTypes([]*snap.HookType{hookType}) 94 } 95 96 func (s *YamlSuite) TearDownTest(c *C) { 97 s.BaseTest.TearDownTest(c) 98 s.restore() 99 } 100 101 func (s *YamlSuite) TestUnmarshalGarbage(c *C) { 102 _, err := snap.InfoFromSnapYaml([]byte(`"`)) 103 c.Assert(err, ErrorMatches, ".*: yaml: found unexpected end of stream") 104 } 105 106 func (s *YamlSuite) TestUnmarshalEmpty(c *C) { 107 info, err := snap.InfoFromSnapYaml([]byte(``)) 108 c.Assert(err, IsNil) 109 c.Assert(info.Plugs, HasLen, 0) 110 c.Assert(info.Slots, HasLen, 0) 111 c.Assert(info.Apps, HasLen, 0) 112 } 113 114 // Tests focusing on plugs 115 116 func (s *YamlSuite) TestUnmarshalStandaloneImplicitPlug(c *C) { 117 // NOTE: yaml content cannot use tabs, indent the section with spaces. 118 info, err := snap.InfoFromSnapYaml([]byte(` 119 name: snap 120 plugs: 121 network-client: 122 `)) 123 c.Assert(err, IsNil) 124 c.Check(info.InstanceName(), Equals, "snap") 125 c.Check(info.Plugs, HasLen, 1) 126 c.Check(info.Slots, HasLen, 0) 127 c.Assert(info.Plugs["network-client"], DeepEquals, &snap.PlugInfo{ 128 Snap: info, 129 Name: "network-client", 130 Interface: "network-client", 131 }) 132 } 133 134 func (s *YamlSuite) TestUnmarshalStandaloneAbbreviatedPlug(c *C) { 135 // NOTE: yaml content cannot use tabs, indent the section with spaces. 136 info, err := snap.InfoFromSnapYaml([]byte(` 137 name: snap 138 plugs: 139 net: network-client 140 `)) 141 c.Assert(err, IsNil) 142 c.Check(info.InstanceName(), Equals, "snap") 143 c.Check(info.Plugs, HasLen, 1) 144 c.Check(info.Slots, HasLen, 0) 145 c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{ 146 Snap: info, 147 Name: "net", 148 Interface: "network-client", 149 }) 150 } 151 152 func (s *YamlSuite) TestUnmarshalStandaloneMinimalisticPlug(c *C) { 153 // NOTE: yaml content cannot use tabs, indent the section with spaces. 154 info, err := snap.InfoFromSnapYaml([]byte(` 155 name: snap 156 plugs: 157 net: 158 interface: network-client 159 `)) 160 c.Assert(err, IsNil) 161 c.Check(info.InstanceName(), Equals, "snap") 162 c.Check(info.Plugs, HasLen, 1) 163 c.Check(info.Slots, HasLen, 0) 164 c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{ 165 Snap: info, 166 Name: "net", 167 Interface: "network-client", 168 }) 169 } 170 171 func (s *YamlSuite) TestUnmarshalStandaloneCompletePlug(c *C) { 172 // NOTE: yaml content cannot use tabs, indent the section with spaces. 173 info, err := snap.InfoFromSnapYaml([]byte(` 174 name: snap 175 plugs: 176 net: 177 interface: network-client 178 ipv6-aware: true 179 `)) 180 c.Assert(err, IsNil) 181 c.Check(info.InstanceName(), Equals, "snap") 182 c.Check(info.Plugs, HasLen, 1) 183 c.Check(info.Slots, HasLen, 0) 184 c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{ 185 Snap: info, 186 Name: "net", 187 Interface: "network-client", 188 Attrs: map[string]interface{}{"ipv6-aware": true}, 189 }) 190 } 191 192 func (s *YamlSuite) TestUnmarshalStandalonePlugWithIntAndListAndMap(c *C) { 193 // NOTE: yaml content cannot use tabs, indent the section with spaces. 194 info, err := snap.InfoFromSnapYaml([]byte(` 195 name: snap 196 plugs: 197 iface: 198 interface: complex 199 i: 3 200 l: [1,2,3] 201 m: 202 a: A 203 b: B 204 `)) 205 c.Assert(err, IsNil) 206 c.Check(info.InstanceName(), Equals, "snap") 207 c.Check(info.Plugs, HasLen, 1) 208 c.Check(info.Slots, HasLen, 0) 209 c.Assert(info.Plugs["iface"], DeepEquals, &snap.PlugInfo{ 210 Snap: info, 211 Name: "iface", 212 Interface: "complex", 213 Attrs: map[string]interface{}{ 214 "i": int64(3), 215 "l": []interface{}{int64(1), int64(2), int64(3)}, 216 "m": map[string]interface{}{"a": "A", "b": "B"}, 217 }, 218 }) 219 } 220 221 func (s *YamlSuite) TestUnmarshalLastPlugDefinitionWins(c *C) { 222 // NOTE: yaml content cannot use tabs, indent the section with spaces. 223 info, err := snap.InfoFromSnapYaml([]byte(` 224 name: snap 225 plugs: 226 net: 227 interface: network-client 228 attr: 1 229 net: 230 interface: network-client 231 attr: 2 232 `)) 233 c.Assert(err, IsNil) 234 c.Check(info.InstanceName(), Equals, "snap") 235 c.Check(info.Plugs, HasLen, 1) 236 c.Check(info.Slots, HasLen, 0) 237 c.Assert(info.Plugs["net"], DeepEquals, &snap.PlugInfo{ 238 Snap: info, 239 Name: "net", 240 Interface: "network-client", 241 Attrs: map[string]interface{}{"attr": int64(2)}, 242 }) 243 } 244 245 func (s *YamlSuite) TestUnmarshalPlugsExplicitlyDefinedImplicitlyBoundToApps(c *C) { 246 // NOTE: yaml content cannot use tabs, indent the section with spaces. 247 info, err := snap.InfoFromSnapYaml([]byte(` 248 name: snap 249 plugs: 250 network-client: 251 apps: 252 app: 253 `)) 254 c.Assert(err, IsNil) 255 c.Check(info.InstanceName(), Equals, "snap") 256 c.Check(info.Plugs, HasLen, 1) 257 c.Check(info.Slots, HasLen, 0) 258 c.Check(info.Apps, HasLen, 1) 259 260 plug := info.Plugs["network-client"] 261 app := info.Apps["app"] 262 c.Assert(plug, DeepEquals, &snap.PlugInfo{ 263 Snap: info, 264 Name: "network-client", 265 Interface: "network-client", 266 Apps: map[string]*snap.AppInfo{app.Name: app}, 267 }) 268 c.Assert(app, DeepEquals, &snap.AppInfo{ 269 Snap: info, 270 Name: "app", 271 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 272 }) 273 } 274 275 func (s *YamlSuite) TestUnmarshalGlobalPlugBoundToOneApp(c *C) { 276 // NOTE: yaml content cannot use tabs, indent the section with spaces. 277 info, err := snap.InfoFromSnapYaml([]byte(` 278 name: snap 279 plugs: 280 network-client: 281 apps: 282 with-plug: 283 plugs: [network-client] 284 without-plug: 285 `)) 286 c.Assert(err, IsNil) 287 c.Check(info.InstanceName(), Equals, "snap") 288 c.Check(info.Plugs, HasLen, 1) 289 c.Check(info.Slots, HasLen, 0) 290 c.Check(info.Apps, HasLen, 2) 291 292 plug := info.Plugs["network-client"] 293 withPlugApp := info.Apps["with-plug"] 294 withoutPlugApp := info.Apps["without-plug"] 295 c.Assert(plug, DeepEquals, &snap.PlugInfo{ 296 Snap: info, 297 Name: "network-client", 298 Interface: "network-client", 299 Apps: map[string]*snap.AppInfo{withPlugApp.Name: withPlugApp}, 300 }) 301 c.Assert(withPlugApp, DeepEquals, &snap.AppInfo{ 302 Snap: info, 303 Name: "with-plug", 304 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 305 }) 306 c.Assert(withoutPlugApp, DeepEquals, &snap.AppInfo{ 307 Snap: info, 308 Name: "without-plug", 309 Plugs: map[string]*snap.PlugInfo{}, 310 }) 311 } 312 313 func (s *YamlSuite) TestUnmarshalPlugsExplicitlyDefinedExplicitlyBoundToApps(c *C) { 314 // NOTE: yaml content cannot use tabs, indent the section with spaces. 315 info, err := snap.InfoFromSnapYaml([]byte(` 316 name: snap 317 plugs: 318 net: network-client 319 apps: 320 app: 321 plugs: ["net"] 322 `)) 323 c.Assert(err, IsNil) 324 c.Check(info.InstanceName(), Equals, "snap") 325 c.Check(info.Plugs, HasLen, 1) 326 c.Check(info.Slots, HasLen, 0) 327 c.Check(info.Apps, HasLen, 1) 328 plug := info.Plugs["net"] 329 app := info.Apps["app"] 330 c.Assert(plug, DeepEquals, &snap.PlugInfo{ 331 Snap: info, 332 Name: "net", 333 Interface: "network-client", 334 Apps: map[string]*snap.AppInfo{app.Name: app}, 335 }) 336 c.Assert(app, DeepEquals, &snap.AppInfo{ 337 Snap: info, 338 Name: "app", 339 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 340 }) 341 } 342 343 func (s *YamlSuite) TestUnmarshalPlugsImplicitlyDefinedExplicitlyBoundToApps(c *C) { 344 // NOTE: yaml content cannot use tabs, indent the section with spaces. 345 info, err := snap.InfoFromSnapYaml([]byte(` 346 name: snap 347 apps: 348 app: 349 plugs: ["network-client"] 350 `)) 351 c.Assert(err, IsNil) 352 c.Check(info.InstanceName(), Equals, "snap") 353 c.Check(info.Plugs, HasLen, 1) 354 c.Check(info.Slots, HasLen, 0) 355 c.Check(info.Apps, HasLen, 1) 356 plug := info.Plugs["network-client"] 357 app := info.Apps["app"] 358 c.Assert(plug, DeepEquals, &snap.PlugInfo{ 359 Snap: info, 360 Name: "network-client", 361 Interface: "network-client", 362 Apps: map[string]*snap.AppInfo{app.Name: app}, 363 }) 364 c.Assert(app, DeepEquals, &snap.AppInfo{ 365 Snap: info, 366 Name: "app", 367 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 368 }) 369 } 370 371 func (s *YamlSuite) TestUnmarshalPlugWithoutInterfaceName(c *C) { 372 // NOTE: yaml content cannot use tabs, indent the section with spaces. 373 info, err := snap.InfoFromSnapYaml([]byte(` 374 name: snap 375 plugs: 376 network-client: 377 ipv6-aware: true 378 `)) 379 c.Assert(err, IsNil) 380 c.Check(info.InstanceName(), Equals, "snap") 381 c.Check(info.Plugs, HasLen, 1) 382 c.Check(info.Slots, HasLen, 0) 383 c.Check(info.Apps, HasLen, 0) 384 c.Assert(info.Plugs["network-client"], DeepEquals, &snap.PlugInfo{ 385 Snap: info, 386 Name: "network-client", 387 Interface: "network-client", 388 Attrs: map[string]interface{}{"ipv6-aware": true}, 389 }) 390 } 391 392 func (s *YamlSuite) TestUnmarshalPlugWithLabel(c *C) { 393 // NOTE: yaml content cannot use tabs, indent the section with spaces. 394 info, err := snap.InfoFromSnapYaml([]byte(` 395 name: snap 396 plugs: 397 bool-file: 398 label: Disk I/O indicator 399 `)) 400 c.Assert(err, IsNil) 401 c.Check(info.InstanceName(), Equals, "snap") 402 c.Check(info.Plugs, HasLen, 1) 403 c.Check(info.Slots, HasLen, 0) 404 c.Check(info.Apps, HasLen, 0) 405 c.Assert(info.Plugs["bool-file"], DeepEquals, &snap.PlugInfo{ 406 Snap: info, 407 Name: "bool-file", 408 Interface: "bool-file", 409 Label: "Disk I/O indicator", 410 }) 411 } 412 413 func (s *YamlSuite) TestUnmarshalCorruptedPlugWithNonStringInterfaceName(c *C) { 414 // NOTE: yaml content cannot use tabs, indent the section with spaces. 415 _, err := snap.InfoFromSnapYaml([]byte(` 416 name: snap 417 plugs: 418 net: 419 interface: 1.0 420 ipv6-aware: true 421 `)) 422 c.Assert(err, ErrorMatches, `interface name on plug "net" is not a string \(found float64\)`) 423 } 424 425 func (s *YamlSuite) TestUnmarshalCorruptedPlugWithNonStringLabel(c *C) { 426 // NOTE: yaml content cannot use tabs, indent the section with spaces. 427 _, err := snap.InfoFromSnapYaml([]byte(` 428 name: snap 429 plugs: 430 bool-file: 431 label: 1.0 432 `)) 433 c.Assert(err, ErrorMatches, `label of plug "bool-file" is not a string \(found float64\)`) 434 } 435 436 func (s *YamlSuite) TestUnmarshalCorruptedPlugWithNonStringAttributes(c *C) { 437 // NOTE: yaml content cannot use tabs, indent the section with spaces. 438 _, err := snap.InfoFromSnapYaml([]byte(` 439 name: snap 440 plugs: 441 net: 442 1: ok 443 `)) 444 c.Assert(err, ErrorMatches, `plug "net" has attribute key that is not a string \(found int\)`) 445 } 446 447 func (s *YamlSuite) TestUnmarshalCorruptedPlugWithEmptyAttributeKey(c *C) { 448 // NOTE: yaml content cannot use tabs, indent the section with spaces. 449 _, err := snap.InfoFromSnapYaml([]byte(` 450 name: snap 451 plugs: 452 net: 453 "": ok 454 `)) 455 c.Assert(err, ErrorMatches, `plug "net" has an empty attribute key`) 456 } 457 458 func (s *YamlSuite) TestUnmarshalCorruptedPlugWithUnexpectedType(c *C) { 459 // NOTE: yaml content cannot use tabs, indent the section with spaces. 460 _, err := snap.InfoFromSnapYaml([]byte(` 461 name: snap 462 plugs: 463 net: 5 464 `)) 465 c.Assert(err, ErrorMatches, `plug "net" has malformed definition \(found int\)`) 466 } 467 468 func (s *YamlSuite) TestUnmarshalReservedPlugAttribute(c *C) { 469 // NOTE: yaml content cannot use tabs, indent the section with spaces. 470 _, err := snap.InfoFromSnapYaml([]byte(` 471 name: snap 472 plugs: 473 serial: 474 interface: serial-port 475 $baud-rate: [9600] 476 `)) 477 c.Assert(err, ErrorMatches, `plug "serial" uses reserved attribute "\$baud-rate"`) 478 } 479 480 func (s *YamlSuite) TestUnmarshalInvalidPlugAttribute(c *C) { 481 // NOTE: yaml content cannot use tabs, indent the section with spaces. 482 _, err := snap.InfoFromSnapYaml([]byte(` 483 name: snap 484 plugs: 485 serial: 486 interface: serial-port 487 foo: null 488 `)) 489 c.Assert(err, ErrorMatches, `attribute "foo" of plug \"serial\": invalid scalar:.*`) 490 } 491 492 func (s *YamlSuite) TestUnmarshalInvalidAttributeMapKey(c *C) { 493 // NOTE: yaml content cannot use tabs, indent the section with spaces. 494 _, err := snap.InfoFromSnapYaml([]byte(` 495 name: snap 496 plugs: 497 serial: 498 interface: serial-port 499 bar: 500 baz: 501 - 1: A 502 `)) 503 c.Assert(err, ErrorMatches, `attribute "bar" of plug \"serial\": non-string key: 1`) 504 } 505 506 // Tests focusing on slots 507 508 func (s *YamlSuite) TestUnmarshalStandaloneImplicitSlot(c *C) { 509 // NOTE: yaml content cannot use tabs, indent the section with spaces. 510 info, err := snap.InfoFromSnapYaml([]byte(` 511 name: snap 512 slots: 513 network-client: 514 `)) 515 c.Assert(err, IsNil) 516 c.Check(info.InstanceName(), Equals, "snap") 517 c.Check(info.Plugs, HasLen, 0) 518 c.Check(info.Slots, HasLen, 1) 519 c.Assert(info.Slots["network-client"], DeepEquals, &snap.SlotInfo{ 520 Snap: info, 521 Name: "network-client", 522 Interface: "network-client", 523 }) 524 } 525 526 func (s *YamlSuite) TestUnmarshalStandaloneAbbreviatedSlot(c *C) { 527 // NOTE: yaml content cannot use tabs, indent the section with spaces. 528 info, err := snap.InfoFromSnapYaml([]byte(` 529 name: snap 530 slots: 531 net: network-client 532 `)) 533 c.Assert(err, IsNil) 534 c.Check(info.InstanceName(), Equals, "snap") 535 c.Check(info.Plugs, HasLen, 0) 536 c.Check(info.Slots, HasLen, 1) 537 c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{ 538 Snap: info, 539 Name: "net", 540 Interface: "network-client", 541 }) 542 } 543 544 func (s *YamlSuite) TestUnmarshalStandaloneMinimalisticSlot(c *C) { 545 // NOTE: yaml content cannot use tabs, indent the section with spaces. 546 info, err := snap.InfoFromSnapYaml([]byte(` 547 name: snap 548 slots: 549 net: 550 interface: network-client 551 `)) 552 c.Assert(err, IsNil) 553 c.Check(info.InstanceName(), Equals, "snap") 554 c.Check(info.Plugs, HasLen, 0) 555 c.Check(info.Slots, HasLen, 1) 556 c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{ 557 Snap: info, 558 Name: "net", 559 Interface: "network-client", 560 }) 561 } 562 563 func (s *YamlSuite) TestUnmarshalStandaloneCompleteSlot(c *C) { 564 // NOTE: yaml content cannot use tabs, indent the section with spaces. 565 info, err := snap.InfoFromSnapYaml([]byte(` 566 name: snap 567 slots: 568 net: 569 interface: network-client 570 ipv6-aware: true 571 `)) 572 c.Assert(err, IsNil) 573 c.Check(info.InstanceName(), Equals, "snap") 574 c.Check(info.Plugs, HasLen, 0) 575 c.Check(info.Slots, HasLen, 1) 576 c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{ 577 Snap: info, 578 Name: "net", 579 Interface: "network-client", 580 Attrs: map[string]interface{}{"ipv6-aware": true}, 581 }) 582 } 583 584 func (s *YamlSuite) TestUnmarshalStandaloneSlotWithIntAndListAndMap(c *C) { 585 // NOTE: yaml content cannot use tabs, indent the section with spaces. 586 info, err := snap.InfoFromSnapYaml([]byte(` 587 name: snap 588 slots: 589 iface: 590 interface: complex 591 i: 3 592 l: [1,2] 593 m: 594 a: "A" 595 `)) 596 c.Assert(err, IsNil) 597 c.Check(info.InstanceName(), Equals, "snap") 598 c.Check(info.Plugs, HasLen, 0) 599 c.Check(info.Slots, HasLen, 1) 600 c.Assert(info.Slots["iface"], DeepEquals, &snap.SlotInfo{ 601 Snap: info, 602 Name: "iface", 603 Interface: "complex", 604 Attrs: map[string]interface{}{ 605 "i": int64(3), 606 "l": []interface{}{int64(1), int64(2)}, 607 "m": map[string]interface{}{"a": "A"}, 608 }, 609 }) 610 } 611 612 func (s *YamlSuite) TestUnmarshalLastSlotDefinitionWins(c *C) { 613 // NOTE: yaml content cannot use tabs, indent the section with spaces. 614 info, err := snap.InfoFromSnapYaml([]byte(` 615 name: snap 616 slots: 617 net: 618 interface: network-client 619 attr: 1 620 net: 621 interface: network-client 622 attr: 2 623 `)) 624 c.Assert(err, IsNil) 625 c.Check(info.InstanceName(), Equals, "snap") 626 c.Check(info.Plugs, HasLen, 0) 627 c.Check(info.Slots, HasLen, 1) 628 c.Assert(info.Slots["net"], DeepEquals, &snap.SlotInfo{ 629 Snap: info, 630 Name: "net", 631 Interface: "network-client", 632 Attrs: map[string]interface{}{"attr": int64(2)}, 633 }) 634 } 635 636 func (s *YamlSuite) TestUnmarshalSlotsExplicitlyDefinedImplicitlyBoundToApps(c *C) { 637 // NOTE: yaml content cannot use tabs, indent the section with spaces. 638 info, err := snap.InfoFromSnapYaml([]byte(` 639 name: snap 640 slots: 641 network-client: 642 apps: 643 app: 644 `)) 645 c.Assert(err, IsNil) 646 c.Check(info.InstanceName(), Equals, "snap") 647 c.Check(info.Plugs, HasLen, 0) 648 c.Check(info.Slots, HasLen, 1) 649 c.Check(info.Apps, HasLen, 1) 650 slot := info.Slots["network-client"] 651 app := info.Apps["app"] 652 c.Assert(slot, DeepEquals, &snap.SlotInfo{ 653 Snap: info, 654 Name: "network-client", 655 Interface: "network-client", 656 Apps: map[string]*snap.AppInfo{app.Name: app}, 657 }) 658 c.Assert(app, DeepEquals, &snap.AppInfo{ 659 Snap: info, 660 Name: "app", 661 Slots: map[string]*snap.SlotInfo{slot.Name: slot}, 662 }) 663 } 664 665 func (s *YamlSuite) TestUnmarshalSlotsExplicitlyDefinedExplicitlyBoundToApps(c *C) { 666 // NOTE: yaml content cannot use tabs, indent the section with spaces. 667 info, err := snap.InfoFromSnapYaml([]byte(` 668 name: snap 669 slots: 670 net: network-client 671 apps: 672 app: 673 slots: ["net"] 674 `)) 675 c.Assert(err, IsNil) 676 c.Check(info.InstanceName(), Equals, "snap") 677 c.Check(info.Plugs, HasLen, 0) 678 c.Check(info.Slots, HasLen, 1) 679 c.Check(info.Apps, HasLen, 1) 680 slot := info.Slots["net"] 681 app := info.Apps["app"] 682 c.Assert(slot, DeepEquals, &snap.SlotInfo{ 683 Snap: info, 684 Name: "net", 685 Interface: "network-client", 686 Apps: map[string]*snap.AppInfo{app.Name: app}, 687 }) 688 c.Assert(app, DeepEquals, &snap.AppInfo{ 689 Snap: info, 690 Name: "app", 691 Slots: map[string]*snap.SlotInfo{slot.Name: slot}, 692 }) 693 } 694 695 func (s *YamlSuite) TestUnmarshalSlotsImplicitlyDefinedExplicitlyBoundToApps(c *C) { 696 // NOTE: yaml content cannot use tabs, indent the section with spaces. 697 info, err := snap.InfoFromSnapYaml([]byte(` 698 name: snap 699 apps: 700 app: 701 slots: ["network-client"] 702 `)) 703 c.Assert(err, IsNil) 704 c.Check(info.InstanceName(), Equals, "snap") 705 c.Check(info.Plugs, HasLen, 0) 706 c.Check(info.Slots, HasLen, 1) 707 c.Check(info.Apps, HasLen, 1) 708 slot := info.Slots["network-client"] 709 app := info.Apps["app"] 710 c.Assert(slot, DeepEquals, &snap.SlotInfo{ 711 Snap: info, 712 Name: "network-client", 713 Interface: "network-client", 714 Apps: map[string]*snap.AppInfo{app.Name: app}, 715 }) 716 c.Assert(app, DeepEquals, &snap.AppInfo{ 717 Snap: info, 718 Name: "app", 719 Slots: map[string]*snap.SlotInfo{slot.Name: slot}, 720 }) 721 } 722 723 func (s *YamlSuite) TestUnmarshalSlotWithoutInterfaceName(c *C) { 724 // NOTE: yaml content cannot use tabs, indent the section with spaces. 725 info, err := snap.InfoFromSnapYaml([]byte(` 726 name: snap 727 slots: 728 network-client: 729 ipv6-aware: true 730 `)) 731 c.Assert(err, IsNil) 732 c.Check(info.InstanceName(), Equals, "snap") 733 c.Check(info.Plugs, HasLen, 0) 734 c.Check(info.Slots, HasLen, 1) 735 c.Check(info.Apps, HasLen, 0) 736 c.Assert(info.Slots["network-client"], DeepEquals, &snap.SlotInfo{ 737 Snap: info, 738 Name: "network-client", 739 Interface: "network-client", 740 Attrs: map[string]interface{}{"ipv6-aware": true}, 741 }) 742 } 743 744 func (s *YamlSuite) TestUnmarshalSlotWithLabel(c *C) { 745 // NOTE: yaml content cannot use tabs, indent the section with spaces. 746 info, err := snap.InfoFromSnapYaml([]byte(` 747 name: snap 748 slots: 749 led0: 750 interface: bool-file 751 label: Front panel LED (red) 752 `)) 753 c.Assert(err, IsNil) 754 c.Check(info.InstanceName(), Equals, "snap") 755 c.Check(info.Plugs, HasLen, 0) 756 c.Check(info.Slots, HasLen, 1) 757 c.Check(info.Apps, HasLen, 0) 758 c.Assert(info.Slots["led0"], DeepEquals, &snap.SlotInfo{ 759 Snap: info, 760 Name: "led0", 761 Interface: "bool-file", 762 Label: "Front panel LED (red)", 763 }) 764 } 765 766 func (s *YamlSuite) TestUnmarshalGlobalSlotsBindToHooks(c *C) { 767 // NOTE: yaml content cannot use tabs, indent the section with spaces. 768 info, err := snap.InfoFromSnapYaml([]byte(` 769 name: snap 770 slots: 771 test-slot: 772 hooks: 773 test-hook: 774 `)) 775 c.Assert(err, IsNil) 776 c.Check(info.InstanceName(), Equals, "snap") 777 c.Check(info.Plugs, HasLen, 0) 778 c.Check(info.Slots, HasLen, 1) 779 c.Check(info.Apps, HasLen, 0) 780 c.Check(info.Hooks, HasLen, 1) 781 782 slot, ok := info.Slots["test-slot"] 783 c.Assert(ok, Equals, true, Commentf("Expected slots to include 'test-slot'")) 784 hook, ok := info.Hooks["test-hook"] 785 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 786 787 c.Check(slot, DeepEquals, &snap.SlotInfo{ 788 Snap: info, 789 Name: "test-slot", 790 Interface: "test-slot", 791 Hooks: map[string]*snap.HookInfo{hook.Name: hook}, 792 }) 793 c.Check(hook, DeepEquals, &snap.HookInfo{ 794 Snap: info, 795 Name: "test-hook", 796 Slots: map[string]*snap.SlotInfo{slot.Name: slot}, 797 798 Explicit: true, 799 }) 800 } 801 802 func (s *YamlSuite) TestUnmarshalHookWithSlot(c *C) { 803 // NOTE: yaml content cannot use tabs, indent the section with spaces. 804 info, err := snap.InfoFromSnapYaml([]byte(` 805 name: snap 806 hooks: 807 test-hook: 808 slots: [test-slot] 809 `)) 810 c.Assert(err, IsNil) 811 c.Check(info.InstanceName(), Equals, "snap") 812 c.Check(info.Plugs, HasLen, 0) 813 c.Check(info.Slots, HasLen, 1) 814 c.Check(info.Apps, HasLen, 0) 815 c.Check(info.Hooks, HasLen, 1) 816 817 slot, ok := info.Slots["test-slot"] 818 c.Assert(ok, Equals, true, Commentf("Expected slots to include 'test-slot'")) 819 hook, ok := info.Hooks["test-hook"] 820 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 821 822 c.Check(slot, DeepEquals, &snap.SlotInfo{ 823 Snap: info, 824 Name: "test-slot", 825 Interface: "test-slot", 826 Hooks: map[string]*snap.HookInfo{hook.Name: hook}, 827 }) 828 c.Check(hook, DeepEquals, &snap.HookInfo{ 829 Snap: info, 830 Name: "test-hook", 831 Slots: map[string]*snap.SlotInfo{slot.Name: slot}, 832 833 Explicit: true, 834 }) 835 } 836 837 func (s *YamlSuite) TestUnmarshalCorruptedSlotWithNonStringInterfaceName(c *C) { 838 // NOTE: yaml content cannot use tabs, indent the section with spaces. 839 _, err := snap.InfoFromSnapYaml([]byte(` 840 name: snap 841 slots: 842 net: 843 interface: 1.0 844 ipv6-aware: true 845 `)) 846 c.Assert(err, ErrorMatches, `interface name on slot "net" is not a string \(found float64\)`) 847 } 848 849 func (s *YamlSuite) TestUnmarshalCorruptedSlotWithNonStringLabel(c *C) { 850 // NOTE: yaml content cannot use tabs, indent the section with spaces. 851 _, err := snap.InfoFromSnapYaml([]byte(` 852 name: snap 853 slots: 854 bool-file: 855 label: 1.0 856 `)) 857 c.Assert(err, ErrorMatches, `label of slot "bool-file" is not a string \(found float64\)`) 858 } 859 860 func (s *YamlSuite) TestUnmarshalCorruptedSlotWithNonStringAttributes(c *C) { 861 // NOTE: yaml content cannot use tabs, indent the section with spaces. 862 _, err := snap.InfoFromSnapYaml([]byte(` 863 name: snap 864 slots: 865 net: 866 1: ok 867 `)) 868 c.Assert(err, ErrorMatches, `slot "net" has attribute key that is not a string \(found int\)`) 869 } 870 871 func (s *YamlSuite) TestUnmarshalCorruptedSlotWithEmptyAttributeKey(c *C) { 872 // NOTE: yaml content cannot use tabs, indent the section with spaces. 873 _, err := snap.InfoFromSnapYaml([]byte(` 874 name: snap 875 slots: 876 net: 877 "": ok 878 `)) 879 c.Assert(err, ErrorMatches, `slot "net" has an empty attribute key`) 880 } 881 882 func (s *YamlSuite) TestUnmarshalCorruptedSlotWithUnexpectedType(c *C) { 883 // NOTE: yaml content cannot use tabs, indent the section with spaces. 884 _, err := snap.InfoFromSnapYaml([]byte(` 885 name: snap 886 slots: 887 net: 5 888 `)) 889 c.Assert(err, ErrorMatches, `slot "net" has malformed definition \(found int\)`) 890 } 891 892 func (s *YamlSuite) TestUnmarshalReservedSlotAttribute(c *C) { 893 // NOTE: yaml content cannot use tabs, indent the section with spaces. 894 _, err := snap.InfoFromSnapYaml([]byte(` 895 name: snap 896 slots: 897 serial: 898 interface: serial-port 899 $baud-rate: [9600] 900 `)) 901 c.Assert(err, ErrorMatches, `slot "serial" uses reserved attribute "\$baud-rate"`) 902 } 903 904 func (s *YamlSuite) TestUnmarshalInvalidSlotAttribute(c *C) { 905 // NOTE: yaml content cannot use tabs, indent the section with spaces. 906 _, err := snap.InfoFromSnapYaml([]byte(` 907 name: snap 908 slots: 909 serial: 910 interface: serial-port 911 foo: null 912 `)) 913 c.Assert(err, ErrorMatches, `attribute "foo" of slot \"serial\": invalid scalar:.*`) 914 } 915 916 func (s *YamlSuite) TestUnmarshalHook(c *C) { 917 // NOTE: yaml content cannot use tabs, indent the section with spaces. 918 info, err := snap.InfoFromSnapYaml([]byte(` 919 name: snap 920 hooks: 921 test-hook: 922 `)) 923 c.Assert(err, IsNil) 924 c.Check(info.InstanceName(), Equals, "snap") 925 c.Check(info.Plugs, HasLen, 0) 926 c.Check(info.Slots, HasLen, 0) 927 c.Check(info.Apps, HasLen, 0) 928 c.Check(info.Hooks, HasLen, 1) 929 930 hook, ok := info.Hooks["test-hook"] 931 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 932 933 c.Check(hook, DeepEquals, &snap.HookInfo{ 934 Snap: info, 935 Name: "test-hook", 936 Plugs: nil, 937 938 Explicit: true, 939 }) 940 } 941 942 func (s *YamlSuite) TestUnmarshalUnsupportedHook(c *C) { 943 s.restore() 944 hookType := snap.NewHookType(regexp.MustCompile("not-test-hook")) 945 s.restore = snap.MockSupportedHookTypes([]*snap.HookType{hookType}) 946 947 // NOTE: yaml content cannot use tabs, indent the section with spaces. 948 info, err := snap.InfoFromSnapYaml([]byte(` 949 name: snap 950 hooks: 951 test-hook: 952 `)) 953 c.Assert(err, IsNil) 954 c.Check(info.InstanceName(), Equals, "snap") 955 c.Check(info.Plugs, HasLen, 0) 956 c.Check(info.Slots, HasLen, 0) 957 c.Check(info.Apps, HasLen, 0) 958 c.Check(info.Hooks, HasLen, 0, Commentf("Expected no hooks to be loaded")) 959 } 960 961 func (s *YamlSuite) TestUnmarshalHookFiltersOutUnsupportedHooks(c *C) { 962 s.restore() 963 hookType := snap.NewHookType(regexp.MustCompile("test-.*")) 964 s.restore = snap.MockSupportedHookTypes([]*snap.HookType{hookType}) 965 966 // NOTE: yaml content cannot use tabs, indent the section with spaces. 967 info, err := snap.InfoFromSnapYaml([]byte(` 968 name: snap 969 hooks: 970 test-hook: 971 foo-hook: 972 `)) 973 c.Assert(err, IsNil) 974 c.Check(info.InstanceName(), Equals, "snap") 975 c.Check(info.Plugs, HasLen, 0) 976 c.Check(info.Slots, HasLen, 0) 977 c.Check(info.Apps, HasLen, 0) 978 c.Check(info.Hooks, HasLen, 1) 979 980 hook, ok := info.Hooks["test-hook"] 981 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 982 983 c.Check(hook, DeepEquals, &snap.HookInfo{ 984 Snap: info, 985 Name: "test-hook", 986 Plugs: nil, 987 988 Explicit: true, 989 }) 990 } 991 992 func (s *YamlSuite) TestUnmarshalHookWithPlug(c *C) { 993 // NOTE: yaml content cannot use tabs, indent the section with spaces. 994 info, err := snap.InfoFromSnapYaml([]byte(` 995 name: snap 996 hooks: 997 test-hook: 998 plugs: [test-plug] 999 `)) 1000 c.Assert(err, IsNil) 1001 c.Check(info.InstanceName(), Equals, "snap") 1002 c.Check(info.Plugs, HasLen, 1) 1003 c.Check(info.Slots, HasLen, 0) 1004 c.Check(info.Apps, HasLen, 0) 1005 c.Check(info.Hooks, HasLen, 1) 1006 1007 plug, ok := info.Plugs["test-plug"] 1008 c.Assert(ok, Equals, true, Commentf("Expected plugs to include 'test-plug'")) 1009 hook, ok := info.Hooks["test-hook"] 1010 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 1011 1012 c.Check(plug, DeepEquals, &snap.PlugInfo{ 1013 Snap: info, 1014 Name: "test-plug", 1015 Interface: "test-plug", 1016 Hooks: map[string]*snap.HookInfo{hook.Name: hook}, 1017 }) 1018 c.Check(hook, DeepEquals, &snap.HookInfo{ 1019 Snap: info, 1020 Name: "test-hook", 1021 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 1022 1023 Explicit: true, 1024 }) 1025 } 1026 1027 func (s *YamlSuite) TestUnmarshalGlobalPlugsBindToHooks(c *C) { 1028 // NOTE: yaml content cannot use tabs, indent the section with spaces. 1029 info, err := snap.InfoFromSnapYaml([]byte(` 1030 name: snap 1031 plugs: 1032 test-plug: 1033 hooks: 1034 test-hook: 1035 `)) 1036 c.Assert(err, IsNil) 1037 c.Check(info.InstanceName(), Equals, "snap") 1038 c.Check(info.Plugs, HasLen, 1) 1039 c.Check(info.Slots, HasLen, 0) 1040 c.Check(info.Apps, HasLen, 0) 1041 c.Check(info.Hooks, HasLen, 1) 1042 1043 plug, ok := info.Plugs["test-plug"] 1044 c.Assert(ok, Equals, true, Commentf("Expected plugs to include 'test-plug'")) 1045 hook, ok := info.Hooks["test-hook"] 1046 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 1047 1048 c.Check(plug, DeepEquals, &snap.PlugInfo{ 1049 Snap: info, 1050 Name: "test-plug", 1051 Interface: "test-plug", 1052 Hooks: map[string]*snap.HookInfo{hook.Name: hook}, 1053 }) 1054 c.Check(hook, DeepEquals, &snap.HookInfo{ 1055 Snap: info, 1056 Name: "test-hook", 1057 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 1058 1059 Explicit: true, 1060 }) 1061 } 1062 1063 func (s *YamlSuite) TestUnmarshalGlobalPlugBoundToOneHook(c *C) { 1064 // NOTE: yaml content cannot use tabs, indent the section with spaces. 1065 info, err := snap.InfoFromSnapYaml([]byte(` 1066 name: snap 1067 plugs: 1068 test-plug: 1069 hooks: 1070 with-plug: 1071 plugs: [test-plug] 1072 without-plug: 1073 `)) 1074 c.Assert(err, IsNil) 1075 c.Check(info.InstanceName(), Equals, "snap") 1076 c.Check(info.Plugs, HasLen, 1) 1077 c.Check(info.Slots, HasLen, 0) 1078 c.Check(info.Apps, HasLen, 0) 1079 c.Check(info.Hooks, HasLen, 2) 1080 1081 plug := info.Plugs["test-plug"] 1082 withPlugHook := info.Hooks["with-plug"] 1083 withoutPlugHook := info.Hooks["without-plug"] 1084 c.Assert(plug, DeepEquals, &snap.PlugInfo{ 1085 Snap: info, 1086 Name: "test-plug", 1087 Interface: "test-plug", 1088 Hooks: map[string]*snap.HookInfo{withPlugHook.Name: withPlugHook}, 1089 }) 1090 c.Assert(withPlugHook, DeepEquals, &snap.HookInfo{ 1091 Snap: info, 1092 Name: "with-plug", 1093 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 1094 1095 Explicit: true, 1096 }) 1097 c.Assert(withoutPlugHook, DeepEquals, &snap.HookInfo{ 1098 Snap: info, 1099 Name: "without-plug", 1100 Plugs: map[string]*snap.PlugInfo{}, 1101 1102 Explicit: true, 1103 }) 1104 } 1105 1106 func (s *YamlSuite) TestUnmarshalExplicitGlobalPlugBoundToHook(c *C) { 1107 // NOTE: yaml content cannot use tabs, indent the section with spaces. 1108 info, err := snap.InfoFromSnapYaml([]byte(` 1109 name: snap 1110 plugs: 1111 test-plug: test-interface 1112 hooks: 1113 test-hook: 1114 plugs: ["test-plug"] 1115 `)) 1116 c.Assert(err, IsNil) 1117 c.Check(info.InstanceName(), Equals, "snap") 1118 c.Check(info.Plugs, HasLen, 1) 1119 c.Check(info.Slots, HasLen, 0) 1120 c.Check(info.Apps, HasLen, 0) 1121 c.Check(info.Hooks, HasLen, 1) 1122 1123 plug, ok := info.Plugs["test-plug"] 1124 c.Assert(ok, Equals, true, Commentf("Expected plugs to include 'test-plug'")) 1125 hook, ok := info.Hooks["test-hook"] 1126 c.Assert(ok, Equals, true, Commentf("Expected hooks to include 'test-hook'")) 1127 1128 c.Check(plug, DeepEquals, &snap.PlugInfo{ 1129 Snap: info, 1130 Name: "test-plug", 1131 Interface: "test-interface", 1132 Hooks: map[string]*snap.HookInfo{hook.Name: hook}, 1133 }) 1134 c.Check(hook, DeepEquals, &snap.HookInfo{ 1135 Snap: info, 1136 Name: "test-hook", 1137 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 1138 1139 Explicit: true, 1140 }) 1141 } 1142 1143 func (s *YamlSuite) TestUnmarshalGlobalPlugBoundToHookNotApp(c *C) { 1144 // NOTE: yaml content cannot use tabs, indent the section with spaces. 1145 info, err := snap.InfoFromSnapYaml([]byte(` 1146 name: snap 1147 plugs: 1148 test-plug: 1149 hooks: 1150 test-hook: 1151 plugs: [test-plug] 1152 apps: 1153 test-app: 1154 `)) 1155 c.Assert(err, IsNil) 1156 c.Check(info.InstanceName(), Equals, "snap") 1157 c.Check(info.Plugs, HasLen, 1) 1158 c.Check(info.Slots, HasLen, 0) 1159 c.Check(info.Apps, HasLen, 1) 1160 c.Check(info.Hooks, HasLen, 1) 1161 1162 plug := info.Plugs["test-plug"] 1163 hook := info.Hooks["test-hook"] 1164 app := info.Apps["test-app"] 1165 c.Assert(plug, DeepEquals, &snap.PlugInfo{ 1166 Snap: info, 1167 Name: "test-plug", 1168 Interface: "test-plug", 1169 Apps: map[string]*snap.AppInfo{}, 1170 Hooks: map[string]*snap.HookInfo{hook.Name: hook}, 1171 }) 1172 c.Assert(hook, DeepEquals, &snap.HookInfo{ 1173 Snap: info, 1174 Name: "test-hook", 1175 Plugs: map[string]*snap.PlugInfo{plug.Name: plug}, 1176 1177 Explicit: true, 1178 }) 1179 c.Assert(app, DeepEquals, &snap.AppInfo{ 1180 Snap: info, 1181 Name: "test-app", 1182 Plugs: map[string]*snap.PlugInfo{}, 1183 }) 1184 } 1185 1186 func (s *YamlSuite) TestUnmarshalComplexExample(c *C) { 1187 // NOTE: yaml content cannot use tabs, indent the section with spaces. 1188 info, err := snap.InfoFromSnapYaml([]byte(` 1189 name: foo 1190 version: 1.2 1191 title: Foo 1192 summary: foo app 1193 type: app 1194 epoch: 1* 1195 confinement: devmode 1196 license: GPL-3.0 1197 description: | 1198 Foo provides useful services 1199 apps: 1200 daemon: 1201 command: foo --daemon 1202 plugs: [network, network-bind] 1203 slots: [foo-socket-slot] 1204 foo: 1205 command: fooctl 1206 plugs: [foo-socket-plug] 1207 hooks: 1208 test-hook: 1209 plugs: [foo-socket-plug] 1210 slots: [foo-socket-slot] 1211 plugs: 1212 foo-socket-plug: 1213 interface: socket 1214 # $protocol: foo 1215 logging: 1216 interface: syslog 1217 slots: 1218 foo-socket-slot: 1219 interface: socket 1220 path: $SNAP_DATA/socket 1221 protocol: foo 1222 tracing: 1223 interface: ptrace 1224 `)) 1225 c.Assert(err, IsNil) 1226 c.Check(info.InstanceName(), Equals, "foo") 1227 c.Check(info.Version, Equals, "1.2") 1228 c.Check(info.GetType(), Equals, snap.TypeApp) 1229 c.Check(info.Epoch, DeepEquals, snap.E("1*")) 1230 c.Check(info.Confinement, Equals, snap.DevModeConfinement) 1231 c.Check(info.Title(), Equals, "Foo") 1232 c.Check(info.Summary(), Equals, "foo app") 1233 c.Check(info.Description(), Equals, "Foo provides useful services\n") 1234 c.Check(info.Apps, HasLen, 2) 1235 c.Check(info.Plugs, HasLen, 4) 1236 c.Check(info.Slots, HasLen, 2) 1237 // these don't come from snap.yaml 1238 c.Check(info.Publisher, Equals, snap.StoreAccount{}) 1239 c.Check(info.Channel, Equals, "") 1240 c.Check(info.License, Equals, "GPL-3.0") 1241 1242 app1 := info.Apps["daemon"] 1243 app2 := info.Apps["foo"] 1244 hook := info.Hooks["test-hook"] 1245 plug1 := info.Plugs["network"] 1246 plug2 := info.Plugs["network-bind"] 1247 plug3 := info.Plugs["foo-socket-plug"] 1248 plug4 := info.Plugs["logging"] 1249 slot1 := info.Slots["foo-socket-slot"] 1250 slot2 := info.Slots["tracing"] 1251 1252 // app1 ("daemon") has three plugs ("network", "network-bind", "logging") 1253 // and two slots ("foo-socket", "tracing"). The slot "tracing" and plug 1254 // "logging" are global, everything else is app-bound. 1255 1256 c.Assert(app1, Not(IsNil)) 1257 c.Check(app1.Snap, Equals, info) 1258 c.Check(app1.Name, Equals, "daemon") 1259 c.Check(app1.Command, Equals, "foo --daemon") 1260 c.Check(app1.Plugs, DeepEquals, map[string]*snap.PlugInfo{ 1261 plug1.Name: plug1, plug2.Name: plug2, plug4.Name: plug4}) 1262 c.Check(app1.Slots, DeepEquals, map[string]*snap.SlotInfo{ 1263 slot1.Name: slot1, slot2.Name: slot2}) 1264 1265 // app2 ("foo") has two plugs ("foo-socket", "logging") and one slot 1266 // ("tracing"). The slot "tracing" and plug "logging" are global while 1267 // "foo-socket" is app-bound. 1268 1269 c.Assert(app2, Not(IsNil)) 1270 c.Check(app2.Snap, Equals, info) 1271 c.Check(app2.Name, Equals, "foo") 1272 c.Check(app2.Command, Equals, "fooctl") 1273 c.Check(app2.Plugs, DeepEquals, map[string]*snap.PlugInfo{ 1274 plug3.Name: plug3, plug4.Name: plug4}) 1275 c.Check(app2.Slots, DeepEquals, map[string]*snap.SlotInfo{ 1276 slot2.Name: slot2}) 1277 1278 // hook1 has two plugs ("foo-socket", "logging") and two slots ("foo-socket", "tracing"). 1279 // The plug "logging" and slot "tracing" are global while "foo-socket" is hook-bound. 1280 1281 c.Assert(hook, NotNil) 1282 c.Check(hook.Snap, Equals, info) 1283 c.Check(hook.Name, Equals, "test-hook") 1284 c.Check(hook.Plugs, DeepEquals, map[string]*snap.PlugInfo{ 1285 plug3.Name: plug3, plug4.Name: plug4}) 1286 c.Check(hook.Slots, DeepEquals, map[string]*snap.SlotInfo{ 1287 slot1.Name: slot1, slot2.Name: slot2}) 1288 1289 // plug1 ("network") is implicitly defined and app-bound to "daemon" 1290 1291 c.Assert(plug1, Not(IsNil)) 1292 c.Check(plug1.Snap, Equals, info) 1293 c.Check(plug1.Name, Equals, "network") 1294 c.Check(plug1.Interface, Equals, "network") 1295 c.Check(plug1.Attrs, HasLen, 0) 1296 c.Check(plug1.Label, Equals, "") 1297 c.Check(plug1.Apps, DeepEquals, map[string]*snap.AppInfo{app1.Name: app1}) 1298 1299 // plug2 ("network-bind") is implicitly defined and app-bound to "daemon" 1300 1301 c.Assert(plug2, Not(IsNil)) 1302 c.Check(plug2.Snap, Equals, info) 1303 c.Check(plug2.Name, Equals, "network-bind") 1304 c.Check(plug2.Interface, Equals, "network-bind") 1305 c.Check(plug2.Attrs, HasLen, 0) 1306 c.Check(plug2.Label, Equals, "") 1307 c.Check(plug2.Apps, DeepEquals, map[string]*snap.AppInfo{app1.Name: app1}) 1308 1309 // plug3 ("foo-socket") is app-bound to "foo" 1310 1311 c.Assert(plug3, Not(IsNil)) 1312 c.Check(plug3.Snap, Equals, info) 1313 c.Check(plug3.Name, Equals, "foo-socket-plug") 1314 c.Check(plug3.Interface, Equals, "socket") 1315 c.Check(plug3.Attrs, HasLen, 0) 1316 c.Check(plug3.Label, Equals, "") 1317 c.Check(plug3.Apps, DeepEquals, map[string]*snap.AppInfo{app2.Name: app2}) 1318 1319 // plug4 ("logging") is global so it is bound to all apps 1320 1321 c.Assert(plug4, Not(IsNil)) 1322 c.Check(plug4.Snap, Equals, info) 1323 c.Check(plug4.Name, Equals, "logging") 1324 c.Check(plug4.Interface, Equals, "syslog") 1325 c.Check(plug4.Attrs, HasLen, 0) 1326 c.Check(plug4.Label, Equals, "") 1327 c.Check(plug4.Apps, DeepEquals, map[string]*snap.AppInfo{ 1328 app1.Name: app1, app2.Name: app2}) 1329 1330 // slot1 ("foo-socket") is app-bound to "daemon" 1331 1332 c.Assert(slot1, Not(IsNil)) 1333 c.Check(slot1.Snap, Equals, info) 1334 c.Check(slot1.Name, Equals, "foo-socket-slot") 1335 c.Check(slot1.Interface, Equals, "socket") 1336 c.Check(slot1.Attrs, DeepEquals, map[string]interface{}{ 1337 "protocol": "foo", "path": "$SNAP_DATA/socket"}) 1338 c.Check(slot1.Label, Equals, "") 1339 c.Check(slot1.Apps, DeepEquals, map[string]*snap.AppInfo{app1.Name: app1}) 1340 1341 // slot2 ("tracing") is global so it is bound to all apps 1342 1343 c.Assert(slot2, Not(IsNil)) 1344 c.Check(slot2.Snap, Equals, info) 1345 c.Check(slot2.Name, Equals, "tracing") 1346 c.Check(slot2.Interface, Equals, "ptrace") 1347 c.Check(slot2.Attrs, HasLen, 0) 1348 c.Check(slot2.Label, Equals, "") 1349 c.Check(slot2.Apps, DeepEquals, map[string]*snap.AppInfo{ 1350 app1.Name: app1, app2.Name: app2}) 1351 } 1352 1353 // type and architectures 1354 1355 func (s *YamlSuite) TestSnapYamlTypeDefault(c *C) { 1356 y := []byte(`name: binary 1357 version: 1.0 1358 `) 1359 info, err := snap.InfoFromSnapYaml(y) 1360 c.Assert(err, IsNil) 1361 c.Assert(info.GetType(), Equals, snap.TypeApp) 1362 } 1363 1364 func (s *YamlSuite) TestSnapYamlEpochDefault(c *C) { 1365 y := []byte(`name: binary 1366 version: 1.0 1367 `) 1368 info, err := snap.InfoFromSnapYaml(y) 1369 c.Assert(err, IsNil) 1370 c.Assert(info.Epoch, DeepEquals, snap.E("0")) 1371 } 1372 1373 func (s *YamlSuite) TestSnapYamlConfinementDefault(c *C) { 1374 y := []byte(`name: binary 1375 version: 1.0 1376 `) 1377 info, err := snap.InfoFromSnapYaml(y) 1378 c.Assert(err, IsNil) 1379 c.Assert(info.Confinement, Equals, snap.StrictConfinement) 1380 } 1381 1382 func (s *YamlSuite) TestSnapYamlMultipleArchitecturesParsing(c *C) { 1383 y := []byte(`name: binary 1384 version: 1.0 1385 architectures: [i386, armhf] 1386 `) 1387 info, err := snap.InfoFromSnapYaml(y) 1388 c.Assert(err, IsNil) 1389 c.Assert(info.Architectures, DeepEquals, []string{"i386", "armhf"}) 1390 } 1391 1392 func (s *YamlSuite) TestSnapYamlSingleArchitecturesParsing(c *C) { 1393 y := []byte(`name: binary 1394 version: 1.0 1395 architectures: [i386] 1396 `) 1397 info, err := snap.InfoFromSnapYaml(y) 1398 c.Assert(err, IsNil) 1399 c.Assert(info.Architectures, DeepEquals, []string{"i386"}) 1400 } 1401 1402 func (s *YamlSuite) TestSnapYamlAssumesParsing(c *C) { 1403 y := []byte(`name: binary 1404 version: 1.0 1405 assumes: [feature2, feature1] 1406 `) 1407 info, err := snap.InfoFromSnapYaml(y) 1408 c.Assert(err, IsNil) 1409 c.Assert(info.Assumes, DeepEquals, []string{"feature1", "feature2"}) 1410 } 1411 1412 func (s *YamlSuite) TestSnapYamlNoArchitecturesParsing(c *C) { 1413 y := []byte(`name: binary 1414 version: 1.0 1415 `) 1416 info, err := snap.InfoFromSnapYaml(y) 1417 c.Assert(err, IsNil) 1418 c.Assert(info.Architectures, DeepEquals, []string{"all"}) 1419 } 1420 1421 func (s *YamlSuite) TestSnapYamlBadArchitectureParsing(c *C) { 1422 y := []byte(`name: binary 1423 version: 1.0 1424 architectures: 1425 armhf: 1426 no 1427 `) 1428 _, err := snap.InfoFromSnapYaml(y) 1429 c.Assert(err, NotNil) 1430 } 1431 1432 // apps 1433 1434 func (s *YamlSuite) TestSimpleAppExample(c *C) { 1435 y := []byte(`name: wat 1436 version: 42 1437 apps: 1438 cm: 1439 command: cm0 1440 `) 1441 info, err := snap.InfoFromSnapYaml(y) 1442 c.Assert(err, IsNil) 1443 c.Check(info.Apps, DeepEquals, map[string]*snap.AppInfo{ 1444 "cm": { 1445 Snap: info, 1446 Name: "cm", 1447 Command: "cm0", 1448 }, 1449 }) 1450 } 1451 1452 func (s *YamlSuite) TestDaemonEverythingExample(c *C) { 1453 y := []byte(`name: wat 1454 version: 42 1455 apps: 1456 svc: 1457 command: svc1 1458 description: svc one 1459 stop-timeout: 25s 1460 start-timeout: 42m 1461 daemon: forking 1462 stop-command: stop-cmd 1463 post-stop-command: post-stop-cmd 1464 restart-condition: on-abnormal 1465 bus-name: busName 1466 sockets: 1467 sock1: 1468 listen-stream: $SNAP_DATA/sock1.socket 1469 socket-mode: 0666 1470 `) 1471 info, err := snap.InfoFromSnapYaml(y) 1472 c.Assert(err, IsNil) 1473 1474 app := snap.AppInfo{ 1475 Snap: info, 1476 Name: "svc", 1477 Command: "svc1", 1478 Daemon: "forking", 1479 RestartCond: snap.RestartOnAbnormal, 1480 StopTimeout: timeout.Timeout(25 * time.Second), 1481 StartTimeout: timeout.Timeout(42 * time.Minute), 1482 StopCommand: "stop-cmd", 1483 PostStopCommand: "post-stop-cmd", 1484 BusName: "busName", 1485 Sockets: map[string]*snap.SocketInfo{}, 1486 } 1487 1488 app.Sockets["sock1"] = &snap.SocketInfo{ 1489 App: &app, 1490 Name: "sock1", 1491 ListenStream: "$SNAP_DATA/sock1.socket", 1492 SocketMode: 0666, 1493 } 1494 1495 c.Check(info.Apps, DeepEquals, map[string]*snap.AppInfo{"svc": &app}) 1496 } 1497 1498 func (s *YamlSuite) TestDaemonListenStreamAsInteger(c *C) { 1499 y := []byte(`name: wat 1500 version: 42 1501 apps: 1502 svc: 1503 command: svc 1504 sockets: 1505 sock: 1506 listen-stream: 8080 1507 `) 1508 info, err := snap.InfoFromSnapYaml(y) 1509 c.Assert(err, IsNil) 1510 1511 app := snap.AppInfo{ 1512 Snap: info, 1513 Name: "svc", 1514 Command: "svc", 1515 Sockets: map[string]*snap.SocketInfo{}, 1516 } 1517 1518 app.Sockets["sock"] = &snap.SocketInfo{ 1519 App: &app, 1520 Name: "sock", 1521 ListenStream: "8080", 1522 } 1523 1524 c.Check(info.Apps, DeepEquals, map[string]*snap.AppInfo{ 1525 "svc": &app, 1526 }) 1527 } 1528 1529 func (s *YamlSuite) TestDaemonInvalidSocketMode(c *C) { 1530 y := []byte(`name: wat 1531 version: 42 1532 apps: 1533 svc: 1534 command: svc 1535 sockets: 1536 sock: 1537 listen-stream: 8080 1538 socket-mode: asdfasdf 1539 `) 1540 _, err := snap.InfoFromSnapYaml(y) 1541 c.Check(err.Error(), Equals, "cannot parse snap.yaml: yaml: unmarshal errors:\n"+ 1542 " line 9: cannot unmarshal !!str `asdfasdf` into os.FileMode") 1543 } 1544 1545 func (s *YamlSuite) TestSnapYamlGlobalEnvironment(c *C) { 1546 y := []byte(` 1547 name: foo 1548 version: 1.0 1549 environment: 1550 foo: bar 1551 baz: boom 1552 `) 1553 info, err := snap.InfoFromSnapYaml(y) 1554 c.Assert(err, IsNil) 1555 c.Assert(info.Environment, DeepEquals, *strutil.NewOrderedMap("foo", "bar", "baz", "boom")) 1556 } 1557 1558 func (s *YamlSuite) TestSnapYamlPerAppEnvironment(c *C) { 1559 y := []byte(` 1560 name: foo 1561 version: 1.0 1562 apps: 1563 foo: 1564 environment: 1565 k1: v1 1566 k2: v2 1567 `) 1568 info, err := snap.InfoFromSnapYaml(y) 1569 c.Assert(err, IsNil) 1570 c.Assert(info.Apps["foo"].Environment, DeepEquals, *strutil.NewOrderedMap("k1", "v1", "k2", "v2")) 1571 } 1572 1573 func (s *YamlSuite) TestSnapYamlPerHookEnvironment(c *C) { 1574 y := []byte(` 1575 name: foo 1576 version: 1.0 1577 hooks: 1578 foo: 1579 environment: 1580 k1: v1 1581 k2: v2 1582 `) 1583 info, err := snap.InfoFromSnapYaml(y) 1584 c.Assert(err, IsNil) 1585 c.Assert(info.Hooks["foo"].Environment, DeepEquals, *strutil.NewOrderedMap("k1", "v1", "k2", "v2")) 1586 } 1587 1588 // classic confinement 1589 func (s *YamlSuite) TestClassicConfinement(c *C) { 1590 y := []byte(` 1591 name: foo 1592 confinement: classic 1593 `) 1594 info, err := snap.InfoFromSnapYaml(y) 1595 c.Assert(err, IsNil) 1596 c.Assert(info.Confinement, Equals, snap.ClassicConfinement) 1597 } 1598 1599 func (s *YamlSuite) TestSnapYamlAliases(c *C) { 1600 y := []byte(` 1601 name: foo 1602 version: 1.0 1603 apps: 1604 foo: 1605 aliases: [foo] 1606 bar: 1607 aliases: [bar, bar1] 1608 `) 1609 info, err := snap.InfoFromSnapYaml(y) 1610 c.Assert(err, IsNil) 1611 1612 c.Check(info.Apps["foo"].LegacyAliases, DeepEquals, []string{"foo"}) 1613 c.Check(info.Apps["bar"].LegacyAliases, DeepEquals, []string{"bar", "bar1"}) 1614 1615 c.Check(info.LegacyAliases, DeepEquals, map[string]*snap.AppInfo{ 1616 "foo": info.Apps["foo"], 1617 "bar": info.Apps["bar"], 1618 "bar1": info.Apps["bar"], 1619 }) 1620 } 1621 1622 func (s *YamlSuite) TestSnapYamlAliasesConflict(c *C) { 1623 y := []byte(` 1624 name: foo 1625 version: 1.0 1626 apps: 1627 foo: 1628 aliases: [bar] 1629 bar: 1630 aliases: [bar] 1631 `) 1632 _, err := snap.InfoFromSnapYaml(y) 1633 c.Assert(err, ErrorMatches, `cannot set "bar" as alias for both ("foo" and "bar"|"bar" and "foo")`) 1634 } 1635 1636 func (s *YamlSuite) TestSnapYamlAppStartOrder(c *C) { 1637 y := []byte(`name: wat 1638 version: 42 1639 apps: 1640 foo: 1641 after: [bar, zed] 1642 bar: 1643 before: [foo] 1644 baz: 1645 after: [foo] 1646 zed: 1647 1648 `) 1649 info, err := snap.InfoFromSnapYaml(y) 1650 c.Assert(err, IsNil) 1651 1652 c.Check(info.Apps, DeepEquals, map[string]*snap.AppInfo{ 1653 "foo": { 1654 Snap: info, 1655 Name: "foo", 1656 After: []string{"bar", "zed"}, 1657 }, 1658 "bar": { 1659 Snap: info, 1660 Name: "bar", 1661 Before: []string{"foo"}, 1662 }, 1663 "baz": { 1664 Snap: info, 1665 Name: "baz", 1666 After: []string{"foo"}, 1667 }, 1668 "zed": { 1669 Snap: info, 1670 Name: "zed", 1671 }, 1672 }) 1673 } 1674 1675 func (s *YamlSuite) TestSnapYamlWatchdog(c *C) { 1676 y := []byte(` 1677 name: foo 1678 version: 1.0 1679 apps: 1680 foo: 1681 watchdog-timeout: 12s 1682 `) 1683 info, err := snap.InfoFromSnapYaml(y) 1684 c.Assert(err, IsNil) 1685 1686 c.Check(info.Apps["foo"].WatchdogTimeout, Equals, timeout.Timeout(12*time.Second)) 1687 } 1688 1689 func (s *YamlSuite) TestLayout(c *C) { 1690 y := []byte(` 1691 name: foo 1692 version: 1.0 1693 layout: 1694 /usr/share/foo: 1695 bind: $SNAP/usr/share/foo 1696 /usr/share/bar: 1697 symlink: $SNAP/usr/share/bar 1698 /etc/froz: 1699 bind-file: $SNAP/etc/froz 1700 `) 1701 info, err := snap.InfoFromSnapYaml(y) 1702 c.Assert(err, IsNil) 1703 c.Assert(info.Layout["/usr/share/foo"], DeepEquals, &snap.Layout{ 1704 Snap: info, 1705 Path: "/usr/share/foo", 1706 Bind: "$SNAP/usr/share/foo", 1707 User: "root", 1708 Group: "root", 1709 Mode: 0755, 1710 }) 1711 c.Assert(info.Layout["/usr/share/bar"], DeepEquals, &snap.Layout{ 1712 Snap: info, 1713 Path: "/usr/share/bar", 1714 Symlink: "$SNAP/usr/share/bar", 1715 User: "root", 1716 Group: "root", 1717 Mode: 0755, 1718 }) 1719 c.Assert(info.Layout["/etc/froz"], DeepEquals, &snap.Layout{ 1720 Snap: info, 1721 Path: "/etc/froz", 1722 BindFile: "$SNAP/etc/froz", 1723 User: "root", 1724 Group: "root", 1725 Mode: 0755, 1726 }) 1727 } 1728 1729 func (s *YamlSuite) TestLayoutsWithTypo(c *C) { 1730 y := []byte(` 1731 name: foo 1732 version: 1.0 1733 layouts: 1734 /usr/share/foo: 1735 bind: $SNAP/usr/share/foo 1736 `) 1737 info, err := snap.InfoFromSnapYaml(y) 1738 c.Assert(err, ErrorMatches, `cannot parse snap.yaml: typo detected: use singular "layout" instead of plural "layouts"`) 1739 c.Assert(info, IsNil) 1740 } 1741 1742 func (s *YamlSuite) TestSnapYamlAppTimer(c *C) { 1743 y := []byte(`name: wat 1744 version: 42 1745 apps: 1746 foo: 1747 daemon: oneshot 1748 timer: mon,10:00-12:00 1749 1750 `) 1751 info, err := snap.InfoFromSnapYaml(y) 1752 c.Assert(err, IsNil) 1753 app := info.Apps["foo"] 1754 c.Check(app.Timer, DeepEquals, &snap.TimerInfo{App: app, Timer: "mon,10:00-12:00"}) 1755 } 1756 1757 func (s *YamlSuite) TestSnapYamlAppAutostart(c *C) { 1758 yAutostart := []byte(`name: wat 1759 version: 42 1760 apps: 1761 foo: 1762 command: bin/foo 1763 autostart: foo.desktop 1764 1765 `) 1766 info, err := snap.InfoFromSnapYaml(yAutostart) 1767 c.Assert(err, IsNil) 1768 app := info.Apps["foo"] 1769 c.Check(app.Autostart, Equals, "foo.desktop") 1770 1771 yNoAutostart := []byte(`name: wat 1772 version: 42 1773 apps: 1774 foo: 1775 command: bin/foo 1776 1777 `) 1778 info, err = snap.InfoFromSnapYaml(yNoAutostart) 1779 c.Assert(err, IsNil) 1780 app = info.Apps["foo"] 1781 c.Check(app.Autostart, Equals, "") 1782 } 1783 1784 func (s *YamlSuite) TestSnapYamlAppCommonID(c *C) { 1785 yAutostart := []byte(`name: wat 1786 version: 42 1787 apps: 1788 foo: 1789 command: bin/foo 1790 common-id: org.foo 1791 bar: 1792 command: bin/foo 1793 common-id: org.bar 1794 baz: 1795 command: bin/foo 1796 1797 `) 1798 info, err := snap.InfoFromSnapYaml(yAutostart) 1799 c.Assert(err, IsNil) 1800 c.Check(info.Apps["foo"].CommonID, Equals, "org.foo") 1801 c.Check(info.Apps["bar"].CommonID, Equals, "org.bar") 1802 c.Check(info.Apps["baz"].CommonID, Equals, "") 1803 c.Assert(info.CommonIDs, HasLen, 2) 1804 c.Assert((info.CommonIDs[0] == "org.foo" && info.CommonIDs[1] == "org.bar") || 1805 (info.CommonIDs[1] == "org.foo" && info.CommonIDs[0] == "org.bar"), 1806 Equals, 1807 true) 1808 } 1809 1810 func (s *YamlSuite) TestSnapYamlCommandChain(c *C) { 1811 yAutostart := []byte(`name: wat 1812 version: 42 1813 apps: 1814 foo: 1815 command: bin/foo 1816 command-chain: [chain1, chain2] 1817 hooks: 1818 configure: 1819 command-chain: [hookchain1, hookchain2] 1820 `) 1821 info, err := snap.InfoFromSnapYaml(yAutostart) 1822 c.Assert(err, IsNil) 1823 app := info.Apps["foo"] 1824 c.Check(app.CommandChain, DeepEquals, []string{"chain1", "chain2"}) 1825 hook := info.Hooks["configure"] 1826 c.Check(hook.CommandChain, DeepEquals, []string{"hookchain1", "hookchain2"}) 1827 } 1828 1829 func (s *YamlSuite) TestSnapYamlRestartDelay(c *C) { 1830 yAutostart := []byte(`name: wat 1831 version: 42 1832 apps: 1833 foo: 1834 command: bin/foo 1835 daemon: simple 1836 restart-delay: 12s 1837 `) 1838 info, err := snap.InfoFromSnapYaml(yAutostart) 1839 c.Assert(err, IsNil) 1840 app := info.Apps["foo"] 1841 c.Assert(app, NotNil) 1842 c.Check(app.RestartDelay, Equals, timeout.Timeout(12*time.Second)) 1843 } 1844 1845 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsing(c *C) { 1846 y := []byte(`name: binary 1847 version: 1.0 1848 system-usernames: 1849 foo: shared 1850 bar: 1851 scope: external 1852 baz: 1853 scope: private 1854 attr1: norf 1855 attr2: corge 1856 attr3: "" 1857 `) 1858 info, err := snap.InfoFromSnapYaml(y) 1859 c.Assert(err, IsNil) 1860 c.Check(info.SystemUsernames, HasLen, 3) 1861 c.Assert(info.SystemUsernames["foo"], DeepEquals, &snap.SystemUsernameInfo{ 1862 Name: "foo", 1863 Scope: "shared", 1864 }) 1865 c.Assert(info.SystemUsernames["bar"], DeepEquals, &snap.SystemUsernameInfo{ 1866 Name: "bar", 1867 Scope: "external", 1868 }) 1869 c.Assert(info.SystemUsernames["baz"], DeepEquals, &snap.SystemUsernameInfo{ 1870 Name: "baz", 1871 Scope: "private", 1872 Attrs: map[string]interface{}{ 1873 "attr1": "norf", 1874 "attr2": "corge", 1875 "attr3": "", 1876 }, 1877 }) 1878 } 1879 1880 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadType(c *C) { 1881 y := []byte(`name: binary 1882 version: 1.0 1883 system-usernames: 1884 a: true 1885 `) 1886 info, err := snap.InfoFromSnapYaml(y) 1887 c.Assert(err, ErrorMatches, `system username "a" has malformed definition \(found bool\)`) 1888 c.Assert(info, IsNil) 1889 } 1890 1891 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadValue(c *C) { 1892 y := []byte(`name: binary 1893 version: 1.0 1894 system-usernames: 1895 a: [b, c] 1896 `) 1897 info, err := snap.InfoFromSnapYaml(y) 1898 c.Assert(err, ErrorMatches, `system username "a" has malformed definition \(found \[\]interface {}\)`) 1899 c.Assert(info, IsNil) 1900 } 1901 1902 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadKeyEmpty(c *C) { 1903 y := []byte(`name: binary 1904 version: 1.0 1905 system-usernames: 1906 "": shared 1907 `) 1908 _, err := snap.InfoFromSnapYaml(y) 1909 c.Assert(err, ErrorMatches, `system username cannot be empty`) 1910 } 1911 1912 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadKeyList(c *C) { 1913 y := []byte(`name: binary 1914 version: 1.0 1915 system-usernames: 1916 - foo: shared 1917 `) 1918 _, err := snap.InfoFromSnapYaml(y) 1919 c.Assert(err, ErrorMatches, `(?m)cannot parse snap.yaml:.*`) 1920 } 1921 1922 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadValueEmpty(c *C) { 1923 y := []byte(`name: binary 1924 version: 1.0 1925 system-usernames: 1926 a: "" 1927 `) 1928 _, err := snap.InfoFromSnapYaml(y) 1929 c.Assert(err, ErrorMatches, `system username "a" does not specify a scope`) 1930 } 1931 1932 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadValueNull(c *C) { 1933 y := []byte(`name: binary 1934 version: 1.0 1935 system-usernames: 1936 a: null 1937 `) 1938 _, err := snap.InfoFromSnapYaml(y) 1939 c.Assert(err, ErrorMatches, `system username "a" does not specify a scope`) 1940 } 1941 1942 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadAttrKeyEmpty(c *C) { 1943 y := []byte(`name: binary 1944 version: 1.0 1945 system-usernames: 1946 foo: 1947 scope: shared 1948 "": bar 1949 `) 1950 _, err := snap.InfoFromSnapYaml(y) 1951 c.Assert(err, ErrorMatches, `system username "foo" has an empty attribute key`) 1952 } 1953 1954 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadAttrKeyNonString(c *C) { 1955 y := []byte(`name: binary 1956 version: 1.0 1957 system-usernames: 1958 foo: 1959 scope: shared 1960 1: bar 1961 `) 1962 _, err := snap.InfoFromSnapYaml(y) 1963 c.Assert(err, ErrorMatches, `system username "foo" has attribute key that is not a string \(found int\)`) 1964 } 1965 1966 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadAttrValue(c *C) { 1967 y := []byte(`name: binary 1968 version: 1.0 1969 system-usernames: 1970 foo: 1971 scope: shared 1972 bar: null 1973 `) 1974 _, err := snap.InfoFromSnapYaml(y) 1975 c.Assert(err, ErrorMatches, `attribute "bar" of system username "foo": invalid scalar:.*`) 1976 } 1977 1978 func (s *YamlSuite) TestSnapYamlSystemUsernamesParsingBadScopeNonString(c *C) { 1979 y := []byte(`name: binary 1980 version: 1.0 1981 system-usernames: 1982 foo: 1983 scope: 10 1984 `) 1985 _, err := snap.InfoFromSnapYaml(y) 1986 c.Assert(err, ErrorMatches, `scope on system username "foo" is not a string \(found int\)`) 1987 }