github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/connection_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2017 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 21 22 import ( 23 . "gopkg.in/check.v1" 24 25 "github.com/snapcore/snapd/interfaces/utils" 26 "github.com/snapcore/snapd/snap" 27 "github.com/snapcore/snapd/snap/snaptest" 28 "github.com/snapcore/snapd/testutil" 29 ) 30 31 type connSuite struct { 32 testutil.BaseTest 33 plug *snap.PlugInfo 34 slot *snap.SlotInfo 35 } 36 37 var _ = Suite(&connSuite{}) 38 39 func (s *connSuite) SetUpTest(c *C) { 40 s.BaseTest.SetUpTest(c) 41 s.BaseTest.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 42 consumer := snaptest.MockInfo(c, ` 43 name: consumer 44 version: 0 45 apps: 46 app: 47 plugs: 48 plug: 49 interface: interface 50 attr: value 51 complex: 52 c: d 53 `, nil) 54 s.plug = consumer.Plugs["plug"] 55 producer := snaptest.MockInfo(c, ` 56 name: producer 57 version: 0 58 apps: 59 app: 60 slots: 61 slot: 62 interface: interface 63 attr: value 64 number: 100 65 complex: 66 a: b 67 `, nil) 68 s.slot = producer.Slots["slot"] 69 } 70 71 func (s *connSuite) TearDownTest(c *C) { 72 s.BaseTest.TearDownTest(c) 73 } 74 75 // Make sure ConnectedPlug,ConnectedSlot, PlugInfo, SlotInfo implement Attrer. 76 var _ Attrer = (*ConnectedPlug)(nil) 77 var _ Attrer = (*ConnectedSlot)(nil) 78 var _ Attrer = (*snap.PlugInfo)(nil) 79 var _ Attrer = (*snap.SlotInfo)(nil) 80 81 func (s *connSuite) TestStaticSlotAttrs(c *C) { 82 slot := NewConnectedSlot(s.slot, nil, nil) 83 c.Assert(slot, NotNil) 84 85 var val string 86 var intVal int 87 c.Assert(slot.StaticAttr("unknown", &val), ErrorMatches, `snap "producer" does not have attribute "unknown" for interface "interface"`) 88 89 attrs := slot.StaticAttrs() 90 c.Assert(attrs, DeepEquals, map[string]interface{}{ 91 "attr": "value", 92 "number": int64(100), 93 "complex": map[string]interface{}{"a": "b"}, 94 }) 95 slot.StaticAttr("attr", &val) 96 c.Assert(val, Equals, "value") 97 98 c.Assert(slot.StaticAttr("unknown", &val), ErrorMatches, `snap "producer" does not have attribute "unknown" for interface "interface"`) 99 c.Check(slot.StaticAttr("attr", &intVal), ErrorMatches, `snap "producer" has interface "interface" with invalid value type string for "attr" attribute: \*int`) 100 c.Check(slot.StaticAttr("attr", val), ErrorMatches, `internal error: cannot get "attr" attribute of interface "interface" with non-pointer value`) 101 102 // static attributes passed via args take precedence over slot.Attrs 103 slot2 := NewConnectedSlot(s.slot, map[string]interface{}{"foo": "bar"}, nil) 104 slot2.StaticAttr("foo", &val) 105 c.Assert(val, Equals, "bar") 106 } 107 108 func (s *connSuite) TestSlotRef(c *C) { 109 slot := NewConnectedSlot(s.slot, nil, nil) 110 c.Assert(slot, NotNil) 111 c.Assert(*slot.Ref(), DeepEquals, SlotRef{Snap: "producer", Name: "slot"}) 112 } 113 114 func (s *connSuite) TestPlugRef(c *C) { 115 plug := NewConnectedPlug(s.plug, nil, nil) 116 c.Assert(plug, NotNil) 117 c.Assert(*plug.Ref(), DeepEquals, PlugRef{Snap: "consumer", Name: "plug"}) 118 } 119 120 func (s *connSuite) TestStaticPlugAttrs(c *C) { 121 plug := NewConnectedPlug(s.plug, nil, nil) 122 c.Assert(plug, NotNil) 123 124 var val string 125 var intVal int 126 c.Assert(plug.StaticAttr("unknown", &val), ErrorMatches, `snap "consumer" does not have attribute "unknown" for interface "interface"`) 127 128 attrs := plug.StaticAttrs() 129 c.Assert(attrs, DeepEquals, map[string]interface{}{ 130 "attr": "value", 131 "complex": map[string]interface{}{"c": "d"}, 132 }) 133 plug.StaticAttr("attr", &val) 134 c.Assert(val, Equals, "value") 135 136 c.Assert(plug.StaticAttr("unknown", &val), ErrorMatches, `snap "consumer" does not have attribute "unknown" for interface "interface"`) 137 c.Check(plug.StaticAttr("attr", &intVal), ErrorMatches, `snap "consumer" has interface "interface" with invalid value type string for "attr" attribute: \*int`) 138 c.Check(plug.StaticAttr("attr", val), ErrorMatches, `internal error: cannot get "attr" attribute of interface "interface" with non-pointer value`) 139 140 // static attributes passed via args take precedence over plug.Attrs 141 plug2 := NewConnectedPlug(s.plug, map[string]interface{}{"foo": "bar"}, nil) 142 plug2.StaticAttr("foo", &val) 143 c.Assert(val, Equals, "bar") 144 } 145 146 func (s *connSuite) TestDynamicSlotAttrs(c *C) { 147 attrs := map[string]interface{}{ 148 "foo": "bar", 149 "number": int(100), 150 } 151 slot := NewConnectedSlot(s.slot, nil, attrs) 152 c.Assert(slot, NotNil) 153 154 var strVal string 155 var intVal int64 156 var mapVal map[string]interface{} 157 158 c.Assert(slot.Attr("foo", &strVal), IsNil) 159 c.Assert(strVal, Equals, "bar") 160 161 c.Assert(slot.Attr("attr", &strVal), IsNil) 162 c.Assert(strVal, Equals, "value") 163 164 c.Assert(slot.Attr("number", &intVal), IsNil) 165 c.Assert(intVal, Equals, int64(100)) 166 167 err := slot.SetAttr("other", map[string]interface{}{"number-two": int(222)}) 168 c.Assert(err, IsNil) 169 c.Assert(slot.Attr("other", &mapVal), IsNil) 170 num := mapVal["number-two"] 171 c.Assert(num, Equals, int64(222)) 172 173 c.Check(slot.Attr("unknown", &strVal), ErrorMatches, `snap "producer" does not have attribute "unknown" for interface "interface"`) 174 c.Check(slot.Attr("foo", &intVal), ErrorMatches, `snap "producer" has interface "interface" with invalid value type string for "foo" attribute: \*int64`) 175 c.Check(slot.Attr("number", intVal), ErrorMatches, `internal error: cannot get "number" attribute of interface "interface" with non-pointer value`) 176 } 177 178 func (s *connSuite) TestDottedPathSlot(c *C) { 179 attrs := map[string]interface{}{ 180 "nested": map[string]interface{}{ 181 "foo": "bar", 182 }, 183 } 184 var strVal string 185 186 slot := NewConnectedSlot(s.slot, nil, attrs) 187 c.Assert(slot, NotNil) 188 189 // static attribute complex.a 190 c.Assert(slot.Attr("complex.a", &strVal), IsNil) 191 c.Assert(strVal, Equals, "b") 192 193 v, ok := slot.Lookup("complex.a") 194 c.Assert(ok, Equals, true) 195 c.Assert(v, Equals, "b") 196 197 // dynamic attribute nested.foo 198 c.Assert(slot.Attr("nested.foo", &strVal), IsNil) 199 c.Assert(strVal, Equals, "bar") 200 201 v, ok = slot.Lookup("nested.foo") 202 c.Assert(ok, Equals, true) 203 c.Assert(v, Equals, "bar") 204 205 _, ok = slot.Lookup("..") 206 c.Assert(ok, Equals, false) 207 } 208 209 func (s *connSuite) TestDottedPathPlug(c *C) { 210 attrs := map[string]interface{}{ 211 "a": "b", 212 "nested": map[string]interface{}{ 213 "foo": "bar", 214 }, 215 } 216 var strVal string 217 218 plug := NewConnectedPlug(s.plug, nil, attrs) 219 c.Assert(plug, NotNil) 220 221 v, ok := plug.Lookup("a") 222 c.Assert(ok, Equals, true) 223 c.Assert(v, Equals, "b") 224 225 // static attribute complex.c 226 c.Assert(plug.Attr("complex.c", &strVal), IsNil) 227 c.Assert(strVal, Equals, "d") 228 229 v, ok = plug.Lookup("complex.c") 230 c.Assert(ok, Equals, true) 231 c.Assert(v, Equals, "d") 232 233 // dynamic attribute nested.foo 234 c.Assert(plug.Attr("nested.foo", &strVal), IsNil) 235 c.Assert(strVal, Equals, "bar") 236 237 v, ok = plug.Lookup("nested.foo") 238 c.Assert(ok, Equals, true) 239 c.Assert(v, Equals, "bar") 240 241 _, ok = plug.Lookup("nested.x") 242 c.Assert(ok, Equals, false) 243 244 _, ok = plug.Lookup("nested.foo.y") 245 c.Assert(ok, Equals, false) 246 247 _, ok = plug.Lookup("..") 248 c.Assert(ok, Equals, false) 249 } 250 251 func (s *connSuite) TestLookupFailure(c *C) { 252 attrs := map[string]interface{}{} 253 254 slot := NewConnectedSlot(s.slot, nil, attrs) 255 c.Assert(slot, NotNil) 256 plug := NewConnectedPlug(s.plug, nil, attrs) 257 c.Assert(plug, NotNil) 258 259 v, ok := slot.Lookup("a") 260 c.Assert(ok, Equals, false) 261 c.Assert(v, IsNil) 262 263 v, ok = plug.Lookup("a") 264 c.Assert(ok, Equals, false) 265 c.Assert(v, IsNil) 266 } 267 268 func (s *connSuite) TestDynamicPlugAttrs(c *C) { 269 attrs := map[string]interface{}{ 270 "foo": "bar", 271 "number": int(100), 272 } 273 plug := NewConnectedPlug(s.plug, nil, attrs) 274 c.Assert(plug, NotNil) 275 276 var strVal string 277 var intVal int64 278 var mapVal map[string]interface{} 279 280 c.Assert(plug.Attr("foo", &strVal), IsNil) 281 c.Assert(strVal, Equals, "bar") 282 283 c.Assert(plug.Attr("attr", &strVal), IsNil) 284 c.Assert(strVal, Equals, "value") 285 286 c.Assert(plug.Attr("number", &intVal), IsNil) 287 c.Assert(intVal, Equals, int64(100)) 288 289 err := plug.SetAttr("other", map[string]interface{}{"number-two": int(222)}) 290 c.Assert(err, IsNil) 291 c.Assert(plug.Attr("other", &mapVal), IsNil) 292 num := mapVal["number-two"] 293 c.Assert(num, Equals, int64(222)) 294 295 c.Check(plug.Attr("unknown", &strVal), ErrorMatches, `snap "consumer" does not have attribute "unknown" for interface "interface"`) 296 c.Check(plug.Attr("foo", &intVal), ErrorMatches, `snap "consumer" has interface "interface" with invalid value type string for "foo" attribute: \*int64`) 297 c.Check(plug.Attr("number", intVal), ErrorMatches, `internal error: cannot get "number" attribute of interface "interface" with non-pointer value`) 298 } 299 300 func (s *connSuite) TestOverwriteStaticAttrError(c *C) { 301 attrs := map[string]interface{}{} 302 303 plug := NewConnectedPlug(s.plug, nil, attrs) 304 c.Assert(plug, NotNil) 305 slot := NewConnectedSlot(s.slot, nil, attrs) 306 c.Assert(slot, NotNil) 307 308 err := plug.SetAttr("attr", "overwrite") 309 c.Assert(err, NotNil) 310 c.Assert(err, ErrorMatches, `cannot change attribute "attr" as it was statically specified in the snap details`) 311 312 err = slot.SetAttr("attr", "overwrite") 313 c.Assert(err, NotNil) 314 c.Assert(err, ErrorMatches, `cannot change attribute "attr" as it was statically specified in the snap details`) 315 } 316 317 func (s *connSuite) TestCopyAttributes(c *C) { 318 orig := map[string]interface{}{ 319 "a": "A", 320 "b": true, 321 "c": int(100), 322 "d": []interface{}{"x", "y", true}, 323 "e": map[string]interface{}{"e1": "E1"}, 324 } 325 326 cpy := utils.CopyAttributes(orig) 327 c.Check(cpy, DeepEquals, orig) 328 329 cpy["d"].([]interface{})[0] = 999 330 c.Check(orig["d"].([]interface{})[0], Equals, "x") 331 cpy["e"].(map[string]interface{})["e1"] = "x" 332 c.Check(orig["e"].(map[string]interface{})["e1"], Equals, "E1") 333 } 334 335 func (s *connSuite) TestNewConnectedPlugExplicitStaticAttrs(c *C) { 336 staticAttrs := map[string]interface{}{ 337 "baz": "boom", 338 } 339 dynAttrs := map[string]interface{}{ 340 "foo": "bar", 341 } 342 plug := NewConnectedPlug(s.plug, staticAttrs, dynAttrs) 343 c.Assert(plug, NotNil) 344 c.Assert(plug.StaticAttrs(), DeepEquals, map[string]interface{}{"baz": "boom"}) 345 c.Assert(plug.DynamicAttrs(), DeepEquals, map[string]interface{}{"foo": "bar"}) 346 } 347 348 func (s *connSuite) TestNewConnectedSlotExplicitStaticAttrs(c *C) { 349 staticAttrs := map[string]interface{}{ 350 "baz": "boom", 351 } 352 dynAttrs := map[string]interface{}{ 353 "foo": "bar", 354 } 355 slot := NewConnectedSlot(s.slot, staticAttrs, dynAttrs) 356 c.Assert(slot, NotNil) 357 c.Assert(slot.StaticAttrs(), DeepEquals, map[string]interface{}{"baz": "boom"}) 358 c.Assert(slot.DynamicAttrs(), DeepEquals, map[string]interface{}{"foo": "bar"}) 359 }