1# frozen_string_literal: true
2
3require "simplecov"
4SimpleCov.start do
5 add_filter "/test/"
6 enable_coverage :branch
7 command_name ENV.fetch("COVERAGE_NAME", "tests")
8end
9
10require "minitest/autorun"
11require "webmock/minitest"
12
13MMS_PROXY = "https://proxy.test.example.com/"
14
15_saved_argv = ARGV.dup
16
17ARGV[0] = "component"
18ARGV[6] = MMS_PROXY
19
20require_relative "../sgx-bwmsgsv2"
21ARGV.replace(_saved_argv)
22
23def SGXbwmsgsv2.write_to_stream(s)
24 @written ||= []
25 @written << s
26end
27
28def reset_stanzas!
29 SGXbwmsgsv2.instance_variable_set(:@written, [])
30end
31
32def reset_redis!
33 REDIS.reset!
34 REDIS.set("catapult_jid-", "HERE")
35 REDIS.set("catapult_jid-+15550000000", "test@example.com")
36 REDIS.set("catapult_cred-test@example.com", [
37 'account', 'user', 'password', '+15550000000'
38 ])
39end
40
41def written
42 SGXbwmsgsv2.instance_variable_get(:@written)
43end
44
45def invoke_webhook(payload, extra_env: {})
46 with_stubs([
47 [
48 SGXbwmsgsv2,
49 :write,
50 ->(data) { SGXbwmsgsv2.write_to_stream(data) }
51 ]
52 ]) do
53 handler = WebhookHandler.new
54 env = {
55 "REQUEST_URI" => "/",
56 "REQUEST_METHOD" => "POST",
57 "params" => { "_json" => [payload] }
58 }.merge(extra_env)
59 handler.instance_variable_set(:@env, env)
60 def handler.params
61 @env["params"]
62 end
63 EMPromise.resolve(nil).then {
64 handler.response(env)
65 }.sync
66 end
67end
68
69def process_stanza(s)
70 SGXbwmsgsv2.send(:client).receive_data(s)
71 raise $panic if $panic
72end
73
74def xmpp_error_name(error)
75 error.find_first(
76 "child::*[name()!='text']",
77 Blather::StanzaError::STANZA_ERR_NS
78 ).element_name
79end
80
81def xmpp_error_text(error)
82 error.find_first("ns:text", ns: Blather::StanzaError::STANZA_ERR_NS)&.text
83end
84
85
86begin
87 require "pry-byebug"
88
89 module Minitest
90 class Test
91 alias old_capture_exceptions capture_exceptions
92 def capture_exceptions
93 old_capture_exceptions do
94 yield
95 rescue Minitest::Skip => e
96 failures << e
97 end
98 end
99 end
100 end
101rescue LoadError, NameError
102 # Just helpers for dev, no big deal if missing
103 nil
104end
105
106
107$VERBOSE = nil
108
109class FakeRedis
110 def initialize(values={})
111 @values = values
112 end
113
114 def reset!(values={})
115 @values = values
116 end
117
118 def set(key, value, *)
119 @values[key] = value
120 EMPromise.resolve("OK")
121 end
122
123 def setex(key, _expiry, value)
124 set(key, value)
125 end
126
127 def del(*keys)
128 keys.each { |key| @values.delete(key) }
129 end
130
131 def mget(*keys)
132 EMPromise.all(keys.map(&method(:get)))
133 end
134
135 def get(key)
136 EMPromise.resolve(@values[key])
137 end
138
139 def getbit(key, bit)
140 get(key).then { |v| v.to_i.to_s(2)[bit].to_i }
141 end
142
143 def bitfield(key, *ops)
144 get(key).then do |v|
145 bits = v.to_i.to_s(2)
146 ops.each_slice(3).map do |(op, encoding, offset)|
147 raise "unsupported bitfield op" unless op == "GET"
148 raise "unsupported bitfield op" unless encoding == "u1"
149
150 bits[offset].to_i
151 end
152 end
153 end
154
155 def hget(key, field)
156 @values.dig(key, field)
157 end
158
159 def hincrby(key, field, incrby)
160 @values[key] ||= {}
161 @values[key][field] ||= 0
162 @values[key][field] += incrby
163 end
164
165 def sadd(key, member)
166 @values[key] ||= Set.new
167 @values[key] << member
168 end
169
170 def srem(key, member)
171 @values[key].delete(member)
172 end
173
174 def scard(key)
175 @values[key]&.size || 0
176 end
177
178 def expire(_, _); end
179
180 def exists(*keys)
181 EMPromise.resolve(
182 @values.select { |k, _| keys.include? k }.size.to_s
183 )
184 end
185
186 def lindex(key, index)
187 get(key).then { |v| v&.fetch(index) }
188 end
189
190 def lrange(key, sindex, eindex)
191 get(key).then { |v| v ? v[sindex..eindex] : [] }
192 end
193
194 def rpush(key, *values)
195 @values[key] ||= []
196 values.each { |v| @values[key].push(v) }
197 end
198
199 def multi
200 end
201
202 def exec
203 end
204
205 def discard
206 end
207
208 def xadd(stream, id, *args)
209 @values[stream] ||= []
210 entry_id = id == "*" ? "#{Time.now.to_i}-0" : id
211 fields = Hash[*args]
212 @values[stream] << { id: entry_id, fields: fields }
213 EMPromise.resolve(entry_id)
214 end
215
216 def stream_entries(stream)
217 EMPromise.resolve(@values[stream] || [])
218 end
219end
220
221REDIS = FakeRedis.new
222
223module Minitest
224 class Test
225 def with_stubs(stubs, &block)
226 if stubs.empty?
227 block.call
228 else
229 obj, method, value = stubs.first
230 obj.stub(method, value) do
231 with_stubs(stubs[1..], &block)
232 end
233 end
234 end
235
236 def self.em(m)
237 alias_method "raw_#{m}", m
238 define_method(m) do
239 $panic = nil
240 e = nil
241 EM.run do
242 Fiber.new {
243 ARGV[0] = "component"
244 ARGV[6] = MMS_PROXY
245 begin
246 send("raw_#{m}")
247 rescue
248 e = $!
249 ensure
250 EM.stop
251 end
252 }.resume
253 end
254 raise e if e
255 end
256 end
257 end
258end