github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/interfaces/systemd/spec_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2021 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 systemd_test
    21  
    22  import (
    23  	"fmt"
    24  
    25  	. "gopkg.in/check.v1"
    26  
    27  	"github.com/snapcore/snapd/interfaces"
    28  	"github.com/snapcore/snapd/interfaces/ifacetest"
    29  	"github.com/snapcore/snapd/interfaces/systemd"
    30  	"github.com/snapcore/snapd/snap"
    31  	"github.com/snapcore/snapd/snap/snaptest"
    32  )
    33  
    34  type specSuite struct{}
    35  
    36  var _ = Suite(&specSuite{})
    37  
    38  func (s *specSuite) TestAddService(c *C) {
    39  	spec := systemd.Specification{}
    40  	c.Assert(spec.Services(), IsNil)
    41  	svc1 := &systemd.Service{ExecStart: "one"}
    42  	err := spec.AddService("svc1", svc1)
    43  	c.Assert(err, IsNil)
    44  	svc2 := &systemd.Service{ExecStart: "two"}
    45  	err = spec.AddService("svc2", svc2)
    46  	c.Assert(err, IsNil)
    47  	c.Assert(spec.Services(), DeepEquals, map[string]*systemd.Service{
    48  		"svc1": svc1,
    49  		"svc2": svc2,
    50  	})
    51  }
    52  
    53  func (s *specSuite) TestClashingSameIface(c *C) {
    54  	info1 := snaptest.MockInfo(c, `name: snap1
    55  version: 0
    56  plugs:
    57      plug1:
    58          interface: test
    59  `, nil)
    60  
    61  	iface := &ifacetest.TestInterface{
    62  		InterfaceName: "test",
    63  	}
    64  	svc1 := &systemd.Service{ExecStart: "one"}
    65  	svc2 := &systemd.Service{ExecStart: "two"}
    66  
    67  	iface.SystemdPermanentPlugCallback = func(spec *systemd.Specification, plug *snap.PlugInfo) error {
    68  		if err := spec.AddService("foo", svc1); err != nil {
    69  			return err
    70  		}
    71  		return spec.AddService("foo", svc2)
    72  	}
    73  
    74  	spec := systemd.Specification{}
    75  	err := spec.AddPermanentPlug(iface, info1.Plugs["plug1"])
    76  	c.Assert(err, ErrorMatches, `internal error: interface "test" has inconsistent system needs: service for "foo" used to be defined as .*, now re-defined as .*`)
    77  }
    78  
    79  func (s *specSuite) TestClashingTwoIfaces(c *C) {
    80  	info1 := snaptest.MockInfo(c, `name: snap1
    81  version: 0
    82  plugs:
    83      plug1:
    84          interface: test1
    85      plug2:
    86          interface: test2
    87  `, nil)
    88  
    89  	iface1 := &ifacetest.TestInterface{
    90  		InterfaceName: "test1",
    91  	}
    92  	iface2 := &ifacetest.TestInterface{
    93  		InterfaceName: "test2",
    94  	}
    95  	svc1 := &systemd.Service{ExecStart: "one"}
    96  	svc2 := &systemd.Service{ExecStart: "two"}
    97  
    98  	iface1.SystemdPermanentPlugCallback = func(spec *systemd.Specification, plug *snap.PlugInfo) error {
    99  		return spec.AddService("foo", svc1)
   100  	}
   101  
   102  	iface2.SystemdPermanentPlugCallback = func(spec *systemd.Specification, plug *snap.PlugInfo) error {
   103  		return spec.AddService("foo", svc2)
   104  	}
   105  
   106  	spec := systemd.Specification{}
   107  	err := spec.AddPermanentPlug(iface1, info1.Plugs["plug1"])
   108  	c.Assert(err, IsNil)
   109  	err = spec.AddPermanentPlug(iface2, info1.Plugs["plug2"])
   110  	c.Assert(err, ErrorMatches, `internal error: interface "test2" and "test1" have conflicting system needs: service for "foo" used to be defined as .* by "test1", now re-defined as .*`)
   111  }
   112  
   113  func (s *specSuite) TestDifferentObjectsNotClashing(c *C) {
   114  	svc1 := &systemd.Service{ExecStart: "one and the same"}
   115  	svc2 := &systemd.Service{ExecStart: "one and the same"}
   116  	spec := systemd.Specification{}
   117  	err := spec.AddService("foo", svc1)
   118  	c.Assert(err, IsNil)
   119  	err = spec.AddService("foo", svc2)
   120  	c.Assert(err, IsNil)
   121  }
   122  
   123  func (s *specSuite) TestAddMethods(c *C) {
   124  	info1 := snaptest.MockInfo(c, `name: snap1
   125  version: 0
   126  plugs:
   127      plug1:
   128          interface: test
   129  `, nil)
   130  	info2 := snaptest.MockInfo(c, `name: snap2
   131  version: 0
   132  slots:
   133      slot2:
   134          interface: test
   135  `, nil)
   136  	plugInfo := info1.Plugs["plug1"]
   137  	plug := interfaces.NewConnectedPlug(plugInfo, nil, nil)
   138  	slotInfo := info2.Slots["slot2"]
   139  	slot := interfaces.NewConnectedSlot(slotInfo, nil, nil)
   140  
   141  	spec := systemd.Specification{}
   142  
   143  	iface := &ifacetest.TestInterface{
   144  		InterfaceName: "test",
   145  		SystemdConnectedPlugCallback: func(spec *systemd.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   146  			spec.AddService(fmt.Sprintf("%s-%s", plug.Name(), slot.Name()), &systemd.Service{ExecStart: "connected-plug"})
   147  			return nil
   148  		},
   149  		SystemdConnectedSlotCallback: func(spec *systemd.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   150  			spec.AddService(fmt.Sprintf("%s-%s", slot.Name(), plug.Name()), &systemd.Service{ExecStart: "connected-slot"})
   151  			return nil
   152  		},
   153  		SystemdPermanentPlugCallback: func(spec *systemd.Specification, plug *snap.PlugInfo) error {
   154  			spec.AddService(plug.Name, &systemd.Service{ExecStart: "permanent-plug"})
   155  			return nil
   156  		},
   157  		SystemdPermanentSlotCallback: func(spec *systemd.Specification, slot *snap.SlotInfo) error {
   158  			spec.AddService(slot.Name, &systemd.Service{ExecStart: "permanent-slot"})
   159  			return nil
   160  		},
   161  	}
   162  
   163  	err := spec.AddPermanentSlot(iface, slotInfo)
   164  	c.Assert(err, IsNil)
   165  
   166  	err = spec.AddPermanentPlug(iface, plugInfo)
   167  	c.Assert(err, IsNil)
   168  
   169  	err = spec.AddConnectedSlot(iface, plug, slot)
   170  	c.Assert(err, IsNil)
   171  
   172  	err = spec.AddConnectedPlug(iface, plug, slot)
   173  	c.Assert(err, IsNil)
   174  
   175  	c.Check(spec.Services(), DeepEquals, map[string]*systemd.Service{
   176  		"plug1-slot2": {ExecStart: "connected-plug"},
   177  		"slot2-plug1": {ExecStart: "connected-slot"},
   178  		"plug1":       {ExecStart: "permanent-plug"},
   179  		"slot2":       {ExecStart: "permanent-slot"},
   180  	})
   181  }