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