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 }