fbe 0.29.1 → 0.31.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.
@@ -1,446 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
- # SPDX-License-Identifier: MIT
5
-
6
- require 'qbash'
7
- require 'securerandom'
8
- require_relative '../../../lib/fbe/middleware'
9
- require_relative '../../../lib/fbe/middleware/sqlite_store'
10
- require_relative '../../test__helper'
11
-
12
- # Test.
13
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
14
- # Copyright:: Copyright (c) 2024-2025 Zerocracy
15
- # License:: MIT
16
- class SqliteStoreTest < Fbe::Test
17
- def test_simple_caching_algorithm
18
- with_tmpfile('x.db') do |f|
19
- store = Fbe::Middleware::SqliteStore.new(f, '0.0.0')
20
- k = 'some-key'
21
- assert_nil(store.read(k))
22
- assert_nil(store.delete(k))
23
- v1 = 'first value to save'
24
- assert_nil(store.write(k, v1))
25
- assert_equal(v1, store.read(k))
26
- v2 = 'another value to save'
27
- assert_nil(store.write(k, v2))
28
- assert_equal(v2, store.read(k))
29
- assert_nil(store.delete(k))
30
- assert_nil(store.read(k))
31
- assert_path_exists(f)
32
- end
33
- end
34
-
35
- def test_returns_empty_list
36
- with_tmpfile('b.db') do |f|
37
- store = Fbe::Middleware::SqliteStore.new(f, '0.0.0', loog: fake_loog)
38
- assert_empty(store.all)
39
- end
40
- end
41
-
42
- def test_clear_all_keys
43
- with_tmpfile('a.db') do |f|
44
- store = Fbe::Middleware::SqliteStore.new(f, '0.0.0', loog: fake_loog)
45
- k = 'a key'
46
- store.write(k, 'some value')
47
- store.clear
48
- assert_empty(store.all)
49
- end
50
- end
51
-
52
- def test_empty_all_if_not_written
53
- with_tmpfile do |f|
54
- store = Fbe::Middleware::SqliteStore.new(f, '0.0.0', loog: fake_loog)
55
- assert_empty(store.all)
56
- end
57
- end
58
-
59
- def test_wrong_db_path
60
- assert_raises(ArgumentError) do
61
- Fbe::Middleware::SqliteStore.new(nil, '0.0.0', loog: fake_loog).read('my_key')
62
- end
63
- assert_raises(ArgumentError) do
64
- Fbe::Middleware::SqliteStore.new('', '0.0.0', loog: fake_loog).read('my_key')
65
- end
66
- assert_raises(ArgumentError) do
67
- Fbe::Middleware::SqliteStore.new('/fakepath/fakefolder/test.db', '0.0.0', loog: fake_loog).read('my_key')
68
- end
69
- end
70
-
71
- def test_not_db_file
72
- with_tmpfile do |f|
73
- File.binwrite(f, Array.new(20) { rand(0..255) }.pack('C*'))
74
- ex =
75
- assert_raises(SQLite3::NotADatabaseException) do
76
- Fbe::Middleware::SqliteStore.new(f, '0.0.0', loog: fake_loog).read('my_key')
77
- end
78
- assert_match('file is not a database', ex.message)
79
- end
80
- end
81
-
82
- def test_defer_db_close_callback
83
- txt = <<~RUBY
84
- require 'tempfile'
85
- require 'sqlite3'
86
- require 'fbe/middleware/sqlite_store'
87
- SQLite3::Database.class_eval do
88
- prepend(Module.new do
89
- def close
90
- super
91
- puts 'closed sqlite after process exit'
92
- end
93
- end)
94
- end
95
- Tempfile.open('test.db') do |f|
96
- Fbe::Middleware::SqliteStore.new(f.path, '0.0.0').then do |s|
97
- s.write('my_key', 'my_value')
98
- s.read('my_key')
99
- end
100
- end
101
- RUBY
102
- out =
103
- qbash(
104
- 'bundle exec ruby ' \
105
- "-I#{Shellwords.escape(File.expand_path('../../../lib', __dir__))} " \
106
- "-e #{Shellwords.escape(txt)} 2>&1"
107
- )
108
- assert_match('closed sqlite after process exit', out)
109
- end
110
-
111
- def test_different_versions
112
- with_tmpfile('d.db') do |f|
113
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
114
- store.write('kkk1', 'some value')
115
- store.write('kkk2', 'another value')
116
- end
117
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
118
- assert_equal('some value', store.read('kkk1'))
119
- assert_equal('another value', store.read('kkk2'))
120
- end
121
- Fbe::Middleware::SqliteStore.new(f, '0.0.2', loog: fake_loog).then do |store|
122
- assert_nil(store.read('kkk1'))
123
- assert_nil(store.read('kkk2'))
124
- end
125
- end
126
- end
127
-
128
- def test_initialize_wrong_version
129
- with_tmpfile('e.db') do |f|
130
- msg = 'Version cannot be nil or empty'
131
- assert_raises(ArgumentError) { Fbe::Middleware::SqliteStore.new(f, nil, loog: fake_loog) }.then do |ex|
132
- assert_match(msg, ex.message)
133
- end
134
- assert_raises(ArgumentError) { Fbe::Middleware::SqliteStore.new(f, '', loog: fake_loog) }.then do |ex|
135
- assert_match(msg, ex.message)
136
- end
137
- end
138
- end
139
-
140
- def test_skip_write_if_value_more_then_10k_bytes
141
- with_tmpfile('a.db') do |f|
142
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
143
- store.write('a', 'a' * 9_997)
144
- store.write('b', 'b' * 9_998)
145
- store.write('c', SecureRandom.alphanumeric((19_999 * 1.4).to_i))
146
- store.write('d', SecureRandom.alphanumeric((30_000 * 1.4).to_i))
147
- assert_equal('a' * 9_997, store.read('a'))
148
- assert_equal('b' * 9_998, store.read('b'))
149
- assert_nil(store.read('c'))
150
- assert_nil(store.read('d'))
151
- end
152
- end
153
- end
154
-
155
- def test_shrink_cache_if_more_then_10_mb
156
- with_tmpfile('large.db') do |f|
157
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
158
- store.write('a', 'aa')
159
- Time.stub(:now, (Time.now - (5 * 60 * 60)).round) do
160
- store.write('b', 'bb')
161
- store.write('c', 'cc')
162
- end
163
- assert_equal('cc', store.read('c'))
164
- Time.stub(:now, rand((Time.now - (5 * 60 * 60))..Time.now).round) do
165
- key = 'a' * 65_536
166
- value = SecureRandom.alphanumeric(8_192)
167
- 52.times do
168
- store.write(key, value)
169
- key = key.next
170
- end
171
- end
172
- end
173
- assert_operator(File.size(f), :>, 10 * 1024 * 1024)
174
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
175
- assert_equal('aa', store.read('a'))
176
- assert_nil(store.read('b'))
177
- assert_equal('cc', store.read('c'))
178
- assert_operator(File.size(f), :<=, 10 * 1024 * 1024)
179
- end
180
- end
181
- end
182
-
183
- def test_upgrade_sqlite_schema_for_add_touched_at_column
184
- with_tmpfile('a.db') do |f|
185
- SQLite3::Database.new(f).tap do |d|
186
- d.execute 'CREATE TABLE IF NOT EXISTS cache(key TEXT UNIQUE NOT NULL, value TEXT);'
187
- [
188
- ['key1', Zlib::Deflate.deflate(JSON.dump('value1'))],
189
- ['key2', Zlib::Deflate.deflate(JSON.dump('value2'))]
190
- ].each { d.execute 'INSERT INTO cache(key, value) VALUES(?1, ?2);', _1 }
191
- d.execute 'CREATE TABLE IF NOT EXISTS meta(key TEXT UNIQUE NOT NULL, value TEXT);'
192
- d.execute "INSERT INTO meta(key, value) VALUES('version', ?);", ['0.0.1']
193
- end
194
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
195
- assert_equal('value1', store.read('key1'))
196
- assert_equal('value2', store.read('key2'))
197
- rescue SQLite3::SQLException => e
198
- assert_nil(e)
199
- end
200
- end
201
- end
202
-
203
- def test_use_compress_for_stored_data
204
- with_tmpfile('c.db') do |f|
205
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
206
- a = SecureRandom.alphanumeric(200)
207
- store.write('a', a)
208
- store.write('b', 'b' * 100_000)
209
- assert_equal(a, store.read('a'))
210
- assert_equal('b' * 100_000, store.read('b'))
211
- store.all.each do |k, v|
212
- case k
213
- when 'a'
214
- assert_operator(v.size, :<, a.size)
215
- when 'b'
216
- assert_operator(v.size, :<, 100_000)
217
- end
218
- end
219
- end
220
- end
221
- end
222
-
223
- def test_corrupted_compression_stored_data
224
- with_tmpfile('c.db') do |f|
225
- SQLite3::Database.new(f).tap do |d|
226
- d.execute 'CREATE TABLE IF NOT EXISTS cache(key TEXT UNIQUE NOT NULL, value TEXT);'
227
- [
228
- ['my_key', JSON.dump('value1')]
229
- ].each { d.execute 'INSERT INTO cache(key, value) VALUES(?1, ?2);', _1 }
230
- d.execute 'CREATE TABLE IF NOT EXISTS meta(key TEXT UNIQUE NOT NULL, value TEXT);'
231
- d.execute "INSERT INTO meta(key, value) VALUES('version', ?);", ['0.0.1']
232
- end
233
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
234
- assert_nil(store.read('my_key'))
235
- assert_predicate(store.all.count, :zero?)
236
- end
237
- end
238
- end
239
-
240
- def test_upgrade_sqlite_schema_for_add_created_at_column
241
- with_tmpfile('a.db') do |f|
242
- SQLite3::Database.new(f).tap do |d|
243
- d.execute 'CREATE TABLE IF NOT EXISTS cache(key TEXT UNIQUE NOT NULL, value TEXT, touched_at TEXT NOT NULL);'
244
- [
245
- ['key1', Zlib::Deflate.deflate(JSON.dump('value1')), Time.now.utc.iso8601],
246
- ['key2', Zlib::Deflate.deflate(JSON.dump('value2')), Time.now.utc.iso8601]
247
- ].each { d.execute 'INSERT INTO cache(key, value, touched_at) VALUES(?1, ?2, ?3);', _1 }
248
- d.execute 'CREATE TABLE IF NOT EXISTS meta(key TEXT UNIQUE NOT NULL, value TEXT);'
249
- d.execute "INSERT INTO meta(key, value) VALUES('version', ?);", ['0.0.1']
250
- end
251
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
252
- assert_equal('value1', store.read('key1'))
253
- assert_equal('value2', store.read('key2'))
254
- rescue SQLite3::SQLException => e
255
- assert_nil(e)
256
- end
257
- end
258
- end
259
-
260
- def test_set_correct_ttl
261
- with_tmpfile('c.db') do |f|
262
- s = Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: nil)
263
- refute_nil(s)
264
- s = Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 24)
265
- refute_nil(s)
266
- end
267
- end
268
-
269
- def test_set_incorrect_ttl
270
- with_tmpfile('c.db') do |f|
271
- ex =
272
- assert_raises(ArgumentError) do
273
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 0)
274
- end
275
- assert_equal('TTL can be nil or Integer > 0', ex.message)
276
- ex =
277
- assert_raises(ArgumentError) do
278
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: -10)
279
- end
280
- assert_equal('TTL can be nil or Integer > 0', ex.message)
281
- ex =
282
- assert_raises(ArgumentError) do
283
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 10.0)
284
- end
285
- assert_equal('TTL can be nil or Integer > 0', ex.message)
286
- ex =
287
- assert_raises(ArgumentError) do
288
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: '10')
289
- end
290
- assert_equal('TTL can be nil or Integer > 0', ex.message)
291
- ex =
292
- assert_raises(ArgumentError) do
293
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: Object.new)
294
- end
295
- assert_equal('TTL can be nil or Integer > 0', ex.message)
296
- end
297
- end
298
-
299
- def test_delete_keys_if_ttl_expired
300
- with_tmpfile('c.db') do |f|
301
- now = Time.now
302
- Time.stub(:now, now) do
303
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 24).then do |s|
304
- s.write('test1', 'value1')
305
- s.write('test2', 'value2')
306
- end
307
- end
308
- Time.stub(:now, now + (12 * 60 * 60)) do
309
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 24).then do |s|
310
- s.write('test3', 'value3')
311
- s.write('test4', 'value4')
312
- end
313
- end
314
- Time.stub(:now, now + (24 * 60 * 60)) do
315
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 24).then do |s|
316
- assert_equal('value1', s.read('test1'))
317
- assert_equal('value2', s.read('test2'))
318
- assert_equal('value3', s.read('test3'))
319
- assert_equal('value4', s.read('test4'))
320
- end
321
- end
322
- Time.stub(:now, now + (24 * 60 * 60) + 1) do
323
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, ttl: 24).then do |s|
324
- assert_nil(s.read('test1'))
325
- assert_nil(s.read('test2'))
326
- assert_equal('value3', s.read('test3'))
327
- assert_equal('value4', s.read('test4'))
328
- end
329
- end
330
- end
331
- end
332
-
333
- def test_set_correct_cache_min_age
334
- with_tmpfile('c.db') do |f|
335
- s = Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, cache_min_age: nil)
336
- refute_nil(s)
337
- s = Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, cache_min_age: 600)
338
- refute_nil(s)
339
- end
340
- end
341
-
342
- def test_set_incorrect_cache_min_age
343
- with_tmpfile('c.db') do |f|
344
- msg = 'Cache min age can be nil or Integer > 0'
345
- [0, -50, 120.0, '120', Object.new].each do |cache_min_age|
346
- ex =
347
- assert_raises(ArgumentError) do
348
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, cache_min_age:)
349
- end
350
- assert_equal(msg, ex.message)
351
- end
352
- end
353
- end
354
-
355
- def test_not_overwrite_cache_control
356
- with_tmpfile('t.db') do |f|
357
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, cache_min_age: 30).then do |store|
358
- store.write(
359
- 'test1',
360
- faraday_value(resp: { 'response_headers' => { 'cache-control' => 'public, max-age=60, s-maxage=60' } })
361
- )
362
- store.write(
363
- 'test2',
364
- faraday_value(resp: { 'response_headers' => { 'cache-control' => 'public, max-age=30, s-maxage=30' } })
365
- )
366
- store.write(
367
- 'test3',
368
- faraday_value(resp: { 'response_headers' => { 'content-type' => 'application/json; charset=utf-8' } })
369
- )
370
- store.write('test4', faraday_value(resp: { 'status' => 200, 'body' => '{"some":"value"}' }))
371
- store.write('test5', faraday_value(resp: {}))
372
- store.write('test6', [[JSON.dump({ 'method' => 'get' }), 1]])
373
- store.write('test7', faraday_value(resp: 'some string'))
374
- store.write('test8', faraday_value(resp: nil))
375
- end
376
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog).then do |store|
377
- assert_equal(
378
- 'public, max-age=60, s-maxage=60',
379
- JSON.parse(store.read('test1')[0][1]).dig('response_headers', 'cache-control')
380
- )
381
- assert_equal(
382
- 'public, max-age=30, s-maxage=30',
383
- JSON.parse(store.read('test2')[0][1]).dig('response_headers', 'cache-control')
384
- )
385
- assert_nil(JSON.parse(store.read('test3')[0][1]).dig('response_headers', 'cache-control'))
386
- assert_nil(JSON.parse(store.read('test4')[0][1]).dig('response_headers', 'cache-control'))
387
- assert_nil(JSON.parse(store.read('test5')[0][1]).dig('response_headers', 'cache-control'))
388
- assert_equal(1, store.read('test6')[0][1])
389
- assert_equal(JSON.dump('some string'), store.read('test7')[0][1])
390
- assert_nil(store.read('test8')[0][1])
391
- end
392
- end
393
- end
394
-
395
- def test_overwrite_cache_control
396
- with_tmpfile('t.db') do |f|
397
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, cache_min_age: 300).then do |store|
398
- store.write(
399
- 'test1',
400
- faraday_value(resp: { 'response_headers' => { 'cache-control' => 'public, max-age=60, s-maxage=60' } })
401
- )
402
- end
403
- Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog, cache_min_age: 1555).then do |store|
404
- store.write(
405
- 'test2',
406
- faraday_value(resp: { 'response_headers' => { 'cache-control' => 'public, max-age=60, s-maxage=60' } })
407
- )
408
- end
409
- store = Fbe::Middleware::SqliteStore.new(f, '0.0.1', loog: fake_loog)
410
- assert_equal(
411
- 'public, max-age=300, s-maxage=300',
412
- JSON.parse(store.read('test1')[0][1]).dig('response_headers', 'cache-control')
413
- )
414
- assert_equal(
415
- 'public, max-age=1555, s-maxage=1555',
416
- JSON.parse(store.read('test2')[0][1]).dig('response_headers', 'cache-control')
417
- )
418
- end
419
- end
420
-
421
- private
422
-
423
- def with_tmpfile(name = 'test.db', &)
424
- Dir.mktmpdir do |dir|
425
- yield File.expand_path(name, dir)
426
- end
427
- end
428
-
429
- def faraday_value(
430
- req: {
431
- 'method' => 'get',
432
- 'url' => 'https://example.com/test',
433
- 'headers' => { 'Content-Type' => 'application/json' }
434
- },
435
- resp: {
436
- 'status' => 200,
437
- 'body' => '{"some":"value"}',
438
- 'response_headers' => { 'content-type' => 'application/json; charset=utf-8' }
439
- }
440
- )
441
- value = []
442
- value << JSON.dump(req) if req
443
- value << JSON.dump(resp) if resp
444
- [value]
445
- end
446
- end
@@ -1,168 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
- # SPDX-License-Identifier: MIT
5
-
6
- require 'faraday'
7
- require 'faraday/http_cache'
8
- require 'webmock'
9
- require_relative '../../../lib/fbe'
10
- require_relative '../../../lib/fbe/middleware'
11
- require_relative '../../../lib/fbe/middleware/trace'
12
- require_relative '../../test__helper'
13
-
14
- # Test.
15
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
16
- # Copyright:: Copyright (c) 2024-2025 Zerocracy
17
- # License:: MIT
18
- class TraceTest < Fbe::Test
19
- def test_traces_successful_request
20
- trace = []
21
- stub_request(:get, 'http://example.com/test')
22
- .to_return(status: 200, body: 'success')
23
- conn =
24
- Faraday.new do |f|
25
- f.use Fbe::Middleware::Trace, trace
26
- f.adapter :net_http
27
- end
28
- conn.get('http://example.com/test')
29
- assert_equal 1, trace.size
30
- entry = trace.first
31
- assert_equal :get, entry[:method]
32
- assert_equal 'http://example.com/test', entry[:url]
33
- assert_equal 200, entry[:status]
34
- assert_instance_of Time, entry[:started_at]
35
- assert_instance_of Time, entry[:finished_at]
36
- assert_instance_of Float, entry[:duration]
37
- assert_operator entry[:duration], :>=, 0
38
- assert_operator entry[:finished_at], :>=, entry[:started_at]
39
- end
40
-
41
- def test_traces_multiple_requests
42
- trace = []
43
- stub_request(:get, 'http://example.com/endpoint1').to_return(status: 200)
44
- stub_request(:post, 'http://example.com/endpoint2').to_return(status: 201)
45
- stub_request(:delete, 'http://example.com/endpoint3').to_return(status: 404)
46
- conn =
47
- Faraday.new do |f|
48
- f.use Fbe::Middleware::Trace, trace
49
- f.adapter :net_http
50
- end
51
- conn.get('http://example.com/endpoint1')
52
- conn.post('http://example.com/endpoint2')
53
- conn.delete('http://example.com/endpoint3')
54
- assert_equal 3, trace.size
55
- assert_equal :get, trace[0][:method]
56
- assert_equal 200, trace[0][:status]
57
- assert_equal :post, trace[1][:method]
58
- assert_equal 201, trace[1][:status]
59
- assert_equal :delete, trace[2][:method]
60
- assert_equal 404, trace[2][:status]
61
- end
62
-
63
- def test_traces_error_responses
64
- trace = []
65
- stub_request(:get, 'http://example.com/error').to_return(status: 500, body: 'error')
66
- conn =
67
- Faraday.new do |f|
68
- f.use Fbe::Middleware::Trace, trace
69
- f.adapter :net_http
70
- end
71
- conn.get('http://example.com/error')
72
- assert_equal 1, trace.size
73
- entry = trace.first
74
- assert_equal 500, entry[:status]
75
- assert_equal 'http://example.com/error', entry[:url]
76
- end
77
-
78
- def test_handles_connection_errors
79
- trace = []
80
- stub_request(:get, 'http://example.com/timeout').to_timeout
81
- conn =
82
- Faraday.new do |f|
83
- f.use Fbe::Middleware::Trace, trace
84
- f.adapter :net_http
85
- end
86
- assert_raises(Faraday::ConnectionFailed) do
87
- conn.get('http://example.com/timeout')
88
- end
89
- assert_equal 0, trace.size
90
- end
91
-
92
- def test_preserves_request_with_query_params
93
- trace = []
94
- stub_request(:get, 'http://example.com/search').with(query: { 'q' => 'test', 'page' => '2' }).to_return(status: 200)
95
- conn =
96
- Faraday.new do |f|
97
- f.use Fbe::Middleware::Trace, trace
98
- f.adapter :net_http
99
- end
100
- conn.get('http://example.com/search?q=test&page=2')
101
- assert_equal 1, trace.size
102
- url = trace.first[:url]
103
- assert url.start_with?('http://example.com/search?')
104
- assert_includes url, 'q=test'
105
- assert_includes url, 'page=2'
106
- end
107
-
108
- def test_trace_and_cache_middlewares_together
109
- WebMock.disable_net_connect!
110
- now = Time.now
111
- stub_request(:get, 'https://api.example.com/page')
112
- .to_return(
113
- status: 200,
114
- headers: {
115
- 'date' => now.httpdate,
116
- 'cache-control' => 'public, max-age=60, s-maxage=60',
117
- 'last-modified' => (now - (6 * 60 * 60)).httpdate
118
- },
119
- body: 'some body 1'
120
- )
121
- .times(1)
122
- .then
123
- .to_return(
124
- status: 200,
125
- headers: {
126
- 'date' => (now + 70).httpdate,
127
- 'cache-control' => 'public, max-age=60, s-maxage=60',
128
- 'last-modified' => (now - (6 * 60 * 60)).httpdate,
129
- 'content-type' => 'application/json; charset=utf-8'
130
- },
131
- body: 'some body 2'
132
- )
133
- .times(1)
134
- .then.to_raise('no more request to /page')
135
- trace_real = []
136
- trace_full = []
137
- builder =
138
- Faraday::RackBuilder.new do |f|
139
- f.use Fbe::Middleware::Trace, trace_full
140
- f.use(Faraday::HttpCache, serializer: Marshal, shared_cache: false, logger: Loog::NULL)
141
- f.use Fbe::Middleware::Trace, trace_real
142
- f.adapter :net_http
143
- end
144
- conn = Faraday::Connection.new(builder: builder)
145
- 5.times do
146
- r = conn.get('https://api.example.com/page')
147
- assert_equal('some body 1', r.body)
148
- end
149
- assert_equal(1, trace_real.size)
150
- assert_equal(5, trace_full.size)
151
- trace_real.clear
152
- trace_full.clear
153
- 5.times do
154
- r = conn.get('https://api.example.com/page')
155
- assert_equal('some body 1', r.body)
156
- end
157
- assert_equal(0, trace_real.size)
158
- assert_equal(5, trace_full.size)
159
- Time.stub(:now, now + 70) do
160
- 5.times do
161
- r = conn.get('https://api.example.com/page')
162
- assert_equal('some body 2', r.body)
163
- end
164
- end
165
- assert_equal(1, trace_real.size)
166
- assert_equal(10, trace_full.size)
167
- end
168
- end