gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/common_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2018 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 builtin 21 22 import ( 23 "fmt" 24 "os" 25 26 . "gopkg.in/check.v1" 27 28 "gitee.com/mysnapcore/mysnapd/dirs" 29 "gitee.com/mysnapcore/mysnapd/interfaces/apparmor" 30 "gitee.com/mysnapcore/mysnapd/interfaces/udev" 31 "gitee.com/mysnapcore/mysnapd/testutil" 32 ) 33 34 type commonIfaceSuite struct{} 35 36 var _ = Suite(&commonIfaceSuite{}) 37 38 func (s *commonIfaceSuite) TestUDevSpec(c *C) { 39 plug, _ := MockConnectedPlug(c, ` 40 name: consumer 41 version: 0 42 apps: 43 app-a: 44 plugs: [common] 45 app-b: 46 app-c: 47 plugs: [common] 48 `, nil, "common") 49 slot, _ := MockConnectedSlot(c, ` 50 name: producer 51 version: 0 52 slots: 53 common: 54 `, nil, "common") 55 56 // common interface can define connected plug udev rules 57 iface := &commonInterface{ 58 name: "common", 59 connectedPlugUDev: []string{`KERNEL=="foo"`}, 60 } 61 spec := &udev.Specification{} 62 c.Assert(spec.AddConnectedPlug(iface, plug, slot), IsNil) 63 c.Assert(spec.Snippets(), DeepEquals, []string{ 64 `# common 65 KERNEL=="foo", TAG+="snap_consumer_app-a"`, 66 fmt.Sprintf(`TAG=="snap_consumer_app-a", RUN+="%v/snap-device-helper $env{ACTION} snap_consumer_app-a $devpath $major:$minor"`, dirs.DistroLibExecDir), 67 // NOTE: app-b is unaffected as it doesn't have a plug reference. 68 `# common 69 KERNEL=="foo", TAG+="snap_consumer_app-c"`, 70 fmt.Sprintf(`TAG=="snap_consumer_app-c", RUN+="%v/snap-device-helper $env{ACTION} snap_consumer_app-c $devpath $major:$minor"`, dirs.DistroLibExecDir), 71 }) 72 73 // connected plug udev rules are optional 74 iface = &commonInterface{ 75 name: "common", 76 } 77 spec = &udev.Specification{} 78 c.Assert(spec.AddConnectedPlug(iface, plug, slot), IsNil) 79 c.Assert(spec.Snippets(), HasLen, 0) 80 } 81 82 // MockEvalSymlinks replaces the path/filepath.EvalSymlinks function used inside the caps package. 83 func MockEvalSymlinks(test *testutil.BaseTest, fn func(string) (string, error)) { 84 orig := evalSymlinks 85 evalSymlinks = fn 86 test.AddCleanup(func() { 87 evalSymlinks = orig 88 }) 89 } 90 91 // MockReadDir replaces the io/ioutil.ReadDir function used inside the caps package. 92 func MockReadDir(test *testutil.BaseTest, fn func(string) ([]os.FileInfo, error)) { 93 orig := readDir 94 readDir = fn 95 test.AddCleanup(func() { 96 readDir = orig 97 }) 98 } 99 100 func (s *commonIfaceSuite) TestSuppressFeatures(c *C) { 101 plug, _ := MockConnectedPlug(c, ` 102 name: consumer 103 version: 0 104 apps: 105 app: 106 plugs: [common] 107 `, nil, "common") 108 slot, _ := MockConnectedSlot(c, ` 109 name: producer 110 version: 0 111 slots: 112 common: 113 `, nil, "common") 114 115 type Checks []struct { 116 getter func(spec *apparmor.Specification) bool 117 expectedValue bool 118 } 119 120 tests := []struct { 121 iface *commonInterface 122 checks Checks 123 }{ 124 // PtraceTrace 125 { 126 // setting nothing 127 &commonInterface{name: "common", suppressPtraceTrace: false, usesPtraceTrace: false}, 128 Checks{ 129 {(*apparmor.Specification).UsesPtraceTrace, false}, 130 {(*apparmor.Specification).SuppressPtraceTrace, false}, 131 }, 132 }, 133 { 134 // setting only uses 135 &commonInterface{name: "common", suppressPtraceTrace: false, usesPtraceTrace: true}, 136 Checks{ 137 {(*apparmor.Specification).UsesPtraceTrace, true}, 138 {(*apparmor.Specification).SuppressPtraceTrace, false}, 139 }, 140 }, 141 { 142 // setting only suppress 143 &commonInterface{name: "common", suppressPtraceTrace: true, usesPtraceTrace: false}, 144 Checks{ 145 {(*apparmor.Specification).UsesPtraceTrace, false}, 146 {(*apparmor.Specification).SuppressPtraceTrace, true}, 147 }, 148 }, 149 { 150 // setting both, only uses is set 151 &commonInterface{name: "common", suppressPtraceTrace: true, usesPtraceTrace: true}, 152 Checks{ 153 {(*apparmor.Specification).UsesPtraceTrace, true}, 154 {(*apparmor.Specification).SuppressPtraceTrace, false}, 155 }, 156 }, 157 // HomeIx 158 { 159 // setting nothing 160 &commonInterface{name: "common", suppressHomeIx: false}, 161 Checks{ 162 {(*apparmor.Specification).SuppressHomeIx, false}, 163 }, 164 }, 165 { 166 // setting suppress 167 &commonInterface{name: "common", suppressHomeIx: true}, 168 Checks{ 169 {(*apparmor.Specification).SuppressHomeIx, true}, 170 }, 171 }, 172 // sys_module capability 173 { 174 // setting nothing 175 &commonInterface{name: "common", suppressSysModuleCapability: false, usesSysModuleCapability: false}, 176 Checks{ 177 {(*apparmor.Specification).UsesSysModuleCapability, false}, 178 {(*apparmor.Specification).SuppressSysModuleCapability, false}, 179 }, 180 }, 181 { 182 // setting only uses 183 &commonInterface{name: "common", suppressSysModuleCapability: false, usesSysModuleCapability: true}, 184 Checks{ 185 {(*apparmor.Specification).UsesSysModuleCapability, true}, 186 {(*apparmor.Specification).SuppressSysModuleCapability, false}, 187 }, 188 }, 189 { 190 // setting only suppress 191 &commonInterface{name: "common", suppressSysModuleCapability: true, usesSysModuleCapability: false}, 192 Checks{ 193 {(*apparmor.Specification).UsesSysModuleCapability, false}, 194 {(*apparmor.Specification).SuppressSysModuleCapability, true}, 195 }, 196 }, 197 { 198 // setting both, only uses is set 199 &commonInterface{name: "common", suppressSysModuleCapability: true, usesSysModuleCapability: true}, 200 Checks{ 201 {(*apparmor.Specification).UsesSysModuleCapability, true}, 202 {(*apparmor.Specification).SuppressSysModuleCapability, false}, 203 }, 204 }, 205 } 206 207 for _, test := range tests { 208 spec := &apparmor.Specification{} 209 iface := test.iface 210 // before connection, everything should be set to false 211 for _, check := range test.checks { 212 c.Check(check.getter(spec), Equals, false) 213 } 214 c.Check(spec.AddConnectedPlug(iface, plug, slot), IsNil) 215 for _, check := range test.checks { 216 c.Check(check.getter(spec), Equals, check.expectedValue) 217 } 218 } 219 } 220 221 func (s *commonIfaceSuite) TestControlsDeviceCgroup(c *C) { 222 plug, _ := MockConnectedPlug(c, ` 223 name: consumer 224 version: 0 225 apps: 226 app: 227 plugs: [common] 228 `, nil, "common") 229 slot, _ := MockConnectedSlot(c, ` 230 name: producer 231 version: 0 232 slots: 233 common: 234 `, nil, "common") 235 236 // setting nothing 237 iface := &commonInterface{ 238 name: "common", 239 controlsDeviceCgroup: false, 240 } 241 spec := &udev.Specification{} 242 c.Assert(spec.ControlsDeviceCgroup(), Equals, false) 243 c.Assert(spec.AddConnectedPlug(iface, plug, slot), IsNil) 244 c.Assert(spec.ControlsDeviceCgroup(), Equals, false) 245 246 iface = &commonInterface{ 247 name: "common", 248 controlsDeviceCgroup: true, 249 } 250 spec = &udev.Specification{} 251 c.Assert(spec.ControlsDeviceCgroup(), Equals, false) 252 c.Assert(spec.AddConnectedPlug(iface, plug, slot), IsNil) 253 c.Assert(spec.ControlsDeviceCgroup(), Equals, true) 254 }