test_helper.rb

  1# frozen_string_literal: true
  2
  3require "simplecov"
  4SimpleCov.start do
  5	add_filter "/test/"
  6	enable_coverage :branch
  7end
  8
  9require "minitest/autorun"
 10require "webmock/minitest"
 11
 12begin
 13	require "pry-rescue/minitest"
 14	require "pry-reload"
 15	require "pry-byebug"
 16
 17	module Minitest
 18		class Test
 19			alias old_capture_exceptions capture_exceptions
 20			def capture_exceptions
 21				old_capture_exceptions do
 22					yield
 23				rescue Minitest::Skip => e
 24					failures << e
 25				end
 26			end
 27		end
 28	end
 29rescue LoadError, NameError
 30	# Just helpers for dev, no big deal if missing
 31	nil
 32end
 33
 34$VERBOSE = nil
 35
 36class FakeRedis
 37	def initialize(values={})
 38		@values = values
 39	end
 40
 41	def reset!(values={})
 42		@values = values
 43	end
 44
 45	def set(key, value, *)
 46		@values[key] = value
 47		EMPromise.resolve("OK")
 48	end
 49
 50	def setex(key, _expiry, value)
 51		set(key, value)
 52	end
 53
 54	def del(*keys)
 55		keys.each { |key| @values.delete(key) }
 56	end
 57
 58	def mget(*keys)
 59		EMPromise.all(keys.map(&method(:get)))
 60	end
 61
 62	def get(key)
 63		EMPromise.resolve(@values[key])
 64	end
 65
 66	def getbit(key, bit)
 67		get(key).then { |v| v.to_i.to_s(2)[bit].to_i }
 68	end
 69
 70	def bitfield(key, *ops)
 71		get(key).then do |v|
 72			bits = v.to_i.to_s(2)
 73			ops.each_slice(3).map do |(op, encoding, offset)|
 74				raise "unsupported bitfield op" unless op == "GET"
 75				raise "unsupported bitfield op" unless encoding == "u1"
 76
 77				bits[offset].to_i
 78			end
 79		end
 80	end
 81
 82	def hget(key, field)
 83		@values.dig(key, field)
 84	end
 85
 86	def hincrby(key, field, incrby)
 87		@values[key] ||= {}
 88		@values[key][field] ||= 0
 89		@values[key][field] += incrby
 90	end
 91
 92	def sadd(key, member)
 93		@values[key] ||= Set.new
 94		@values[key] << member
 95	end
 96
 97	def srem(key, member)
 98		@values[key].delete(member)
 99	end
100
101	def scard(key)
102		@values[key]&.size || 0
103	end
104
105	def expire(_, _); end
106
107	def exists(*keys)
108		EMPromise.resolve(
109			@values.select { |k, _| keys.include? k }.size.to_s
110		)
111	end
112
113	def lindex(key, index)
114		get(key).then { |v| v&.fetch(index) }
115	end
116
117	def lrange(key, sindex, eindex)
118		get(key).then { |v| v ? v[sindex..eindex] : [] }
119	end
120
121	def rpush(key, *values)
122		@values[key] ||= []
123		values.each { |v| @values[key].push(v) }
124	end
125
126	def multi
127	end
128
129	def exec
130	end
131
132	def discard
133	end
134
135	def xadd(stream, id, *args)
136		@values[stream] ||= []
137		entry_id = id == "*" ? "#{Time.now.to_i}-0" : id
138		fields = Hash[*args]
139		@values[stream] << { id: entry_id, fields: fields }
140		EMPromise.resolve(entry_id)
141	end
142
143	def stream_entries(stream)
144		EMPromise.resolve(@values[stream] || [])
145	end
146end
147
148REDIS = FakeRedis.new
149
150module Minitest
151	class Test
152		def with_stubs(stubs, &block)
153			if stubs.empty?
154				block.call
155			else
156				obj, method, value = stubs.first
157				obj.stub(method, value) do
158					with_stubs(stubs[1..], &block)
159				end
160			end
161		end
162
163		def self.em(m)
164			alias_method "raw_#{m}", m
165			define_method(m) do
166				$panic = nil
167				e = nil
168				EM.run do
169					Fiber.new {
170						begin
171							send("raw_#{m}")
172						rescue
173							e = $!
174						ensure
175							EM.stop
176						end
177					}.resume
178				end
179				raise e if e
180			end
181		end
182	end
183end