vigilem-evdev 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/ext/Rakefile +31 -0
  4. data/ext/rake_helper.rb +10 -0
  5. data/lib/vigilem/_evdev.rb +24 -0
  6. data/lib/vigilem/evdev.rb +14 -0
  7. data/lib/vigilem/evdev/at_exit.rb +8 -0
  8. data/lib/vigilem/evdev/context_filter.rb +92 -0
  9. data/lib/vigilem/evdev/demultiplexer.rb +26 -0
  10. data/lib/vigilem/evdev/device.rb +182 -0
  11. data/lib/vigilem/evdev/device_capabilities.rb +53 -0
  12. data/lib/vigilem/evdev/dom.rb +8 -0
  13. data/lib/vigilem/evdev/dom/adapter.rb +87 -0
  14. data/lib/vigilem/evdev/dom/code_values_tables.rb +172 -0
  15. data/lib/vigilem/evdev/dom/input_event_converter.rb +329 -0
  16. data/lib/vigilem/evdev/dom/input_event_utils.rb +48 -0
  17. data/lib/vigilem/evdev/dom/key_values_tables.rb +248 -0
  18. data/lib/vigilem/evdev/dom/kp_table.rb +52 -0
  19. data/lib/vigilem/evdev/focus_context_filter.rb +124 -0
  20. data/lib/vigilem/evdev/input_system_handler.rb +69 -0
  21. data/lib/vigilem/evdev/key_map_cache.rb +64 -0
  22. data/lib/vigilem/evdev/multiplexer.rb +73 -0
  23. data/lib/vigilem/evdev/system.rb +17 -0
  24. data/lib/vigilem/evdev/system/input.rb +1053 -0
  25. data/lib/vigilem/evdev/system/input/event.rb +4 -0
  26. data/lib/vigilem/evdev/system/input/input_event.rb +33 -0
  27. data/lib/vigilem/evdev/system/int.rb +9 -0
  28. data/lib/vigilem/evdev/system/ioctl.rb +143 -0
  29. data/lib/vigilem/evdev/system/keymap_loaders.rb +89 -0
  30. data/lib/vigilem/evdev/system/keymap_loaders/dumpkeys_loader.rb +98 -0
  31. data/lib/vigilem/evdev/system/keymap_loaders/kmap_loader.rb +74 -0
  32. data/lib/vigilem/evdev/system/posix_types.rb +5 -0
  33. data/lib/vigilem/evdev/system/time.rb +21 -0
  34. data/lib/vigilem/evdev/transfer_agent.rb +40 -0
  35. data/lib/vigilem/evdev/version.rb +5 -0
  36. data/lib/vigilem/evdev/vty_context_filter.rb +216 -0
  37. data/spec/after_each_example_group.rb +29 -0
  38. data/spec/delete_test_cache_after_group.rb +26 -0
  39. data/spec/spec_helper.rb +30 -0
  40. data/spec/vigilem/_evdev_spec.rb +11 -0
  41. data/spec/vigilem/evdev/context_filter_spec.rb +114 -0
  42. data/spec/vigilem/evdev/demultiplexer_spec.rb +44 -0
  43. data/spec/vigilem/evdev/device_capabilities_spec.rb +0 -0
  44. data/spec/vigilem/evdev/device_spec.rb +97 -0
  45. data/spec/vigilem/evdev/dom/adapter_spec.rb +5 -0
  46. data/spec/vigilem/evdev/dom/input_event_converter_spec.rb +253 -0
  47. data/spec/vigilem/evdev/dom/input_event_utils_spec.rb +23 -0
  48. data/spec/vigilem/evdev/focus_context_filter_spec.rb +112 -0
  49. data/spec/vigilem/evdev/input_system_handler_spec.rb +146 -0
  50. data/spec/vigilem/evdev/key_map_cache_spec.rb +65 -0
  51. data/spec/vigilem/evdev/multiplexer_spec.rb +55 -0
  52. data/spec/vigilem/evdev/system/input/input_event_spec.rb +33 -0
  53. data/spec/vigilem/evdev/system/input_spec.rb +274 -0
  54. data/spec/vigilem/evdev/system/int_spec.rb +30 -0
  55. data/spec/vigilem/evdev/system/ioctl_spec.rb +206 -0
  56. data/spec/vigilem/evdev/system/keymap_loaders/dumpkeys_loader_spec.rb +5 -0
  57. data/spec/vigilem/evdev/system/keymap_loaders/kmap_loader_spec.rb +24 -0
  58. data/spec/vigilem/evdev/system/keymap_loaders_spec.rb +22 -0
  59. data/spec/vigilem/evdev/system/posix_types_spec.rb +15 -0
  60. data/spec/vigilem/evdev/system/time_spec.rb +18 -0
  61. data/spec/vigilem/evdev/transfer_agent_spec.rb +57 -0
  62. data/spec/vigilem/evdev/vty_context_filter_spec.rb +282 -0
  63. metadata +286 -0
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ require 'vigilem/evdev/system/posix_types'
4
+
5
+ describe 'int' do
6
+ it 'defines __u8' do
7
+ expect(FFI::TypeDefs[:__u8]).not_to be_nil
8
+ end
9
+
10
+ it 'defines __u8' do
11
+ expect(FFI::TypeDefs[:__u16]).not_to be_nil
12
+ end
13
+
14
+ it 'defines __u8' do
15
+ expect(FFI::TypeDefs[:__u32]).not_to be_nil
16
+ end
17
+
18
+ it 'defines __u8' do
19
+ expect(FFI::TypeDefs[:__s8]).not_to be_nil
20
+ end
21
+
22
+ it 'defines __u8' do
23
+ expect(FFI::TypeDefs[:__s16]).not_to be_nil
24
+ end
25
+
26
+ it 'defines __u8' do
27
+ expect(FFI::TypeDefs[:__s32]).not_to be_nil
28
+ end
29
+
30
+ end
@@ -0,0 +1,206 @@
1
+ require 'spec_helper'
2
+
3
+ require 'vigilem/evdev/system/ioctl'
4
+
5
+ describe Vigilem::Evdev::System::IOCTL do
6
+ class C
7
+ inline do |builder|
8
+ builder.include '<stdio.h>'
9
+ builder.include '<sys/ioctl.h>'
10
+ builder.include '<linux/input.h>'
11
+ builder.include '<fcntl.h>'
12
+ builder.include '<stddef.h>'
13
+ %w(_IOC_NRBITS _IOC_TYPEBITS _IOC_SIZEBITS _IOC_DIRBITS _IOC_NRMASK
14
+ _IOC_TYPEMASK _IOC_SIZEMASK _IOC_DIRMASK _IOC_NRSHIFT _IOC_TYPESHIFT
15
+ _IOC_SIZESHIFT _IOC_DIRSHIFT IOCSIZE_MASK IOCSIZE_SHIFT).map do |str|
16
+ builder.c "
17
+ long r_#{str}() {
18
+ return #{str};
19
+ }
20
+ "
21
+ end
22
+
23
+ %w(_IOC_NONE _IOC_WRITE _IOC_READ).map do |str|
24
+ builder.c "
25
+ int r_#{str}() {
26
+ return #{str};
27
+ }
28
+ "
29
+ end
30
+
31
+ builder.c '
32
+ long r__IO(char type, int nr) {
33
+ return _IO(type, nr);
34
+ }
35
+ '
36
+ builder.c '
37
+ long r_int2_IOC(long dir, char type, int nr) {
38
+ return _IOC(dir, type, nr, sizeof(int[2]));
39
+ }
40
+ '
41
+ end
42
+ end
43
+
44
+ let(:c) { C.new }
45
+
46
+ it 'will return zero if sudo is not used' do
47
+ expect(c.r__IOC_NRBITS).not_to eql 0
48
+ end
49
+
50
+ describe '::_IOC_NRBITS' do
51
+ it 'will match the linux value' do
52
+ expect(described_class::_IOC_NRBITS).to eql(c.r__IOC_NRBITS)
53
+ end
54
+ end
55
+
56
+ describe '::_IOC_TYPEBITS' do
57
+ it 'will match the linux value' do
58
+ expect(described_class::_IOC_TYPEBITS).to eql(c.r__IOC_TYPEBITS)
59
+ end
60
+ end
61
+
62
+ describe '::_IOC_SIZEBITS' do
63
+ it 'will match the linux value' do
64
+ expect(described_class::_IOC_SIZEBITS).to eql(c.r__IOC_SIZEBITS)
65
+ end
66
+ end
67
+
68
+ describe '::_IOC_DIRBITS' do
69
+ it 'will match the linux value' do
70
+ expect(described_class::_IOC_DIRBITS).to eql(c.r__IOC_DIRBITS)
71
+ end
72
+ end
73
+
74
+ describe '::_IOC_NRMASK' do
75
+ it 'will match the linux value' do
76
+ expect(described_class::_IOC_NRMASK).to eql(c.r__IOC_NRMASK)
77
+ end
78
+ end
79
+
80
+ describe '::_IOC_TYPEMASK' do
81
+ it 'will match the linux value' do
82
+ expect(described_class::_IOC_TYPEMASK).to eql(c.r__IOC_TYPEMASK)
83
+ end
84
+ end
85
+
86
+ describe '::_IOC_SIZEMASK' do
87
+ it 'will match the linux value' do
88
+ expect(described_class::_IOC_SIZEMASK).to eql(c.r__IOC_SIZEMASK)
89
+ end
90
+ end
91
+
92
+ describe '::_IOC_DIRMASK' do
93
+ it 'will match the linux value' do
94
+ expect(described_class::_IOC_DIRMASK).to eql(c.r__IOC_DIRMASK)
95
+ end
96
+ end
97
+
98
+ describe '::_IOC_NRSHIFT' do
99
+ it 'will match the linux value' do
100
+ expect(described_class::_IOC_NRSHIFT).to eql(c.r__IOC_NRSHIFT)
101
+ end
102
+ end
103
+
104
+ describe '::_IOC_TYPESHIFT' do
105
+ it 'will match the linux value' do
106
+ expect(described_class::_IOC_TYPESHIFT).to eql(c.r__IOC_TYPESHIFT)
107
+ end
108
+ end
109
+
110
+ describe '::_IOC_SIZESHIFT' do
111
+ it 'will match the linux value' do
112
+ expect(described_class::_IOC_SIZESHIFT).to eql(c.r__IOC_SIZESHIFT)
113
+ end
114
+ end
115
+
116
+ describe '::_IOC_DIRSHIFT' do
117
+ it 'will match the linux value' do
118
+ expect(described_class::_IOC_DIRSHIFT).to eql(c.r__IOC_DIRSHIFT)
119
+ end
120
+ end
121
+
122
+ describe '::IOCSIZE_MASK' do
123
+ it 'will match the linux value' do
124
+ expect(described_class.IOCSIZE_MASK).to eql(c.r_IOCSIZE_MASK)
125
+ end
126
+ end
127
+
128
+ describe '::IOCSIZE_SHIFT' do
129
+ it 'will match the linux value' do
130
+ expect(described_class.IOCSIZE_SHIFT).to eql(c.r_IOCSIZE_SHIFT)
131
+ end
132
+ end
133
+
134
+ describe '::_IOC_NONE' do
135
+ it 'will match the linux value' do
136
+ expect(described_class._IOC_NONE).to eql(c.r__IOC_NONE)
137
+ end
138
+ end
139
+ describe '::_IOC_WRITE' do
140
+ it 'will match the linux value' do
141
+ expect(described_class._IOC_WRITE).to eql(c.r__IOC_WRITE)
142
+ end
143
+ end
144
+
145
+ describe '::_IOC_READ' do
146
+ it 'will match the linux value' do
147
+ expect(described_class._IOC_READ).to eql(c.r__IOC_READ)
148
+ end
149
+ end
150
+
151
+ let(:i_2) { 'ii' }
152
+
153
+ let(:i_2_length) { ([0] * 2).pack('ii').length }
154
+
155
+ let(:ioc_r) { described_class::_IOC_READ }
156
+ let(:ioc_n) { described_class::_IOC_NONE }
157
+
158
+ describe '::_IOC' do
159
+ it 'will match the linux value' do
160
+ expect(described_class._IOC(ioc_r, 'E', 0x03, i_2_length)).to eql(c.r_int2_IOC(ioc_r, 'E', 0x03))
161
+ end
162
+ end
163
+
164
+
165
+ describe '::_IO' do
166
+ it 'will match the linux value' do
167
+ expect(described_class._IO('E', 0x03)).to eql(c.r__IO('E', 0x03))
168
+ end
169
+ end
170
+
171
+ class Macro
172
+ inline do |builder|
173
+ builder.include '<stdio.h>'
174
+ builder.include '<sys/ioctl.h>'
175
+ builder.include '<fcntl.h>'
176
+ %w(_IOR _IOW _IOWR).map do |str|
177
+ builder.c "
178
+ long #{str.downcase}_int(char type, int nr) {
179
+ return #{str}(type, nr, int);
180
+ }
181
+ "
182
+ end
183
+ end
184
+ end
185
+
186
+ let(:macro) { Macro.new }
187
+
188
+ describe '::_IOR' do
189
+ it 'will match the linux value' do
190
+ expect(described_class._IOR('E', 0x03, 'i')).to eql(macro._ior_int('E', 0x03))
191
+ end
192
+ end
193
+
194
+ describe '::_IOW' do
195
+ it 'will match the linux value' do
196
+ expect(described_class._IOW('E', 0x03, 'i')).to eql(macro._iow_int('E', 0x03))
197
+ end
198
+ end
199
+
200
+ describe '::_IOWR' do
201
+ it 'will match the linux value' do
202
+ expect(described_class._IOWR('E', 0x03, 'i')).to eql(macro._iowr_int('E', 0x03))
203
+ end
204
+ end
205
+
206
+ end
@@ -0,0 +1,5 @@
1
+ require 'vigilem/evdev/system/keymap_loaders/dumpkeys_loader'
2
+
3
+ describe Vigilem::Evdev::System::KeymapLoaders::DumpkeysLoader do
4
+
5
+ end
@@ -0,0 +1,24 @@
1
+ require 'vigilem/evdev/system/keymap_loaders/kmap_loader'
2
+
3
+ describe Vigilem::Evdev::System::KeymapLoaders::KmapLoader do
4
+
5
+ describe '#exec' do
6
+ it 'looks for plain text kmap file in console-setup' do
7
+
8
+ end
9
+
10
+ it 'looks for a gzipped kmap file' do
11
+
12
+ end
13
+ end
14
+
15
+ describe '#key_map' do
16
+
17
+ end
18
+
19
+ describe '#key_map_info' do
20
+
21
+ end
22
+
23
+
24
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ require 'vigilem/evdev/system/keymap_loaders'
4
+
5
+ require 'vigilem/evdev/system/keymap_loaders/dumpkeys_loader'
6
+ require 'vigilem/evdev/system/keymap_loaders/kmap_loader'
7
+
8
+ describe Vigilem::Evdev::System::KeymapLoaders, :clean_up_test_cache do
9
+
10
+ describe '::load_key_map' do
11
+ it 'raises an error if a keymap cannot be loaded' do
12
+ described_class.all = []
13
+ expect { described_class.exec }.to raise_error(NotImplementedError)
14
+ end
15
+
16
+ it 'loads a key_map attempting multiple sources' do
17
+ described_class.all += [described_class::KmapLoader.new, described_class::DumpkeysLoader.new]
18
+ expect(described_class.exec).to be_a Vigilem::Support::KeyMap
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ require 'vigilem/evdev/system/posix_types'
4
+
5
+ describe 'posix_types' do
6
+ it 'defines FFI type __kernel_long_t' do
7
+ expect(FFI::TypeDefs[:__kernel_long_t]).not_to be_nil
8
+ end
9
+ it 'defines FFI type __kernel_time_t' do
10
+ expect(FFI::TypeDefs[:__kernel_time_t]).not_to be_nil
11
+ end
12
+ it 'defines FFI type __kernel_suseconds_t' do
13
+ expect(FFI::TypeDefs[:__kernel_suseconds_t]).not_to be_nil
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ require 'vigilem/evdev/system/time'
4
+
5
+ describe Vigilem::Evdev::Time do
6
+
7
+ describe described_class::Timeval do
8
+ describe 'structure' do
9
+ it 'will respond_to #tv_sec' do
10
+ expect(subject).to respond_to(:tv_sec)
11
+ end
12
+
13
+ it 'will respond_to #tv_usec' do
14
+ expect(subject).to respond_to(:tv_usec)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,57 @@
1
+ require 'vigilem/evdev/transfer_agent'
2
+
3
+ describe Vigilem::Evdev::TransferAgent do
4
+
5
+ after(:each) do
6
+ [(v = ::Vigilem)::Evdev::Multiplexer, v::Evdev::Demultiplexer,
7
+ v::Core::Multiplexer, v::Core::Demultiplexer, v::Core::TransferAgent,
8
+ described_class].each do |klass|
9
+ klass.instance_variables.each {|ivar| klass.send(:remove_instance_variable, ivar) }
10
+ end
11
+ end
12
+
13
+ describe '::acquire' do
14
+
15
+ let(:singleton_var_name) { :@transfer_agent }
16
+
17
+ context 'none exists and called with no args' do
18
+ it 'the class instance variable will be nil initially' do
19
+ expect(described_class.instance_variable_get(singleton_var_name)).to be_nil
20
+ end
21
+
22
+ it 'creates a new one' do
23
+ allow(described_class).to receive(:new).and_call_original
24
+ expect(described_class).to receive(:new)
25
+ expect(described_class.acquire()).to be_a described_class
26
+ end
27
+
28
+ it 'sets the class instance variable' do
29
+ described_class.acquire
30
+ expect(described_class.instance_variable_get(singleton_var_name)).not_to be_nil
31
+ end
32
+ end
33
+
34
+ context 'none exists and called with args' do
35
+ it 'creates a new one with given args' do
36
+ allow(described_class).to receive(:new).and_call_original
37
+ expect(described_class).to receive(:new)
38
+ a = []
39
+ expect(described_class.acquire(inputs: [a])).to match(
40
+ an_object_having_attributes(
41
+ :demultiplexer => instance_of(Vigilem::Evdev::Demultiplexer),
42
+ :multiplexer => an_object_having_attributes(:inputs => [a])
43
+ )
44
+ )
45
+ end
46
+ end
47
+
48
+ context 'one exists' do
49
+
50
+ it 'grabs the existing one' do
51
+ expect(described_class.acquire).to eql(described_class.instance_variable_get(singleton_var_name))
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,282 @@
1
+ require 'spec_helper'
2
+
3
+ require 'vigilem/evdev/vty_context_filter'
4
+
5
+ require 'vigilem/evdev/system/input'
6
+
7
+ # @todo based on this system keymap, need to "double"
8
+ describe Vigilem::Evdev::VTYContextFilter, :clean_up_test_cache do
9
+
10
+ let(:key_map_class) { Vigilem::Support::KeyMap }
11
+
12
+ describe '::console_keys' do
13
+ it 'gets all the /console_\d+/i keys from the keymap' do
14
+ cmap = described_class.console_keys(Vigilem::Evdev.key_map)
15
+ expect(cmap.values.all? {|v| v =~ /console_\d+/i}).to be_truthy
16
+ end
17
+ end
18
+
19
+ describe 'instance-level' do
20
+
21
+ let(:key_num) { 65 }
22
+
23
+ let(:keycode) { subject.keysym_or_keycode("keycode#{key_num}") }
24
+
25
+ let(:alt_key_num) { 56 }
26
+
27
+ let(:alt_key_sym) { subject.keysym_or_keycode(alt_key_num) }
28
+
29
+ let(:shift_key_sym) { subject.keysym_or_keycode(42) }
30
+
31
+ describe '#initialize' do
32
+
33
+ it %q<initialize's #current_console_num, #current_console_keys, #other_console_keys> do
34
+
35
+ expect([
36
+ subject.current_console_num,
37
+ subject.current_console_keys,
38
+ subject.other_console_keys
39
+ ]).to match [
40
+ a_kind_of(Integer), a_kind_of(key_map_class), a_kind_of(key_map_class)
41
+ ]
42
+ end
43
+
44
+ end
45
+
46
+ describe '#key_map' do
47
+ it 'the default is to return Evdev.key_map' do
48
+ expect(subject.key_map).to eql(Vigilem::Evdev.key_map)
49
+ end
50
+
51
+ class FakeKmapLoader
52
+ end
53
+
54
+ it 'can be changed by the argument sent in to initialize' do
55
+ arg = Vigilem::Support::KeyMap.new({})
56
+ arg.metadata[:loader] = FakeKmapLoader.new
57
+ inst = described_class.new(arg)
58
+ expect(inst.key_map).to eql(arg)
59
+ end
60
+ end
61
+
62
+ describe '#keysym' do
63
+ context 'key_map.metadata[:loader].class.name =~ /KmapLoader/' do
64
+ it 'converts a keycode to keysym' do
65
+ expect(subject.keysym("keycode#{alt_key_num}")).to eql(alt_key_sym)
66
+ end
67
+ end
68
+ context 'key_map.metadata[:loader].class.name =~ /DumpkeysLoader/' do
69
+ it 'converts a keycode to keysym' do
70
+ a = Vigilem::Evdev::System::KeymapLoaders::DumpkeysLoader.new.exec
71
+ described_class.new(a)
72
+ expect(subject.keysym("keycode#{alt_key_num}")).to eql(alt_key_sym)
73
+ end
74
+ end
75
+ end
76
+
77
+ describe '#keysym_or_keycode' do
78
+ #it '' do
79
+
80
+ #end
81
+ end
82
+
83
+ describe '#add_key' do
84
+ it 'adds keys to the current list of keys' do
85
+ subject.add_key(keycode)
86
+ expect(subject.current_keys).to eql([keycode])
87
+ end
88
+ end
89
+
90
+ describe '#remove_key' do
91
+ it 'removes a key from the #current_keys' do
92
+ subject.add_key(alt_key_sym)
93
+ subject.add_key(shift_key_sym)
94
+ subject.add_key(keycode)
95
+ subject.remove_key(alt_key_sym)
96
+ expect(subject.current_keys).not_to include(alt_key_sym)
97
+ end
98
+ end
99
+
100
+ describe '#reverted_vty?' do
101
+ it 'returns if #was_on? and #current_keys matches one of #current_console_keys' do
102
+ subject.send(:was_on=, true)
103
+ subject.current_keys.replace(["control", "alt", "keycode88"])
104
+
105
+ subject.current_console_keys[["control", "alt", "keycode88"]] = "Console_12"
106
+ expect(subject.reverted_vty?).to be_truthy
107
+ end
108
+ end
109
+
110
+ describe '#changed_vty?' do
111
+ it 'returns if #was_off? and #current_keys matches one of #other_console_keys' do
112
+ subject.send(:was_off=, true)
113
+ subject.current_keys.replace(["control", "alt", "keycode88"])
114
+
115
+ subject.other_console_keys[["control", "alt", "keycode88"]] = "Console_12"
116
+ expect(subject.changed_vty?).to be_truthy
117
+ end
118
+ end
119
+
120
+ describe '#on?' do
121
+ it 'checks is the vty changed' do
122
+ allow(subject).to receive(:changed_vty?) { false }
123
+ allow(subject).to receive(:reverted_vty?) { false }
124
+ expect(subject).to receive(:changed_vty?)
125
+ subject.on?
126
+ end
127
+
128
+ it 'checks is the vty changed reverted back' do
129
+ allow(subject).to receive(:changed_vty?) { false }
130
+ allow(subject).to receive(:reverted_vty?) { false }
131
+ expect(subject).to receive(:reverted_vty?)
132
+ subject.on?
133
+ end
134
+
135
+ it 'will call on_change with the new status when #changed_vty? == true' do
136
+ allow(subject).to receive(:changed_vty?) { true }
137
+ allow(subject).to receive(:reverted_vty?) { false }
138
+ expect(subject).to receive(:on_change) { described_class::ON }
139
+ subject.on?
140
+ end
141
+
142
+ it 'will call on_change with the new status when #reverted_vty? == true' do
143
+ allow(subject).to receive(:changed_vty?) { false }
144
+ allow(subject).to receive(:reverted_vty?) { true }
145
+ expect(subject).to receive(:on_change) { described_class::OFF }
146
+ subject.on?
147
+ end
148
+ end
149
+
150
+ describe '#off?' do
151
+ it 'performs the same actions as #on?' do
152
+ allow(subject).to receive(:on?)
153
+ expect(subject).to receive(:on?)
154
+ subject.off?
155
+ end
156
+
157
+ it 'inverts the result of #on?' do
158
+ expect(subject.off?).to eql(!subject.on?)
159
+ end
160
+ end
161
+
162
+ context 'private' do
163
+ describe '#current_keys_hash_cache' do
164
+ it 'defaults to the #current_keys.hash' do
165
+ expect(subject.send(:current_keys_hash_cache)).to eql(subject.current_keys.hash)
166
+ end
167
+ end
168
+
169
+ describe '#current_keys_changed?' do
170
+ it 'returns false when the #hash of #current_keys has not changed' do
171
+ expect(subject.send(:current_keys_changed? )).to be_falsey
172
+ end
173
+
174
+ it 'returns true when the #hash of #current_keys changed' do
175
+ subject.current_keys << 'f7'
176
+ expect(subject.send(:current_keys_changed? )).to be_truthy
177
+ end
178
+
179
+ end
180
+
181
+ describe '#current_keys_downcase' do
182
+ it 'gets the downcase of all #current_keys' do
183
+ subject.instance_variable_set(:@current_keys, %w(Alt Control keycode63))
184
+ expect(subject.send(:current_keys_downcase)).to eql(%w(alt control keycode63))
185
+ end
186
+
187
+ it 'changes when #current_keys changes' do
188
+ lower = subject.send(:current_keys_downcase)
189
+ subject.current_keys.replace(%w(Alt Control keycode63))
190
+ expect(lower).not_to eql(subject.send(:current_keys_downcase))
191
+ end
192
+ end
193
+
194
+ describe '#allow_release?' do
195
+ it 'determines whether the event can be released while #on?' do
196
+ allow(subject).to receive(:on?) { true }
197
+ subject.send(:filter_ommisions=, [shift_key_sym.downcase])
198
+ expect(subject.send(:allow_release?, shift_key_sym.downcase)).to be_truthy
199
+ end
200
+
201
+ it 'determines whether the event can be released while #off?' do
202
+ allow(subject).to receive(:on?) { false }
203
+ subject.send(:filter_ommisions=, [shift_key_sym.downcase])
204
+ expect(subject.send(:allow_release?, shift_key_sym.downcase)).to be_falsey
205
+ end
206
+ end
207
+
208
+ describe '#filter_ommisions=, #filter_ommisions' do
209
+ it '#filter_ommisions=, sets #filter_ommisions' do
210
+ subject.send(:filter_ommisions=, [shift_key_sym.downcase])
211
+ expect(subject.send(:filter_ommisions)).to eql([shift_key_sym.downcase])
212
+ end
213
+ end
214
+
215
+ end #private
216
+
217
+ describe '#current_keys' do
218
+ it 'defaults to []' do
219
+ expect(subject.current_keys).to eql([])
220
+ end
221
+
222
+ it 'updates @current_keys_hash_cache' do
223
+ ckhc = subject.instance_variable_get(:@current_keys_hash_cache)
224
+ subject.current_keys
225
+ expect(ckhc).not_to eql(subject.instance_variable_get(:@current_keys_hash_cache))
226
+ end
227
+ end
228
+
229
+ describe '#process' do
230
+
231
+ TestInput = Vigilem::Evdev::System::Input
232
+
233
+ let(:syn_1_event) { TestInput::Event[[12, 9], TestInput::EV_SYN, 1, 1] }
234
+
235
+ let(:syn_2_event) { TestInput::Event[[7, 8], TestInput::EV_SYN, 0, 0] }
236
+
237
+ it 'passes all non EV_KEY events if off? == true' do
238
+ allow(subject).to receive(:off?) { true }
239
+ events = [syn_1_event, syn_2_event]
240
+ expect(subject.process(*events)).to eql(events)
241
+ end
242
+
243
+ let(:key_a_event) { TestInput::Event[[12, 9], TestInput::EV_KEY, TestInput::KEY_LEFTSHIFT, 1] }
244
+
245
+ let(:key_b_event) { TestInput::Event[[7, 8], TestInput::EV_KEY, TestInput::KEY_LEFTALT, 0] }
246
+
247
+ it 'passes on EV_KEY events if off? == true and not in filter_ommisions' do
248
+ allow(subject).to receive(:off?) { true }
249
+ events = [key_a_event, key_b_event]
250
+ subject.send(:filter_ommisions=, [])
251
+ expect(subject.process(*events)).to eql(events)
252
+ end
253
+
254
+ it 'filters out EV_KEY events if off? == false and not in filter_ommisions' do
255
+ allow(subject).to receive(:off?) { false }
256
+ events = [key_a_event, key_b_event]
257
+ subject.send(:filter_ommisions=, [])
258
+ expect(subject.process(*events)).to eql([])
259
+ end
260
+
261
+ it 'passes on EV_KEY events if on? == true and in filter_ommisions and value == 0' do
262
+ allow(subject).to receive(:off?) { false }
263
+ allow(subject).to receive(:on?) { true }
264
+ events = [key_a_event, key_b_event]
265
+ subject.send(:filter_ommisions=, [alt_key_sym.downcase])
266
+ expect(subject.process(*events)).to eql([key_b_event])
267
+ end
268
+
269
+ it 'filters on EV_KEY events if off? == true and in filter_ommisions and value == 0' do
270
+ allow(subject).to receive(:off?) { true }
271
+ events = [key_a_event, key_b_event]
272
+
273
+ subject.send(:filter_ommisions=, [alt_key_sym.downcase])
274
+
275
+ expect(subject.process(*events)).to eql([key_a_event])
276
+ end
277
+
278
+ end
279
+
280
+ end
281
+
282
+ end