github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/core_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 interfaces_test 21 22 import ( 23 "fmt" 24 "testing" 25 26 . "gopkg.in/check.v1" 27 28 "github.com/snapcore/snapd/interfaces" 29 // TODO: eliminate this import and just use interfaces import directly 30 . "github.com/snapcore/snapd/interfaces" 31 "github.com/snapcore/snapd/interfaces/builtin" 32 "github.com/snapcore/snapd/interfaces/ifacetest" 33 "github.com/snapcore/snapd/snap" 34 "github.com/snapcore/snapd/snap/snaptest" 35 "github.com/snapcore/snapd/testutil" 36 ) 37 38 func Test(t *testing.T) { 39 TestingT(t) 40 } 41 42 type CoreSuite struct { 43 testutil.BaseTest 44 } 45 46 var _ = Suite(&CoreSuite{}) 47 48 func (s *CoreSuite) SetUpTest(c *C) { 49 s.BaseTest.SetUpTest(c) 50 s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 51 } 52 53 func (s *CoreSuite) TearDownTest(c *C) { 54 s.BaseTest.TearDownTest(c) 55 } 56 57 func (s *CoreSuite) TestValidateDBusBusName(c *C) { 58 // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names 59 validNames := []string{ 60 "a.b", "a.b.c", "a.b1", "a.b1.c2d", 61 "a_a.b", "a_a.b_b.c_c", "a_a.b_b1", "a_a.b_b1.c_c2d_d", 62 "a-a.b", "a-a.b-b.c-c", "a-a.b-b1", "a-a.b-b1.c-c2d-d", 63 } 64 for _, name := range validNames { 65 err := ValidateDBusBusName(name) 66 c.Assert(err, IsNil) 67 } 68 69 invalidNames := []string{ 70 // must not start with ':' 71 ":a.b", 72 // only from [A-Z][a-z][0-9]_- 73 "@.a", 74 // elements may not start with number 75 "0.a", 76 "a.0a", 77 // must have more than one element 78 "a", 79 "a_a", 80 "a-a", 81 // element must not begin with '.' 82 ".a", 83 // each element must be at least 1 character 84 "a.", 85 "a..b", 86 ".a.b", 87 "a.b.", 88 } 89 for _, name := range invalidNames { 90 err := ValidateDBusBusName(name) 91 c.Assert(err, ErrorMatches, `invalid DBus bus name: ".*"`) 92 } 93 94 // must not be empty 95 err := ValidateDBusBusName("") 96 c.Assert(err, ErrorMatches, `DBus bus name must be set`) 97 98 // must not exceed maximum length 99 longName := make([]byte, 256) 100 for i := range longName { 101 longName[i] = 'b' 102 } 103 // make it look otherwise valid (a.bbbb...) 104 longName[0] = 'a' 105 longName[1] = '.' 106 err = ValidateDBusBusName(string(longName)) 107 c.Assert(err, ErrorMatches, `DBus bus name is too long \(must be <= 255\)`) 108 } 109 110 // PlugRef.String works as expected 111 func (s *CoreSuite) TestPlugRefString(c *C) { 112 ref := PlugRef{Snap: "snap", Name: "plug"} 113 c.Check(ref.String(), Equals, "snap:plug") 114 refPtr := &PlugRef{Snap: "snap", Name: "plug"} 115 c.Check(refPtr.String(), Equals, "snap:plug") 116 } 117 118 // SlotRef.String works as expected 119 func (s *CoreSuite) TestSlotRefString(c *C) { 120 ref := SlotRef{Snap: "snap", Name: "slot"} 121 c.Check(ref.String(), Equals, "snap:slot") 122 refPtr := &SlotRef{Snap: "snap", Name: "slot"} 123 c.Check(refPtr.String(), Equals, "snap:slot") 124 } 125 126 // ConnRef.ID works as expected 127 func (s *CoreSuite) TestConnRefID(c *C) { 128 conn := &ConnRef{ 129 PlugRef: PlugRef{Snap: "consumer", Name: "plug"}, 130 SlotRef: SlotRef{Snap: "producer", Name: "slot"}, 131 } 132 c.Check(conn.ID(), Equals, "consumer:plug producer:slot") 133 } 134 135 // ParseConnRef works as expected 136 func (s *CoreSuite) TestParseConnRef(c *C) { 137 ref, err := ParseConnRef("consumer:plug producer:slot") 138 c.Assert(err, IsNil) 139 c.Check(ref, DeepEquals, &ConnRef{ 140 PlugRef: PlugRef{Snap: "consumer", Name: "plug"}, 141 SlotRef: SlotRef{Snap: "producer", Name: "slot"}, 142 }) 143 _, err = ParseConnRef("garbage") 144 c.Assert(err, ErrorMatches, `malformed connection identifier: "garbage"`) 145 _, err = ParseConnRef("snap:plug:garbage snap:slot") 146 c.Assert(err, ErrorMatches, `malformed connection identifier: ".*"`) 147 _, err = ParseConnRef("snap:plug snap:slot:garbage") 148 c.Assert(err, ErrorMatches, `malformed connection identifier: ".*"`) 149 } 150 151 type simpleIface struct { 152 name string 153 } 154 155 func (si simpleIface) Name() string { return si.name } 156 func (si simpleIface) AutoConnect(plug *snap.PlugInfo, slot *snap.SlotInfo) bool { return false } 157 158 func (s *CoreSuite) TestByName(c *C) { 159 // setup a mock interface using builtin - this will also trigger init() in 160 // builtin package which set ByName to a real implementation 161 r := builtin.MockInterface(simpleIface{name: "mock-network"}) 162 defer r() 163 164 _, err := interfaces.ByName("no-such-interface") 165 c.Assert(err, ErrorMatches, "interface \"no-such-interface\" not found") 166 167 iface, err := interfaces.ByName("mock-network") 168 c.Assert(err, IsNil) 169 c.Assert(iface.Name(), Equals, "mock-network") 170 } 171 172 type serviceSnippetIface struct { 173 simpleIface 174 175 sanitizerErr error 176 177 snips []string 178 } 179 180 func (ssi serviceSnippetIface) BeforePreparePlug(plug *snap.PlugInfo) error { 181 return ssi.sanitizerErr 182 } 183 184 func (ssi serviceSnippetIface) ServicePermanentPlug(plug *snap.PlugInfo) []string { 185 return ssi.snips 186 } 187 188 func (s *CoreSuite) TestPermanentPlugServiceSnippets(c *C) { 189 // setup a mock interface using builtin - this will also trigger init() in 190 // builtin package which set ByName to a real implementation 191 ssi := serviceSnippetIface{ 192 simpleIface: simpleIface{name: "mock-service-snippets"}, 193 snips: []string{"foo1", "foo2"}, 194 } 195 r := builtin.MockInterface(ssi) 196 defer r() 197 198 iface, err := interfaces.ByName("mock-service-snippets") 199 c.Assert(err, IsNil) 200 c.Assert(iface.Name(), Equals, "mock-service-snippets") 201 202 info := snaptest.MockInfo(c, ` 203 name: snap 204 version: 0 205 plugs: 206 plug: 207 interface: mock-service-snippets 208 `, nil) 209 plug := info.Plugs["plug"] 210 211 snips, err := interfaces.PermanentPlugServiceSnippets(iface, plug) 212 c.Assert(err, IsNil) 213 c.Assert(snips, DeepEquals, []string{"foo1", "foo2"}) 214 } 215 216 func (s *CoreSuite) TestPermanentPlugServiceSnippetsSanitizesPlugs(c *C) { 217 // setup a mock interface using builtin - this will also trigger init() in 218 // builtin package which set ByName to a real implementation 219 ssi := serviceSnippetIface{ 220 simpleIface: simpleIface{name: "unclean-service-snippets"}, 221 sanitizerErr: fmt.Errorf("cannot sanitize: foo"), 222 } 223 r := builtin.MockInterface(ssi) 224 defer r() 225 226 info := snaptest.MockInfo(c, ` 227 name: snap 228 version: 0 229 plugs: 230 plug: 231 interface: unclean-service-snippets 232 `, nil) 233 plug := info.Plugs["plug"] 234 235 iface, err := interfaces.ByName("unclean-service-snippets") 236 c.Assert(err, IsNil) 237 c.Assert(iface.Name(), Equals, "unclean-service-snippets") 238 239 _, err = interfaces.PermanentPlugServiceSnippets(iface, plug) 240 c.Assert(err, ErrorMatches, "cannot sanitize: foo") 241 } 242 243 func (s *CoreSuite) TestSanitizePlug(c *C) { 244 info := snaptest.MockInfo(c, ` 245 name: snap 246 version: 0 247 plugs: 248 plug: 249 interface: iface 250 `, nil) 251 plug := info.Plugs["plug"] 252 c.Assert(BeforePreparePlug(&ifacetest.TestInterface{ 253 InterfaceName: "iface", 254 }, plug), IsNil) 255 c.Assert(BeforePreparePlug(&ifacetest.TestInterface{ 256 InterfaceName: "iface", 257 BeforePreparePlugCallback: func(plug *snap.PlugInfo) error { return fmt.Errorf("broken") }, 258 }, plug), ErrorMatches, "broken") 259 c.Assert(BeforePreparePlug(&ifacetest.TestInterface{ 260 InterfaceName: "other", 261 }, plug), ErrorMatches, `cannot sanitize plug "snap:plug" \(interface "iface"\) using interface "other"`) 262 } 263 264 func (s *CoreSuite) TestSanitizeSlot(c *C) { 265 info := snaptest.MockInfo(c, ` 266 name: snap 267 version: 0 268 slots: 269 slot: 270 interface: iface 271 `, nil) 272 slot := info.Slots["slot"] 273 c.Assert(BeforePrepareSlot(&ifacetest.TestInterface{ 274 InterfaceName: "iface", 275 }, slot), IsNil) 276 c.Assert(BeforePrepareSlot(&ifacetest.TestInterface{ 277 InterfaceName: "iface", 278 BeforePrepareSlotCallback: func(slot *snap.SlotInfo) error { return fmt.Errorf("broken") }, 279 }, slot), ErrorMatches, "broken") 280 c.Assert(BeforePrepareSlot(&ifacetest.TestInterface{ 281 InterfaceName: "other", 282 }, slot), ErrorMatches, `cannot sanitize slot "snap:slot" \(interface "iface"\) using interface "other"`) 283 }