forked from rubocop/rubocop
/
compound_hash_spec.rb
203 lines (177 loc) · 5.97 KB
/
compound_hash_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# frozen_string_literal: true
RSpec.describe RuboCop::Cop::Security::CompoundHash, :config do
it 'registers an offense when using XOR operator in the implementation of the hash method' do
expect_offense(<<~RUBY)
def hash
1.hash ^ 2.hash ^ 3.hash
^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR operator in the implementation of the hash method, even without sub-calls to hash' do
expect_offense(<<~RUBY)
def hash
1 ^ 2 ^ 3
^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR operator in the implementation of the hash singleton method' do
expect_offense(<<~RUBY)
def object.hash
1.hash ^ 2.hash ^ 3.hash
^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR operator in the implementation of a dynamic hash method' do
expect_offense(<<~RUBY)
define_method(:hash) do
1.hash ^ 2.hash ^ 3.hash
^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR operator in the implementation of a dynamic hash singleton method' do
expect_offense(<<~RUBY)
define_singleton_method(:hash) do
1.hash ^ 2.hash ^ 3.hash
^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when delegating to Array#hash for a single value' do
expect_offense(<<~RUBY)
def hash
[1].hash
^^^^^^^^ Delegate hash directly without wrapping in an array when only using a single value
end
RUBY
end
it 'registers an offense if .hash is called on any elements of a hashed array' do
expect_offense(<<~RUBY)
[1, 2.hash, 3].hash
^^^^^^ Calling .hash on elements of a hashed array is redundant
RUBY
end
it 'does not register an offense when delegating to Array#hash' do
expect_no_offenses(<<~RUBY)
def hash
[1, 2, 3].hash
end
RUBY
end
it 'does not register an offense when delegating to a single object' do
expect_no_offenses(<<~RUBY)
def hash
1.hash
end
RUBY
end
it 'registers an offense when using XOR operator in the implementation of the hash method, even if intermediate variable is used' do
expect_offense(<<~RUBY)
def hash
value = 1.hash ^ 2.hash ^ 3.hash
^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
value
end
RUBY
end
it 'registers an offense when using XOR assignment operator in the implementation of the hash method' do
expect_offense(<<~RUBY)
def hash
h = 0
things.each do |thing|
h ^= thing.hash
^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
h
end
RUBY
end
it 'registers an offense when using addition assignment operator in the implementation of the hash method' do
expect_offense(<<~RUBY)
def hash
h = 0
things.each do |thing|
h += thing.hash
^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
h
end
RUBY
end
it 'registers an offense when using multiplication assignment operator in the implementation of the hash method' do
expect_offense(<<~RUBY)
def hash
h = 0
things.each do |thing|
h *= thing.hash
^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
h
end
RUBY
end
it 'registers an offense when using addition in the implementation of the hash method' do
expect_offense(<<~RUBY)
def hash
foo.hash + bar.hash
^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using multiplication in the implementation of the hash method' do
expect_offense(<<~RUBY)
def hash
to_s.hash * -1
^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR between an array hash and a class' do
expect_offense(<<~RUBY)
def hash
[red, blue, green, alpha].hash ^ self.class.hash
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR involving super' do
expect_offense(<<~RUBY)
def hash
foo.hash ^ super ^ bar.hash
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using XOR and bitshifts' do
expect_offense(<<~RUBY)
def hash
foo.hash ^ bar.hash << 1 ^ biz.hash << 2 ^ bar.hash << 3
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense when using bitshift and OR' do
expect_offense(<<~RUBY)
def hash
([@addr, @mask_addr, @zone_id].hash << 1) | (ipv4? ? 0 : 1)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
RUBY
end
it 'registers an offense for complex usage' do
expect_offense(<<~RUBY)
def hash
@hash ||= begin
hash_ = [@factory, geometry_type].hash
(0...num_geometries).inject(hash_) do |h_, i_|
(1664525 * h_ + geometry_n(i_).hash).hash
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `[...].hash` instead of combining hash values manually.
end
end
end
RUBY
end
end