vigilem-evdev 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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