zache 0.13.1 → 0.14.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.
data/test/test_zache.rb CHANGED
@@ -1,147 +1,138 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # (The MIT License)
4
- #
5
- # Copyright (c) 2018-2023 Yegor Bugayenko
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the 'Software'), to deal
9
- # in the Software without restriction, including without limitation the rights
10
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- # copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in all
15
- # copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
- # SOFTWARE.
3
+ # SPDX-FileCopyrightText: Copyright (c) 2018-2025 Yegor Bugayenko
4
+ # SPDX-License-Identifier: MIT
24
5
 
6
+ require 'concurrent'
25
7
  require 'minitest/autorun'
8
+ require 'securerandom'
26
9
  require 'threads'
27
10
  require 'timeout'
28
- require 'concurrent'
29
11
  require_relative '../lib/zache'
12
+ require_relative 'test__helper'
30
13
 
31
14
  Thread.report_on_exception = true
32
15
 
33
16
  # Cache test.
34
17
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
35
- # Copyright:: Copyright (c) 2018-2023 Yegor Bugayenko
18
+ # Copyright:: Copyright (c) 2018-2025 Yegor Bugayenko
36
19
  # License:: MIT
37
20
  class ZacheTest < Minitest::Test
38
21
  def test_caches
39
22
  cache = Zache.new(sync: false)
40
- first = cache.get(:hey, lifetime: 5) { Random.rand }
41
- second = cache.get(:hey) { Random.rand }
42
- assert(first == second)
23
+ first = cache.get(:hey, lifetime: 5) { rand }
24
+ second = cache.get(:hey) { rand }
25
+ assert_equal(first, second)
43
26
  assert_equal(1, cache.size)
44
27
  end
45
28
 
46
29
  def test_caches_and_expires
47
30
  cache = Zache.new
48
- first = cache.get(:hey, lifetime: 0.01) { Random.rand }
31
+ first = cache.get(:hey, lifetime: 0.01) { rand }
49
32
  sleep 0.1
50
- second = cache.get(:hey) { Random.rand }
51
- assert(first != second)
33
+ second = cache.get(:hey) { rand }
34
+ refute_equal(first, second)
52
35
  end
53
36
 
54
37
  def test_calculates_age
55
38
  cache = Zache.new
56
- cache.get(:hey) { Random.rand }
39
+ cache.get(:hey) { rand }
57
40
  sleep 0.1
58
- assert(cache.mtime(:hey) < Time.now - 0.05)
41
+ assert_operator(cache.mtime(:hey), :<, Time.now - 0.05)
59
42
  end
60
43
 
61
44
  def test_caches_in_threads
62
45
  cache = Zache.new
63
46
  Threads.new(10).assert(100) do
64
- cache.get(:hey, lifetime: 0.0001) { Random.rand }
47
+ cache.get(:hey, lifetime: 0.0001) { rand }
65
48
  end
66
49
  end
67
50
 
68
51
  def test_key_exists
69
52
  cache = Zache.new
70
- cache.get(:hey) { Random.rand }
53
+ cache.get(:hey) { rand }
71
54
  exists_result = cache.exists?(:hey)
72
55
  not_exists_result = cache.exists?(:bye)
73
- assert(exists_result == true)
74
- assert(not_exists_result == false)
56
+ assert(exists_result)
57
+ refute(not_exists_result)
75
58
  end
76
59
 
77
60
  def test_put_and_exists
78
61
  cache = Zache.new
79
62
  cache.put(:hey, 'hello', lifetime: 0.1)
80
63
  sleep 0.2
81
- assert(!cache.exists?(:hey))
64
+ refute(cache.exists?(:hey))
82
65
  end
83
66
 
84
67
  def test_remove_key
85
68
  cache = Zache.new
86
- cache.get(:hey) { Random.rand }
87
- cache.get(:wey) { Random.rand }
88
- assert(cache.exists?(:hey) == true)
89
- assert(cache.exists?(:wey) == true)
69
+ cache.get(:hey) { rand }
70
+ cache.get(:wey) { rand }
71
+ assert(cache.exists?(:hey))
72
+ assert(cache.exists?(:wey))
90
73
  cache.remove(:hey)
91
- assert(cache.exists?(:hey) == false)
92
- assert(cache.exists?(:wey) == true)
74
+ refute(cache.exists?(:hey))
75
+ assert(cache.exists?(:wey))
93
76
  end
94
77
 
95
78
  def test_remove_by_block
96
79
  cache = Zache.new
97
- cache.get('first') { Random.rand }
98
- cache.get('second') { Random.rand }
80
+ cache.get('first') { rand }
81
+ cache.get('second') { rand }
99
82
  cache.remove_by { |k| k == 'first' }
100
- assert(cache.exists?('first') == false)
101
- assert(cache.exists?('second') == true)
83
+ refute(cache.exists?('first'))
84
+ assert(cache.exists?('second'))
102
85
  end
103
86
 
104
87
  def test_remove_key_with_sync_false
105
88
  cache = Zache.new(sync: false)
106
- cache.get(:hey) { Random.rand }
107
- cache.get(:wey) { Random.rand }
108
- assert(cache.exists?(:hey) == true)
109
- assert(cache.exists?(:wey) == true)
89
+ cache.get(:hey) { rand }
90
+ cache.get(:wey) { rand }
91
+ assert(cache.exists?(:hey))
92
+ assert(cache.exists?(:wey))
110
93
  cache.remove(:hey)
111
- assert(cache.exists?(:hey) == false)
112
- assert(cache.exists?(:wey) == true)
94
+ refute(cache.exists?(:hey))
95
+ assert(cache.exists?(:wey))
113
96
  end
114
97
 
115
98
  def test_clean_with_threads
116
99
  cache = Zache.new
117
100
  Threads.new(300).assert(3000) do
118
- cache.get(:hey) { Random.rand }
119
- cache.get(:bye, lifetime: 0.01) { Random.rand }
101
+ cache.get(:hey) { rand }
102
+ cache.get(:bye, lifetime: 0.01) { rand }
120
103
  sleep 0.1
121
104
  cache.clean
122
105
  end
123
- assert(cache.exists?(:hey) == true)
124
- assert(cache.exists?(:bye) == false)
106
+ assert(cache.exists?(:hey))
107
+ refute(cache.exists?(:bye))
125
108
  end
126
109
 
127
110
  def test_clean
128
111
  cache = Zache.new
129
- cache.get(:hey) { Random.rand }
130
- cache.get(:bye, lifetime: 0.01) { Random.rand }
112
+ cache.get(:hey) { rand }
113
+ cache.get(:bye, lifetime: 0.01) { rand }
114
+ sleep 0.1
115
+ cache.clean
116
+ assert(cache.exists?(:hey))
117
+ refute(cache.exists?(:bye))
118
+ end
119
+
120
+ def test_clean_size
121
+ cache = Zache.new
122
+ cache.get(:hey, lifetime: 0.01) { rand }
131
123
  sleep 0.1
132
124
  cache.clean
133
- assert(cache.exists?(:hey) == true)
134
- assert(cache.exists?(:bye) == false)
125
+ assert_empty(cache)
135
126
  end
136
127
 
137
128
  def test_clean_with_sync_false
138
129
  cache = Zache.new(sync: false)
139
- cache.get(:hey) { Random.rand }
140
- cache.get(:bye, lifetime: 0.01) { Random.rand }
130
+ cache.get(:hey) { rand }
131
+ cache.get(:bye, lifetime: 0.01) { rand }
141
132
  sleep 0.1
142
133
  cache.clean
143
- assert(cache.exists?(:hey) == true)
144
- assert(cache.exists?(:bye) == false)
134
+ assert(cache.exists?(:hey))
135
+ refute(cache.exists?(:bye))
145
136
  end
146
137
 
147
138
  def test_remove_absent_key
@@ -151,43 +142,43 @@ class ZacheTest < Minitest::Test
151
142
 
152
143
  def test_check_and_remove
153
144
  cache = Zache.new
154
- cache.get(:hey, lifetime: 0) { Random.rand }
155
- assert(!cache.exists?(:hey))
145
+ cache.get(:hey, lifetime: 0) { rand }
146
+ refute(cache.exists?(:hey))
156
147
  end
157
148
 
158
149
  def test_remove_all_with_threads
159
150
  cache = Zache.new
160
151
  Threads.new(10).assert(100) do |i|
161
- cache.get("hey#{i}".to_sym) { Random.rand }
162
- assert(cache.exists?("hey#{i}".to_sym) == true)
152
+ cache.get(:"hey#{i}") { rand }
153
+ assert(cache.exists?(:"hey#{i}"))
163
154
  cache.remove_all
164
155
  end
165
156
  10.times do |i|
166
- assert(cache.exists?("hey#{i}".to_sym) == false)
157
+ refute(cache.exists?(:"hey#{i}"))
167
158
  end
168
159
  end
169
160
 
170
161
  def test_remove_all_with_sync
171
162
  cache = Zache.new
172
- cache.get(:hey) { Random.rand }
173
- cache.get(:bye) { Random.rand }
163
+ cache.get(:hey) { rand }
164
+ cache.get(:bye) { rand }
174
165
  cache.remove_all
175
- assert(cache.exists?(:hey) == false)
176
- assert(cache.exists?(:bye) == false)
166
+ refute(cache.exists?(:hey))
167
+ refute(cache.exists?(:bye))
177
168
  end
178
169
 
179
170
  def test_remove_all_without_sync
180
171
  cache = Zache.new(sync: false)
181
- cache.get(:hey) { Random.rand }
182
- cache.get(:bye) { Random.rand }
172
+ cache.get(:hey) { rand }
173
+ cache.get(:bye) { rand }
183
174
  cache.remove_all
184
- assert(cache.exists?(:hey) == false)
185
- assert(cache.exists?(:bye) == false)
175
+ refute(cache.exists?(:hey))
176
+ refute(cache.exists?(:bye))
186
177
  end
187
178
 
188
179
  def test_puts_something_in
189
180
  cache = Zache.new(sync: false)
190
- cache.get(:hey) { Random.rand }
181
+ cache.get(:hey) { rand }
191
182
  cache.put(:hey, 123)
192
183
  assert_equal(123, cache.get(:hey))
193
184
  end
@@ -208,19 +199,19 @@ class ZacheTest < Minitest::Test
208
199
  end
209
200
  end
210
201
  sleep 0.1
211
- assert(cache.locked?)
202
+ assert_predicate(cache, :locked?)
212
203
  cache.get(:x) { 'second' }
213
- assert(!cache.locked?)
204
+ refute_predicate(cache, :locked?)
214
205
  long.kill
215
206
  end
216
207
 
217
208
  def test_checks_locked_status_from_inside
218
209
  cache = Zache.new
219
210
  cache.get(:x) do
220
- assert(cache.locked?)
211
+ assert_predicate(cache, :locked?)
221
212
  'done'
222
213
  end
223
- assert(!cache.locked?)
214
+ refute_predicate(cache, :locked?)
224
215
  end
225
216
 
226
217
  def test_returns_dirty_result
@@ -285,4 +276,22 @@ class ZacheTest < Minitest::Test
285
276
  cache.get(:hey) { raise 'intentional' }
286
277
  end
287
278
  end
279
+
280
+ def test_returns_placeholder_in_eager_mode
281
+ cache = Zache.new
282
+ a = cache.get(:me, placeholder: 42, eager: true) do
283
+ sleep 0.1
284
+ 43
285
+ end
286
+ assert_equal(42, a)
287
+ sleep 0.2
288
+ b = cache.get(:me)
289
+ assert_equal(43, b)
290
+ end
291
+
292
+ private
293
+
294
+ def rand
295
+ SecureRandom.uuid
296
+ end
288
297
  end
data/zache.gemspec CHANGED
@@ -1,39 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # (The MIT License)
4
- #
5
- # Copyright (c) 2018-2023 Yegor Bugayenko
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the 'Software'), to deal
9
- # in the Software without restriction, including without limitation the rights
10
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- # copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in all
15
- # copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
- # SOFTWARE.
3
+ # SPDX-FileCopyrightText: Copyright (c) 2018-2025 Yegor Bugayenko
4
+ # SPDX-License-Identifier: MIT
24
5
 
25
6
  require 'English'
26
7
  Gem::Specification.new do |s|
27
8
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
28
- s.required_ruby_version = '>=2.5'
9
+ s.required_ruby_version = '>= 2.5'
29
10
  s.name = 'zache'
30
- s.version = '0.13.1'
11
+ s.version = '0.14.0' # Version should be updated before release
31
12
  s.license = 'MIT'
32
13
  s.summary = 'In-memory Cache'
33
14
  s.description = 'Zero-footprint in-memory thread-safe cache'
34
15
  s.authors = ['Yegor Bugayenko']
35
16
  s.email = 'yegor256@gmail.com'
36
- s.homepage = 'http://github.com/yegor256/zache'
17
+ s.homepage = 'https://github.com/yegor256/zache'
37
18
  s.files = `git ls-files`.split($RS)
38
19
  s.rdoc_options = ['--charset=UTF-8']
39
20
  s.extra_rdoc_files = ['README.md']
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-08-01 00:00:00.000000000 Z
10
+ date: 2025-04-12 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Zero-footprint in-memory thread-safe cache
14
13
  email: yegor256@gmail.com
@@ -18,17 +17,26 @@ extra_rdoc_files:
18
17
  - README.md
19
18
  files:
20
19
  - ".0pdd.yml"
20
+ - ".github/workflows/actionlint.yml"
21
21
  - ".github/workflows/codecov.yml"
22
+ - ".github/workflows/copyrights.yml"
23
+ - ".github/workflows/license.yml"
24
+ - ".github/workflows/markdown-lint.yml"
22
25
  - ".github/workflows/pdd.yml"
23
26
  - ".github/workflows/rake.yml"
27
+ - ".github/workflows/reuse.yml"
24
28
  - ".github/workflows/xcop.yml"
29
+ - ".github/workflows/yamllint.yml"
25
30
  - ".gitignore"
26
31
  - ".pdd"
27
32
  - ".rubocop.yml"
28
33
  - ".rultor.yml"
29
34
  - Gemfile
35
+ - Gemfile.lock
30
36
  - LICENSE.txt
37
+ - LICENSES/MIT.txt
31
38
  - README.md
39
+ - REUSE.toml
32
40
  - Rakefile
33
41
  - lib/zache.rb
34
42
  - logo.svg
@@ -36,12 +44,11 @@ files:
36
44
  - test/test__helper.rb
37
45
  - test/test_zache.rb
38
46
  - zache.gemspec
39
- homepage: http://github.com/yegor256/zache
47
+ homepage: https://github.com/yegor256/zache
40
48
  licenses:
41
49
  - MIT
42
50
  metadata:
43
51
  rubygems_mfa_required: 'true'
44
- post_install_message:
45
52
  rdoc_options:
46
53
  - "--charset=UTF-8"
47
54
  require_paths:
@@ -57,8 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
64
  - !ruby/object:Gem::Version
58
65
  version: '0'
59
66
  requirements: []
60
- rubygems_version: 3.2.15
61
- signing_key:
67
+ rubygems_version: 3.6.2
62
68
  specification_version: 4
63
69
  summary: In-memory Cache
64
70
  test_files: []