gitee.com/mysnapcore/mysnapd@v0.1.0/cmd/snap-bootstrap/triggerwatch/triggerwatch_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 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 triggerwatch_test 21 22 import ( 23 "errors" 24 "fmt" 25 "testing" 26 "time" 27 28 . "gopkg.in/check.v1" 29 30 "gitee.com/mysnapcore/mysnapd/cmd/snap-bootstrap/triggerwatch" 31 "gitee.com/mysnapcore/mysnapd/osutil/udev/netlink" 32 ) 33 34 // Hook up check.v1 into the "go test" runner 35 func Test(t *testing.T) { TestingT(t) } 36 37 type triggerwatchSuite struct{} 38 39 var _ = Suite(&triggerwatchSuite{}) 40 41 type mockTriggerDevice struct { 42 waitForTriggerCalls int 43 closeCalls int 44 ev *triggerwatch.KeyEvent 45 } 46 47 func (m *mockTriggerDevice) WaitForTrigger(n chan triggerwatch.KeyEvent) { 48 m.waitForTriggerCalls++ 49 if m.ev != nil { 50 ev := *m.ev 51 ev.Dev = m 52 n <- ev 53 } 54 } 55 56 func (m *mockTriggerDevice) String() string { return "mock-device" } 57 func (m *mockTriggerDevice) Close() { m.closeCalls++ } 58 59 type mockTrigger struct { 60 f triggerwatch.TriggerCapabilityFilter 61 d *mockTriggerDevice 62 unlistedDevices map[string]*mockTriggerDevice 63 64 err error 65 66 findMatchingCalls int 67 openCalls int 68 } 69 70 func (m *mockTrigger) FindMatchingDevices(f triggerwatch.TriggerCapabilityFilter) ([]triggerwatch.TriggerDevice, error) { 71 m.findMatchingCalls++ 72 73 m.f = f 74 if m.err != nil { 75 return nil, m.err 76 } 77 if m.d != nil { 78 return []triggerwatch.TriggerDevice{m.d}, nil 79 } 80 return nil, nil 81 } 82 83 func (m *mockTrigger) Open(filter triggerwatch.TriggerCapabilityFilter, node string) (triggerwatch.TriggerDevice, error) { 84 m.openCalls++ 85 device, ok := m.unlistedDevices[node] 86 if !ok { 87 return nil, errors.New("Not found") 88 } else { 89 return device, nil 90 } 91 } 92 93 const testTriggerTimeout = 5 * time.Millisecond 94 const testDeviceTimeout = 2 * time.Millisecond 95 96 func (s *triggerwatchSuite) TestNoDevsWaitKey(c *C) { 97 md := &mockTriggerDevice{ev: &triggerwatch.KeyEvent{}} 98 mi := &mockTrigger{d: md} 99 restore := triggerwatch.MockInput(mi) 100 defer restore() 101 102 err := triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) 103 c.Assert(err, IsNil) 104 c.Assert(mi.findMatchingCalls, Equals, 1) 105 c.Assert(md.waitForTriggerCalls, Equals, 1) 106 c.Assert(md.closeCalls, Equals, 1) 107 } 108 109 func (s *triggerwatchSuite) TestNoDevsWaitKeyTimeout(c *C) { 110 md := &mockTriggerDevice{} 111 mi := &mockTrigger{d: md} 112 restore := triggerwatch.MockInput(mi) 113 defer restore() 114 115 err := triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) 116 c.Assert(err, Equals, triggerwatch.ErrTriggerNotDetected) 117 c.Assert(mi.findMatchingCalls, Equals, 1) 118 c.Assert(md.waitForTriggerCalls, Equals, 1) 119 c.Assert(md.closeCalls, Equals, 1) 120 } 121 122 func (s *triggerwatchSuite) TestNoDevsWaitNoMatching(c *C) { 123 mi := &mockTrigger{} 124 restore := triggerwatch.MockInput(mi) 125 defer restore() 126 127 err := triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) 128 c.Assert(err, Equals, triggerwatch.ErrNoMatchingInputDevices) 129 } 130 131 func (s *triggerwatchSuite) TestNoDevsWaitMatchingError(c *C) { 132 mi := &mockTrigger{err: fmt.Errorf("failed")} 133 restore := triggerwatch.MockInput(mi) 134 defer restore() 135 136 err := triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) 137 c.Assert(err, ErrorMatches, "cannot list trigger devices: failed") 138 } 139 140 func (s *triggerwatchSuite) TestChecksInput(c *C) { 141 restore := triggerwatch.MockInput(nil) 142 defer restore() 143 144 c.Assert(func() { triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) }, 145 Panics, "trigger is unset") 146 } 147 148 func (s *triggerwatchSuite) TestUdevEvent(c *C) { 149 nodepath := "/dev/input/event0" 150 devpath := "/devices/SOMEBUS/input/input0/event0" 151 152 md := &mockTriggerDevice{ev: &triggerwatch.KeyEvent{}} 153 mi := &mockTrigger{ 154 unlistedDevices: map[string]*mockTriggerDevice{ 155 "/dev/input/event0": md, 156 }, 157 } 158 restore := triggerwatch.MockInput(mi) 159 defer restore() 160 161 events := []netlink.UEvent{ 162 { 163 Action: netlink.ADD, 164 KObj: devpath, 165 Env: map[string]string{ 166 "SUBSYSTEM": "input", 167 "DEVNAME": nodepath, 168 "DEVPATH": devpath, 169 }, 170 }, 171 } 172 restoreUevents := triggerwatch.MockUEvent(events) 173 defer restoreUevents() 174 175 err := triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) 176 c.Assert(err, IsNil) 177 c.Assert(mi.findMatchingCalls, Equals, 1) 178 179 c.Assert(mi.openCalls, Equals, 1) 180 c.Assert(md.waitForTriggerCalls, Equals, 1) 181 c.Assert(md.closeCalls, Equals, 1) 182 } 183 184 func (s *triggerwatchSuite) TestUdevEventNoKeyEvent(c *C) { 185 nodepath := "/dev/input/event0" 186 devpath := "/devices/SOMEBUS/input/input0/event0" 187 188 md := &mockTriggerDevice{} 189 mi := &mockTrigger{ 190 unlistedDevices: map[string]*mockTriggerDevice{ 191 "/dev/input/event0": md, 192 }, 193 } 194 restore := triggerwatch.MockInput(mi) 195 defer restore() 196 197 events := []netlink.UEvent{ 198 { 199 Action: netlink.ADD, 200 KObj: devpath, 201 Env: map[string]string{ 202 "SUBSYSTEM": "input", 203 "DEVNAME": nodepath, 204 "DEVPATH": devpath, 205 }, 206 }, 207 } 208 restoreUevents := triggerwatch.MockUEvent(events) 209 defer restoreUevents() 210 211 err := triggerwatch.Wait(testTriggerTimeout, testDeviceTimeout) 212 c.Assert(err, Equals, triggerwatch.ErrTriggerNotDetected) 213 c.Assert(mi.findMatchingCalls, Equals, 1) 214 215 c.Assert(mi.openCalls, Equals, 1) 216 c.Assert(md.waitForTriggerCalls, Equals, 1) 217 c.Assert(md.closeCalls, Equals, 1) 218 }