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