redstruct 0.1.7 → 0.2.0
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.
- checksums.yaml +4 -4
- data/README.md +15 -11
- data/Rakefile +5 -5
- data/lib/redstruct/all.rb +14 -0
- data/lib/redstruct/configuration.rb +9 -6
- data/lib/redstruct/connection_proxy.rb +123 -0
- data/lib/redstruct/counter.rb +96 -0
- data/lib/redstruct/error.rb +2 -0
- data/lib/redstruct/factory/object.rb +31 -0
- data/lib/redstruct/factory.rb +94 -55
- data/lib/redstruct/hash.rb +123 -0
- data/lib/redstruct/list.rb +315 -0
- data/lib/redstruct/lock.rb +183 -0
- data/lib/redstruct/script.rb +104 -0
- data/lib/redstruct/set.rb +155 -0
- data/lib/redstruct/sorted_set/slice.rb +124 -0
- data/lib/redstruct/sorted_set.rb +153 -0
- data/lib/redstruct/string.rb +66 -0
- data/lib/redstruct/struct.rb +87 -0
- data/lib/redstruct/utils/coercion.rb +14 -8
- data/lib/redstruct/utils/inspectable.rb +8 -4
- data/lib/redstruct/utils/iterable.rb +52 -0
- data/lib/redstruct/utils/scriptable.rb +32 -6
- data/lib/redstruct/version.rb +4 -1
- data/lib/redstruct.rb +17 -51
- data/lib/yard/defscript_handler.rb +5 -3
- data/test/redstruct/configuration_test.rb +13 -0
- data/test/redstruct/connection_proxy_test.rb +85 -0
- data/test/redstruct/counter_test.rb +108 -0
- data/test/redstruct/factory/object_test.rb +21 -0
- data/test/redstruct/factory_test.rb +136 -0
- data/test/redstruct/hash_test.rb +138 -0
- data/test/redstruct/list_test.rb +244 -0
- data/test/redstruct/lock_test.rb +108 -0
- data/test/redstruct/script_test.rb +53 -0
- data/test/redstruct/set_test.rb +219 -0
- data/test/redstruct/sorted_set/slice_test.rb +10 -0
- data/test/redstruct/sorted_set_test.rb +219 -0
- data/test/redstruct/string_test.rb +8 -0
- data/test/redstruct/struct_test.rb +61 -0
- data/test/redstruct/utils/coercion_test.rb +33 -0
- data/test/redstruct/utils/inspectable_test.rb +31 -0
- data/test/redstruct/utils/iterable_test.rb +94 -0
- data/test/redstruct/utils/scriptable_test.rb +67 -0
- data/test/redstruct_test.rb +14 -0
- data/test/test_helper.rb +77 -1
- metadata +58 -26
- data/lib/redstruct/connection.rb +0 -47
- data/lib/redstruct/factory/creation.rb +0 -95
- data/lib/redstruct/factory/deserialization.rb +0 -7
- data/lib/redstruct/hls/lock.rb +0 -175
- data/lib/redstruct/hls/queue.rb +0 -29
- data/lib/redstruct/hls.rb +0 -2
- data/lib/redstruct/types/base.rb +0 -36
- data/lib/redstruct/types/counter.rb +0 -65
- data/lib/redstruct/types/hash.rb +0 -72
- data/lib/redstruct/types/list.rb +0 -76
- data/lib/redstruct/types/script.rb +0 -56
- data/lib/redstruct/types/set.rb +0 -96
- data/lib/redstruct/types/sorted_set.rb +0 -129
- data/lib/redstruct/types/string.rb +0 -64
- data/lib/redstruct/types/struct.rb +0 -58
- data/lib/releaser/logger.rb +0 -15
- data/lib/releaser/repository.rb +0 -32
- data/lib/tasks/release.rake +0 -49
- data/test/redstruct/restruct_test.rb +0 -4
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
module Redstruct
|
6
|
+
class HashTest < Redstruct::Test
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
@factory = create_factory
|
10
|
+
@hash = @factory.hashmap('hash')
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_brackets
|
14
|
+
value = SecureRandom.hex(4)
|
15
|
+
assert_nil @hash['test'], 'should return nil for non-existent element'
|
16
|
+
@hash['test'] = value
|
17
|
+
assert_equal value, @hash['test'], 'should return the correct value'
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_get_one
|
21
|
+
value = SecureRandom.hex(4)
|
22
|
+
assert_nil @hash.get('a'), 'should return nil for non-existent element'
|
23
|
+
@hash['a'] = value
|
24
|
+
assert_equal value, @hash.get('a'), 'should return correct value'
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_get_multiple
|
28
|
+
hash = { 'a' => SecureRandom.hex(4), 'b' => SecureRandom.hex(4) }
|
29
|
+
assert_equal({}, @hash.get('a', 'b'), 'should return a empty hash for non existent keys')
|
30
|
+
@hash.update(hash)
|
31
|
+
assert_equal hash, @hash.get('a', 'b'), 'should return the correct hash for requested keys'
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_set
|
35
|
+
value = SecureRandom.hex(4)
|
36
|
+
assert_nil @hash['a'], 'should return nothing'
|
37
|
+
@hash.set('a', value)
|
38
|
+
assert_equal value, @hash['a'], 'should return the correct value'
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_set_overwrite
|
42
|
+
initial = SecureRandom.hex(4)
|
43
|
+
updated = SecureRandom.hex(4)
|
44
|
+
|
45
|
+
@hash.set('a', initial)
|
46
|
+
@hash.set('a', updated, overwrite: false)
|
47
|
+
assert_equal initial, @hash['a'], 'should not have overwritten the initial value'
|
48
|
+
@hash.set('a', updated, overwrite: true)
|
49
|
+
assert_equal updated, @hash['a'], 'should have overwritten the initial value'
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_update
|
53
|
+
initial = { 'a' => SecureRandom.hex(4), 'b' => SecureRandom.hex(4) }
|
54
|
+
assert @hash.empty?, 'initial should be empty'
|
55
|
+
@hash.update(initial)
|
56
|
+
assert_equal initial, @hash.to_h, 'should have been updated accordingly'
|
57
|
+
|
58
|
+
updated = { 'a' => SecureRandom.hex(4), 'c' => SecureRandom.hex(4) }
|
59
|
+
@hash.update(updated)
|
60
|
+
assert_equal initial.merge(updated), @hash.to_h, 'should have been updated correctly'
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_empty?
|
64
|
+
assert @hash.empty?, 'should initially be empty'
|
65
|
+
@hash['a'] = 1
|
66
|
+
refute @hash.empty?, 'should not be empty with one element'
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_remove
|
70
|
+
@hash['a'] = 'a'
|
71
|
+
assert @hash.key?('a'), 'should contain something for key a'
|
72
|
+
@hash.remove('a')
|
73
|
+
refute @hash.key?('a'), 'should not contain the key a anymore'
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_key?
|
77
|
+
refute @hash.key?('a'), 'should not contain the key a initially'
|
78
|
+
@hash['a'] = 1
|
79
|
+
assert @hash.key?('a'), 'should now contain the key a'
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_increment
|
83
|
+
assert_equal 1, @hash.increment('a'), 'initial increment should return 1'
|
84
|
+
assert_equal 2, @hash.increment('a'), 'second increment should return 2'
|
85
|
+
assert_equal 3.5, @hash.increment('a', by: 1.5), 'should return 3.5'
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_decrement
|
89
|
+
assert_equal(-1, @hash.decrement('a'), 'initial decrement should return -1')
|
90
|
+
assert_equal(-2, @hash.decrement('a'), 'second decrement should return -2')
|
91
|
+
assert_equal(-3.5, @hash.decrement('a', by: 1.5), 'should return -3.5')
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_keys
|
95
|
+
hash = { 'a' => 'b', 'b' => 'a' }
|
96
|
+
assert_equal [], @hash.keys, 'should initially return no keys initially'
|
97
|
+
@hash.update(hash)
|
98
|
+
assert_equal hash.keys, @hash.keys, 'should return the same keys after an update'
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_values
|
102
|
+
hash = { 'a' => 'b', 'b' => 'a' }
|
103
|
+
assert_equal [], @hash.values, 'should initially return no values initially'
|
104
|
+
@hash.update(hash)
|
105
|
+
assert_equal hash.values, @hash.values, 'should return the same values after an update'
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_to_h
|
109
|
+
hash = { 'a' => 'b', 'b' => 'a' }
|
110
|
+
assert_equal({}, @hash.to_h, 'should be an empty hash initially')
|
111
|
+
@hash.update(hash)
|
112
|
+
assert_equal hash, @hash.to_h, 'should return the whole hash as a standard ruby hash'
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_size
|
116
|
+
hash = { 'a' => 'b', 'b' => 'a' }
|
117
|
+
assert_equal 0, @hash.size, 'should be an empty hash initially'
|
118
|
+
@hash.update(hash)
|
119
|
+
assert_equal 2, @hash.size, 'should return the correct amount of pairs'
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_each
|
123
|
+
hash = { 'a' => 'b', 'b' => 'a' }
|
124
|
+
keys = hash.keys
|
125
|
+
values = hash.values
|
126
|
+
|
127
|
+
@hash.update(hash)
|
128
|
+
@hash.each do |key, value|
|
129
|
+
keys.delete(key)
|
130
|
+
values.delete(value)
|
131
|
+
assert_equal hash[key], value, 'should return the correct key-value-pair'
|
132
|
+
end
|
133
|
+
|
134
|
+
assert_empty keys, 'should have no more keys left to match'
|
135
|
+
assert_empty values, 'should have no more values to match'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
module Redstruct
|
6
|
+
class ListTest < Redstruct::Test
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
@factory = create_factory
|
10
|
+
@list = @factory.list('list')
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_clear
|
14
|
+
@list.append(1, 2, 3)
|
15
|
+
refute @list.empty?, 'should not be empty'
|
16
|
+
@list.clear
|
17
|
+
assert @list.empty?, 'should be empty after a clear operation'
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_empty?
|
21
|
+
assert @list.empty?, 'should be initially empty'
|
22
|
+
@list.push(1)
|
23
|
+
refute @list.empty?, 'should not be empty anymore'
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_brackets
|
27
|
+
(0..2).each do |i|
|
28
|
+
value = SecureRandom.hex(4)
|
29
|
+
assert_nil @list[i], 'should return nothing initially'
|
30
|
+
@list[i] = value
|
31
|
+
assert_equal value, @list[i], 'should return the correct value'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_insert_single
|
36
|
+
initial = SecureRandom.hex(4)
|
37
|
+
assert_raises(Redis::CommandError, 'should fail (out of bounds)') do
|
38
|
+
@list.insert(initial, 1)
|
39
|
+
end
|
40
|
+
|
41
|
+
assert @list.insert(initial, 0), 'should insert correctly first element'
|
42
|
+
assert_equal initial, @list[0]
|
43
|
+
|
44
|
+
assert @list.insert(initial, 1), 'should insert correctly second element'
|
45
|
+
assert_equal initial, @list[1]
|
46
|
+
|
47
|
+
value = SecureRandom.hex(4)
|
48
|
+
assert @list.insert(value, 1), 'should insert correctly between both'
|
49
|
+
assert_equal value, @list[1], 'should have new value at index 1'
|
50
|
+
assert_equal initial, @list[0], 'should still have correct value as index 0'
|
51
|
+
assert_equal initial, @list[2], 'should still have correct value as index 2'
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_append
|
55
|
+
values = %w[1 2]
|
56
|
+
assert_equal values.size, @list.append(*values), 'should have successfully appended'
|
57
|
+
assert_equal values, @list.to_a, 'should have the correct values stored'
|
58
|
+
|
59
|
+
appended = %w[3 4]
|
60
|
+
expected = values + appended
|
61
|
+
assert_equal expected.size, @list.append(*appended), 'should have successfully appended'
|
62
|
+
assert_equal expected, @list.to_a, 'should have the correct values stored'
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_append_exists
|
66
|
+
values = %w[1 2]
|
67
|
+
refute @list.append(*values, exists: true), 'should not append since the list does not exist'
|
68
|
+
|
69
|
+
@list[0] = 'a'
|
70
|
+
assert @list.append(*values, exists: true), 'should have appended once the list existed'
|
71
|
+
assert_equal %w[a 1 2], @list.to_a, 'should contain correct values'
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_append_max
|
75
|
+
values = %w[1 2]
|
76
|
+
assert @list.append(*values, max: 2), 'should append all elements'
|
77
|
+
assert_equal values, @list.to_a, 'should append all elements'
|
78
|
+
|
79
|
+
assert_equal 2, @list.append(3, max: 2), 'should still return the actual size of the list'
|
80
|
+
assert_equal values, @list.to_a, 'should not have appended the last element'
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_prepend
|
84
|
+
values = %w[1 2]
|
85
|
+
assert_equal values.size, @list.prepend(*values), 'should have successfully prepended'
|
86
|
+
assert_equal values, @list.to_a, 'should have the correct values stored'
|
87
|
+
|
88
|
+
prepended = %w[3 4]
|
89
|
+
expected = prepended + values
|
90
|
+
assert_equal expected.size, @list.prepend(*prepended), 'should have successfully prepended'
|
91
|
+
assert_equal expected, @list.to_a, 'should have the correct values stored'
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_prepend_exists
|
95
|
+
values = %w[1 2]
|
96
|
+
refute @list.prepend(*values, exists: true), 'should not prepend since the list does not exist'
|
97
|
+
|
98
|
+
@list[0] = 'a'
|
99
|
+
assert @list.prepend(*values, exists: true), 'should have prepended once the list existed'
|
100
|
+
assert_equal %w[1 2 a], @list.to_a, 'should contain correct values'
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_prepend_max
|
104
|
+
values = %w[1 2]
|
105
|
+
assert @list.prepend(*values, max: 2), 'should prepend all elements'
|
106
|
+
assert_equal values, @list.to_a, 'should append all elements'
|
107
|
+
|
108
|
+
assert_equal 2, @list.prepend(3, max: 2), 'should still return the actual size of the list'
|
109
|
+
assert_equal %w[3 1], @list.to_a, 'should not have prepended the last element'
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_pop_single
|
113
|
+
assert @list.empty?, 'should be empty initially'
|
114
|
+
@list.append('a', 'b')
|
115
|
+
|
116
|
+
assert_equal 'b', @list.pop, 'should have popped the last element'
|
117
|
+
assert_equal %w[a], @list.to_a, 'should have only one element left'
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_pop_multiple
|
121
|
+
assert @list.empty?, 'should be empty initially'
|
122
|
+
@list.append('a', 'b', 'c')
|
123
|
+
|
124
|
+
assert_equal %w[b c], @list.pop(2), 'should have popped the last 2 elements'
|
125
|
+
assert_equal %w[a], @list.to_a, 'should have only one element left'
|
126
|
+
end
|
127
|
+
|
128
|
+
# TODO: not the ideal way to test this, but what would be a better way?
|
129
|
+
def test_pop_timeout
|
130
|
+
assert @list.empty?, 'should be empty initially'
|
131
|
+
|
132
|
+
Thread.new do
|
133
|
+
sleep 0.2
|
134
|
+
@list.push('a', 'b')
|
135
|
+
end
|
136
|
+
|
137
|
+
assert_equal 'b', @list.pop(timeout: 3), 'should have returned the correct element'
|
138
|
+
assert_raises(ArgumentError, 'should not allow timeout with size > 1') do
|
139
|
+
@list.pop(5, timeout: 1)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_shift_single
|
144
|
+
assert @list.empty?, 'should be empty initially'
|
145
|
+
@list.append('a', 'b')
|
146
|
+
|
147
|
+
assert_equal 'a', @list.shift, 'should have shifted the first element'
|
148
|
+
assert_equal %w[b], @list.to_a, 'should have only one element left'
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_shift_multiple
|
152
|
+
assert @list.empty?, 'should be empty initially'
|
153
|
+
@list.append('a', 'b', 'c')
|
154
|
+
|
155
|
+
assert_equal %w[a b], @list.shift(2), 'should have shifted the first 2 elements'
|
156
|
+
assert_equal %w[c], @list.to_a, 'should have only one element left'
|
157
|
+
end
|
158
|
+
|
159
|
+
# TODO: not the ideal way to test this, but what would be a better way?
|
160
|
+
def test_shift_timeout
|
161
|
+
assert @list.empty?, 'should be empty initially'
|
162
|
+
|
163
|
+
Thread.new do
|
164
|
+
sleep 0.2
|
165
|
+
@list.push('a', 'b')
|
166
|
+
end
|
167
|
+
|
168
|
+
assert_equal 'a', @list.shift(timeout: 3), 'should have returned the correct element'
|
169
|
+
assert_raises(ArgumentError, 'should not allow timeout with size > 1') do
|
170
|
+
@list.shift(5, timeout: 1)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_remove_left
|
175
|
+
@list.append('a', 'b', 'a', 'b', 'a', 'b')
|
176
|
+
assert_equal 1, @list.remove('a', count: 1), 'should remove 1 element equal to the value from left'
|
177
|
+
assert_equal %w[b a b a b], @list.to_a, 'should have removed first a only'
|
178
|
+
assert_equal 2, @list.remove('b', count: 2), 'should remove both bs'
|
179
|
+
assert_equal %w[a a b], @list.to_a, 'should have only the last b left'
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_remove_right
|
183
|
+
@list.append('a', 'b', 'a', 'b', 'a', 'b')
|
184
|
+
assert_equal 1, @list.remove('a', count: -1), 'should remove 1 element equal to the value from the right'
|
185
|
+
assert_equal %w[a b a b b], @list.to_a, 'should have removed last a only'
|
186
|
+
assert_equal 2, @list.remove('b', count: -2), 'should remove the last 2 bs'
|
187
|
+
assert_equal %w[a b a], @list.to_a, 'should have only the middle b left'
|
188
|
+
end
|
189
|
+
|
190
|
+
def test_remove_all
|
191
|
+
@list.append('a', 'b', 'b', 'a')
|
192
|
+
assert_equal 2, @list.remove('a', count: 0), 'should remove all elements equal to the given value'
|
193
|
+
assert_equal %w[b b], @list.to_a, 'should have only the other values left'
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_size
|
197
|
+
assert_equal 0, @list.size, 'should have size 0 initially'
|
198
|
+
@list.push(1, 2)
|
199
|
+
assert_equal 2, @list.size, 'should have the same amount that was pushed'
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_to_a
|
203
|
+
expected = %w[a b c]
|
204
|
+
assert_equal [], @list.to_a, 'should return empty array initially'
|
205
|
+
@list.push(*expected)
|
206
|
+
assert_equal expected, @list.to_a, 'should return what was pushed'
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_slice_positive
|
210
|
+
values = %w[a b c d e f g]
|
211
|
+
assert_equal [], @list.slice, 'should return nothing initially'
|
212
|
+
@list.push(*values)
|
213
|
+
|
214
|
+
assert_equal values.slice(0, 1), @list.slice(start: 0, length: 1), 'should return the same as Array#slice'
|
215
|
+
assert_equal values.slice(2, 3), @list.slice(start: 2, length: 3), 'should return the same as Array#slice'
|
216
|
+
end
|
217
|
+
|
218
|
+
def test_slice_negative
|
219
|
+
values = %w[a b c d e f g]
|
220
|
+
assert_equal [], @list.slice, 'should return nothing initially'
|
221
|
+
@list.push(*values)
|
222
|
+
|
223
|
+
assert_equal values, @list.slice(start: 0, length: -1), 'should return the same as Array#slice'
|
224
|
+
assert_equal values[2..-2], @list.slice(start: 2, length: -2), 'should return the same as Array#slice'
|
225
|
+
end
|
226
|
+
|
227
|
+
# Blocking is not tested as I'm still unsure what's a good way to test it
|
228
|
+
def test_popshift
|
229
|
+
assert_raises(ArgumentError, 'should not be able to push on something that is not a list') do
|
230
|
+
@list.popshift(2)
|
231
|
+
end
|
232
|
+
|
233
|
+
values = %w[a b c]
|
234
|
+
list2 = @factory.list('list2')
|
235
|
+
|
236
|
+
@list.push(*values)
|
237
|
+
assert_equal 'c', @list.popshift(list2), 'should have popped the last element'
|
238
|
+
assert_equal %w[c], list2.to_a, 'should contain the popped element'
|
239
|
+
|
240
|
+
assert_equal 'b', @list.popshift(list2), 'should have popped the last element'
|
241
|
+
assert_equal %w[b c], list2.to_a, 'should contain the new popped element as its first element'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
module Redstruct
|
6
|
+
class LockTest < Redstruct::Test
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
@factory = create_factory
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_initialize
|
13
|
+
resource = 'resource'
|
14
|
+
lock = create(resource)
|
15
|
+
|
16
|
+
assert_equal resource, lock.resource, 'should be locking the correct resource'
|
17
|
+
assert_nil lock.token, 'should not hold any tokens at the moment'
|
18
|
+
assert_equal Redstruct::Lock::DEFAULT_EXPIRY, lock.expiry, 'should have the default expiry'
|
19
|
+
assert_equal Redstruct::Lock::DEFAULT_TIMEOUT, lock.timeout, 'should have the default timeout'
|
20
|
+
|
21
|
+
expiry = rand
|
22
|
+
timeout = rand(10)
|
23
|
+
lock = create(timeout: timeout, expiry: expiry)
|
24
|
+
assert_equal expiry, lock.expiry, 'should have the correct expiry'
|
25
|
+
assert_equal timeout, lock.timeout, 'should have the correct timeout'
|
26
|
+
|
27
|
+
lock = create(timeout: Float::INFINITY)
|
28
|
+
assert_equal 0, lock.timeout, 'should have a timeout of 0 when given infinity'
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_acquire
|
32
|
+
resource = 'resource'
|
33
|
+
lock = create(resource)
|
34
|
+
|
35
|
+
f1 = Fiber.new do
|
36
|
+
lock1 = create(resource)
|
37
|
+
Fiber.yield lock1.acquire
|
38
|
+
Fiber.yield lock1.release
|
39
|
+
Fiber.yield lock1.acquire
|
40
|
+
end
|
41
|
+
|
42
|
+
f2 = Fiber.new do
|
43
|
+
lock2 = create(resource)
|
44
|
+
Fiber.yield lock2.acquire
|
45
|
+
Fiber.yield lock2.acquire
|
46
|
+
Fiber.yield lock2.release
|
47
|
+
end
|
48
|
+
|
49
|
+
assert f1.resume, 'should have successfully acquired the lock'
|
50
|
+
refute f2.resume, 'should have failed to acquire the lock'
|
51
|
+
assert f1.resume, 'should have released the lock'
|
52
|
+
assert f2.resume, 'should have acquired the lock'
|
53
|
+
refute f1.resume, 'should have failed to acquire the lock'
|
54
|
+
refute lock.acquire, 'should have failed to acquire the lock'
|
55
|
+
assert f2.resume, 'should have released the lock'
|
56
|
+
assert lock.acquire, 'should have successfully acquired the lock'
|
57
|
+
assert lock.release, 'should have released the lock'
|
58
|
+
end
|
59
|
+
|
60
|
+
# To avoid actually blocking, we simply test that the method is called
|
61
|
+
# without actually calling it. The non-blocking tests should be
|
62
|
+
# sufficient for the actual locking logic.
|
63
|
+
def test_acquire_blocking
|
64
|
+
resource = 'resource'
|
65
|
+
lock = create(resource, expiry: 1)
|
66
|
+
lock2 = create(resource, timeout: 1)
|
67
|
+
|
68
|
+
tokens = lock2.instance_eval { @tokens }
|
69
|
+
ensure_command_called(tokens, :brpop, { timeout: lock2.timeout }, allow: false).and_return(nil)
|
70
|
+
|
71
|
+
assert lock.acquire, 'should have acquired the lock'
|
72
|
+
refute lock2.acquire
|
73
|
+
refute lock2.release, 'should not release something not acquired'
|
74
|
+
assert lock.release, 'should release what was acquired'
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_release
|
78
|
+
lock = create
|
79
|
+
refute lock.release, 'should not be able to release if nothing was acquired'
|
80
|
+
assert lock.acquire, 'should acquire the lock'
|
81
|
+
refute_nil lock.token, 'should have some token'
|
82
|
+
assert lock.release, 'should release the acquired lock'
|
83
|
+
assert_nil lock.token, 'should have no token once released'
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_locked
|
87
|
+
resource = 'resource'
|
88
|
+
lock = create(resource)
|
89
|
+
lock2 = create(resource)
|
90
|
+
|
91
|
+
assert lock2.acquire, 'should be able to acquire free lock'
|
92
|
+
refute(lock.locked { raise 'should not have been able to lock!' })
|
93
|
+
assert lock2.release, 'should be able to release acquired lock'
|
94
|
+
|
95
|
+
executed = false
|
96
|
+
assert(lock.locked { executed = true }, 'should have acquired the lock')
|
97
|
+
assert executed, 'should have executed inner block'
|
98
|
+
assert_nil lock.token, 'should have released previous token'
|
99
|
+
refute lock.release, 'should not be able to release lock since it was already released'
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def create(resource = nil, **options)
|
105
|
+
return @factory.lock(resource || SecureRandom.hex(4), **options)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
module Redstruct
|
6
|
+
class ScriptTest < Redstruct::Test
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
@value = @@counter.incr
|
10
|
+
@code = "return #{@value}"
|
11
|
+
@factory = create_factory
|
12
|
+
@script = @factory.script(@code)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_initialize
|
16
|
+
assert_equal @code, @script.script, 'should have correct script'
|
17
|
+
assert_equal Digest::SHA1.hexdigest(@code), @script.sha1, 'should have correct sha1'
|
18
|
+
assert_equal @factory.connection, @script.connection, 'should have correct connection'
|
19
|
+
|
20
|
+
script = @factory.script(@code, sha1: 'dummy sha1')
|
21
|
+
assert_equal 'dummy sha1', script.sha1, 'should have accepted our dummy sha1 even if incorrect'
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_script=
|
25
|
+
lua = 'return -1'
|
26
|
+
old_sha1 = @script.sha1
|
27
|
+
new_sha1 = Digest::SHA1.hexdigest(lua)
|
28
|
+
|
29
|
+
@script.script = lua
|
30
|
+
assert_equal lua, @script.script, 'should have correctly assigned the new code'
|
31
|
+
assert_equal new_sha1, @script.sha1, 'should have updated the sha1'
|
32
|
+
refute_equal old_sha1, @script.sha1, 'should have a different sha1 now'
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_exists?
|
36
|
+
refute @script.exists?, 'should not initially exists'
|
37
|
+
@script.load
|
38
|
+
assert @script.exists?, 'script should exists after loading it'
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_load
|
42
|
+
refute @script.exists?, 'should not initially exists'
|
43
|
+
assert_equal @script.sha1, @script.load, 'should return the sha1 of the script'
|
44
|
+
assert @script.exists?, 'should exist after load'
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_eval
|
48
|
+
refute @script.exists?, 'should not exist initially'
|
49
|
+
assert_equal @value, @script.eval, "should execute the script (which returns #{@value})"
|
50
|
+
assert @script.exists?, 'should exist after first evaluation'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|