github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/interfaces/udev/spec_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 udev_test
    21  
    22  import (
    23  	. "gopkg.in/check.v1"
    24  
    25  	"github.com/snapcore/snapd/interfaces"
    26  	"github.com/snapcore/snapd/interfaces/ifacetest"
    27  	"github.com/snapcore/snapd/interfaces/udev"
    28  	"github.com/snapcore/snapd/snap"
    29  	"github.com/snapcore/snapd/snap/snaptest"
    30  )
    31  
    32  type specSuite struct {
    33  	iface    *ifacetest.TestInterface
    34  	spec     *udev.Specification
    35  	plugInfo *snap.PlugInfo
    36  	plug     *interfaces.ConnectedPlug
    37  	slotInfo *snap.SlotInfo
    38  	slot     *interfaces.ConnectedSlot
    39  }
    40  
    41  var _ = Suite(&specSuite{
    42  	iface: &ifacetest.TestInterface{
    43  		InterfaceName: "test",
    44  		UDevConnectedPlugCallback: func(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    45  			spec.AddSnippet("connected-plug")
    46  			return nil
    47  		},
    48  		UDevConnectedSlotCallback: func(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
    49  			spec.AddSnippet("connected-slot")
    50  			return nil
    51  		},
    52  		UDevPermanentPlugCallback: func(spec *udev.Specification, plug *snap.PlugInfo) error {
    53  			spec.AddSnippet("permanent-plug")
    54  			return nil
    55  		},
    56  		UDevPermanentSlotCallback: func(spec *udev.Specification, slot *snap.SlotInfo) error {
    57  			spec.AddSnippet("permanent-slot")
    58  			return nil
    59  		},
    60  	},
    61  })
    62  
    63  func (s *specSuite) SetUpSuite(c *C) {
    64  	info1 := snaptest.MockInfo(c, `name: snap1
    65  version: 0
    66  plugs:
    67      name:
    68          interface: test
    69  apps:
    70      foo:
    71          command: bin/foo
    72  hooks:
    73      configure:
    74  `, nil)
    75  	info2 := snaptest.MockInfo(c, `name: snap2
    76  version: 0
    77  slots:
    78      name:
    79          interface: test
    80  `, nil)
    81  	s.plugInfo = info1.Plugs["name"]
    82  	s.plug = interfaces.NewConnectedPlug(s.plugInfo, nil, nil)
    83  	s.slotInfo = info2.Slots["name"]
    84  	s.slot = interfaces.NewConnectedSlot(s.slotInfo, nil, nil)
    85  }
    86  
    87  func (s *specSuite) SetUpTest(c *C) {
    88  	s.spec = &udev.Specification{}
    89  }
    90  
    91  func (s *specSuite) TestAddSnippte(c *C) {
    92  	s.spec.AddSnippet("foo")
    93  	c.Assert(s.spec.Snippets(), DeepEquals, []string{"foo"})
    94  }
    95  
    96  func (s *specSuite) TestTagDevice(c *C) {
    97  	// TagDevice acts in the scope of the plug/slot (as appropriate) and
    98  	// affects all of the apps and hooks related to the given plug or slot
    99  	// (with the exception that slots cannot have hooks).
   100  	iface := &ifacetest.TestInterface{
   101  		InterfaceName: "iface-1",
   102  		UDevConnectedPlugCallback: func(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   103  			spec.TagDevice(`kernel="voodoo"`)
   104  			return nil
   105  		},
   106  	}
   107  	c.Assert(s.spec.AddConnectedPlug(iface, s.plug, s.slot), IsNil)
   108  
   109  	iface = &ifacetest.TestInterface{
   110  		InterfaceName: "iface-2",
   111  		UDevConnectedPlugCallback: func(spec *udev.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   112  			spec.TagDevice(`kernel="hoodoo"`)
   113  			return nil
   114  		},
   115  	}
   116  	c.Assert(s.spec.AddConnectedPlug(iface, s.plug, s.slot), IsNil)
   117  
   118  	c.Assert(s.spec.Snippets(), DeepEquals, []string{
   119  		`# iface-1
   120  kernel="voodoo", TAG+="snap_snap1_foo"`,
   121  		`# iface-2
   122  kernel="hoodoo", TAG+="snap_snap1_foo"`,
   123  		`TAG=="snap_snap1_foo", RUN+="/usr/lib/snapd/snap-device-helper $env{ACTION} snap_snap1_foo $devpath $major:$minor"`,
   124  		`# iface-1
   125  kernel="voodoo", TAG+="snap_snap1_hook_configure"`,
   126  		`# iface-2
   127  kernel="hoodoo", TAG+="snap_snap1_hook_configure"`,
   128  		`TAG=="snap_snap1_hook_configure", RUN+="/usr/lib/snapd/snap-device-helper $env{ACTION} snap_snap1_hook_configure $devpath $major:$minor"`,
   129  	})
   130  }
   131  
   132  // The spec.Specification can be used through the interfaces.Specification interface
   133  func (s *specSuite) TestSpecificationIface(c *C) {
   134  	var r interfaces.Specification = s.spec
   135  	c.Assert(r.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil)
   136  	c.Assert(r.AddConnectedSlot(s.iface, s.plug, s.slot), IsNil)
   137  	c.Assert(r.AddPermanentPlug(s.iface, s.plugInfo), IsNil)
   138  	c.Assert(r.AddPermanentSlot(s.iface, s.slotInfo), IsNil)
   139  	c.Assert(s.spec.Snippets(), DeepEquals, []string{"connected-plug", "connected-slot", "permanent-plug", "permanent-slot"})
   140  }
   141  
   142  func (s *specSuite) TestControlsDeviceCgroup(c *C) {
   143  	c.Assert(s.spec.ControlsDeviceCgroup(), Equals, false)
   144  	s.spec.SetControlsDeviceCgroup()
   145  	c.Assert(s.spec.ControlsDeviceCgroup(), Equals, true)
   146  }