wamp_client 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,129 @@
1
+ require 'wamp_client/serializer'
2
+
3
+ module WampClient
4
+ module Transport
5
+ class Base
6
+
7
+ # Callback when the socket is opened
8
+ @on_open
9
+ def on_open(&on_open)
10
+ @on_open = on_open
11
+ end
12
+
13
+ # Callback when the socket is closed. Parameters are
14
+ # @param reason [String] String telling the reason it was closed
15
+ @on_close
16
+ def on_close(&on_close)
17
+ @on_close = on_close
18
+ end
19
+
20
+ # Callback when a message is received. Parameters are
21
+ # @param msg [Array] The parsed message that was received
22
+ @on_message
23
+ def on_message(&on_message)
24
+ @on_message = on_message
25
+ end
26
+
27
+ # Callback when there is an error. Parameters are
28
+ @on_error
29
+ def on_error(&on_error)
30
+ @on_error = on_error
31
+ end
32
+
33
+ attr_accessor :type, :uri, :headers, :protocol, :serializer, :connected
34
+
35
+ # Constructor for the transport
36
+ # @param options [Hash] The connection options. the different options are as follows
37
+ # @option options [String] :uri The url to connect to
38
+ # @option options [String] :protocol The protocol
39
+ # @option options [Hash] :headers Custom headers to include during the connection
40
+ # @option options [WampClient::Serializer::Base] :serializer The serializer to use
41
+ def initialize(options)
42
+
43
+ # Initialize the parameters
44
+ self.connected = false
45
+ self.uri = options[:uri]
46
+ self.headers = options[:headers] || {}
47
+ self.protocol = options[:protocol] || 'wamp.2.json'
48
+ self.serializer = options[:serializer] || WampClient::Serializer::JSONSerializer.new
49
+
50
+ # Add the wamp.2.json protocol header
51
+ self.headers['Sec-WebSocket-Protocol'] = self.protocol
52
+
53
+ # Initialize callbacks
54
+ @on_open = nil
55
+ @on_close = nil
56
+ @on_message = nil
57
+ @on_error = nil
58
+
59
+ end
60
+
61
+ # Connects to the WAMP Server using the transport
62
+ def connect
63
+ # Implement in subclass
64
+ end
65
+
66
+ # Disconnects from the WAMP Server
67
+ def disconnect
68
+ # Implement in subclass
69
+ end
70
+
71
+ # Returns true if the transport it connected
72
+ def connected?
73
+ self.connected
74
+ end
75
+
76
+ # Sends a Message
77
+ # @param [Array] msg - The message payload to send
78
+ def send_message(msg)
79
+ # Implement in subclass
80
+ end
81
+
82
+ end
83
+
84
+ # This implementation uses the 'websocket-eventmachine-client' Gem. This is the default if no transport is included
85
+ class WebSocketTransport < Base
86
+ attr_accessor :socket
87
+
88
+ def initialize(options)
89
+ super(options)
90
+ self.type = 'websocket'
91
+ self.socket = nil
92
+ end
93
+
94
+ def connect
95
+ self.socket = WebSocket::EventMachine::Client.connect(
96
+ :uri => self.uri,
97
+ :headers => self.headers
98
+ )
99
+
100
+ self.socket.onopen do
101
+ self.connected = true
102
+ @on_open.call unless @on_open.nil?
103
+ end
104
+
105
+ self.socket.onmessage do |msg, type|
106
+ @on_message.call(self.serializer.deserialize(msg)) unless @on_message.nil?
107
+ end
108
+
109
+ self.socket.onclose do |code, reason|
110
+ self.connected = false
111
+ @on_close.call(reason) unless @on_close.nil?
112
+ end
113
+ end
114
+
115
+ def disconnect
116
+ self.connected = !self.socket.close # close returns 'true' if the connection was closed immediately
117
+ end
118
+
119
+ def send_message(msg)
120
+ if self.connected
121
+ self.socket.send(self.serializer.serialize(msg), {type: 'text'})
122
+ else
123
+ raise RuntimeError, "Socket must be open to call 'send_message'"
124
+ end
125
+ end
126
+
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,3 @@
1
+ module WampClient
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'wamp_client/version'
2
+ require 'wamp_client/message'
3
+ require 'wamp_client/serializer'
4
+ require 'wamp_client/transport'
5
+ require 'wamp_client/connection'
6
+ require 'wamp_client/session'
7
+ require 'wamp_client/auth'
@@ -0,0 +1,537 @@
1
+ #!/usr/bin/ruby
2
+
3
+ def value_from_type(type)
4
+
5
+ value = nil
6
+
7
+ if type == 'int' or type == 'id'
8
+ value = '123'
9
+ elsif type == 'uri' or type == 'string'
10
+ value = "'string'"
11
+ elsif type == 'list'
12
+ value = "['test']"
13
+ elsif type == 'dict'
14
+ value = '{ test: 1 }'
15
+ end
16
+
17
+ value
18
+
19
+ end
20
+
21
+ message_type_lookup = {
22
+ 'HELLO' => 1,
23
+ 'WELCOME' => 2,
24
+ 'ABORT' => 3,
25
+ 'CHALLENGE' => 4,
26
+ 'AUTHENTICATE' => 5,
27
+ 'GOODBYE' => 6,
28
+ 'ERROR' => 8,
29
+ 'PUBLISH' => 16,
30
+ 'PUBLISHED' => 17,
31
+ 'SUBSCRIBE' => 32,
32
+ 'SUBSCRIBED' => 33,
33
+ 'UNSUBSCRIBE' => 34,
34
+ 'UNSUBSCRIBED' => 35,
35
+ 'EVENT' => 36,
36
+ 'CALL' => 48,
37
+ 'CANCEL' => 49,
38
+ 'RESULT' => 50,
39
+ 'REGISTER' => 64,
40
+ 'REGISTERED' => 65,
41
+ 'UNREGISTER' => 66,
42
+ 'UNREGISTERED' => 67,
43
+ 'INVOCATION' => 68,
44
+ 'INTERRUPT' => 69,
45
+ 'YIELD' => 70
46
+ }
47
+
48
+ message_type_define = ''
49
+ message_lookup_define = ''
50
+ count = 0
51
+ message_type_lookup.each do |name, value|
52
+
53
+ # Generate the defines
54
+ message_type_define += " #{name} = #{value}\n"
55
+
56
+ # Generate the lookup
57
+ if count == 0
58
+ message_lookup_define += ' if'
59
+ else
60
+ message_lookup_define += ' elsif'
61
+ end
62
+ message_lookup_define += " params[0] == Types::#{name}\n"
63
+ message_lookup_define += " object = WampClient::Message::#{name.downcase.capitalize}.parse(params)\n"
64
+
65
+ count += 1
66
+ end
67
+
68
+ source_file_header = "require 'wamp_client/check'
69
+
70
+ # !!!!THIS FILE IS AUTOGENERATED. DO NOT HAND EDIT!!!!
71
+
72
+ module WampClient
73
+ module Message
74
+
75
+ module Types
76
+ #{message_type_define} end
77
+
78
+ class Base
79
+ include WampClient::Check
80
+
81
+ def payload
82
+ []
83
+ end
84
+
85
+ # @param params [Array]
86
+ def self.parse(params)
87
+ object = nil
88
+ #{message_lookup_define} end
89
+
90
+ object
91
+ end
92
+
93
+ end
94
+ "
95
+
96
+ source_file_footer = "
97
+ end
98
+ end
99
+ "
100
+
101
+ test_file_header = "require 'spec_helper'
102
+
103
+ # !!!!THIS FILE IS AUTOGENERATED. DO NOT HAND EDIT!!!!
104
+
105
+ describe WampClient::Message do
106
+ "
107
+
108
+ test_file_footer = "
109
+ end
110
+ "
111
+
112
+ source_file = source_file_header
113
+ test_file = test_file_header
114
+
115
+ ###############################################
116
+ # Iterate through message types
117
+ ###############################################
118
+
119
+ messages = [
120
+ {
121
+ name: 'hello',
122
+ description: 'Sent by a Client to initiate opening of a WAMP session to a Router attaching to a Realm.',
123
+ formats: [
124
+ '[HELLO, Realm|uri, Details|dict]'
125
+ ]
126
+ },
127
+ {
128
+ name: 'welcome',
129
+ description: 'Sent by a Router to accept a Client. The WAMP session is now open.',
130
+ formats: [
131
+ '[WELCOME, Session|id, Details|dict]'
132
+ ]
133
+ },
134
+ {
135
+ name: 'abort',
136
+ description: 'Sent by a Peer*to abort the opening of a WAMP session. No response is expected.',
137
+ formats: [
138
+ '[ABORT, Details|dict, Reason|uri]'
139
+ ]
140
+ },
141
+ {
142
+ name: 'goodbye',
143
+ description: "Sent by a Peer to close a previously opened WAMP session. Must be echo'ed by the receiving Peer.",
144
+ formats: [
145
+ '[GOODBYE, Details|dict, Reason|uri]'
146
+ ]
147
+ },
148
+ {
149
+ name: 'error',
150
+ description: 'Error reply sent by a Peer as an error response to different kinds of requests.',
151
+ formats: [
152
+ '[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri]',
153
+ '[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri, Arguments|list]',
154
+ '[ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, Error|uri, Arguments|list, ArgumentsKw|dict]'
155
+ ]
156
+ },
157
+ {
158
+ name: 'publish',
159
+ description: 'Sent by a Publisher to a Broker to publish an event.',
160
+ formats: [
161
+ '[PUBLISH, Request|id, Options|dict, Topic|uri]',
162
+ '[PUBLISH, Request|id, Options|dict, Topic|uri, Arguments|list]',
163
+ '[PUBLISH, Request|id, Options|dict, Topic|uri, Arguments|list, ArgumentsKw|dict]'
164
+ ]
165
+ },
166
+ {
167
+ name: 'published',
168
+ description: 'Acknowledge sent by a Broker to a Publisher for acknowledged publications.',
169
+ formats: [
170
+ '[PUBLISHED, PUBLISH.Request|id, Publication|id]'
171
+ ]
172
+ },
173
+ {
174
+ name: 'subscribe',
175
+ description: 'Subscribe request sent by a Subscriber to a Broker to subscribe to a topic.',
176
+ formats: [
177
+ '[SUBSCRIBE, Request|id, Options|dict, Topic|uri]'
178
+ ]
179
+ },
180
+ {
181
+ name: 'subscribed',
182
+ description: 'Acknowledge sent by a Broker to a Subscriber to acknowledge a subscription.',
183
+ formats: [
184
+ '[SUBSCRIBED, SUBSCRIBE.Request|id, Subscription|id]'
185
+ ]
186
+ },
187
+ {
188
+ name: 'unsubscribe',
189
+ description: 'Unsubscribe request sent by a Subscriber to a Broker to unsubscribe a subscription.',
190
+ formats: [
191
+ '[UNSUBSCRIBE, Request|id, SUBSCRIBED.Subscription|id]'
192
+ ]
193
+ },
194
+ {
195
+ name: 'unsubscribed',
196
+ description: 'Acknowledge sent by a Broker to a Subscriber to acknowledge unsubscription.',
197
+ formats: [
198
+ '[UNSUBSCRIBED, UNSUBSCRIBE.Request|id]'
199
+ ]
200
+ },
201
+ {
202
+ name: 'event',
203
+ description: 'Event dispatched by Broker to Subscribers for subscriptions the event was matching.',
204
+ formats: [
205
+ '[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict]',
206
+ '[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict, PUBLISH.Arguments|list]',
207
+ '[EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, Details|dict, PUBLISH.Arguments|list, PUBLISH.ArgumentsKw|dict]'
208
+ ]
209
+ },
210
+ {
211
+ name: 'call',
212
+ description: 'Call as originally issued by the _Caller_ to the _Dealer_.',
213
+ formats: [
214
+ '[CALL, Request|id, Options|dict, Procedure|uri]',
215
+ '[CALL, Request|id, Options|dict, Procedure|uri, Arguments|list]',
216
+ '[CALL, Request|id, Options|dict, Procedure|uri, Arguments|list, ArgumentsKw|dict]'
217
+ ]
218
+ },
219
+ {
220
+ name: 'result',
221
+ description: 'Result of a call as returned by _Dealer_ to _Caller_.',
222
+ formats: [
223
+ '[RESULT, CALL.Request|id, Details|dict]',
224
+ '[RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list]',
225
+ '[RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list, YIELD.ArgumentsKw|dict]'
226
+ ]
227
+ },
228
+ {
229
+ name: 'register',
230
+ description: 'A _Callees_ request to register an endpoint at a _Dealer_.',
231
+ formats: [
232
+ '[REGISTER, Request|id, Options|dict, Procedure|uri]'
233
+ ]
234
+ },
235
+ {
236
+ name: 'registered',
237
+ description: 'Acknowledge sent by a _Dealer_ to a _Callee_ for successful registration.',
238
+ formats: [
239
+ '[REGISTERED, REGISTER.Request|id, Registration|id]'
240
+ ]
241
+ },
242
+ {
243
+ name: 'unregister',
244
+ description: 'A _Callees_ request to unregister a previously established registration.',
245
+ formats: [
246
+ '[UNREGISTER, Request|id, REGISTERED.Registration|id]'
247
+ ]
248
+ },
249
+ {
250
+ name: 'unregistered',
251
+ description: 'Acknowledge sent by a _Dealer_ to a _Callee_ for successful unregistration.',
252
+ formats: [
253
+ '[UNREGISTERED, UNREGISTER.Request|id]'
254
+ ]
255
+ },
256
+ {
257
+ name: 'invocation',
258
+ description: 'Actual invocation of an endpoint sent by _Dealer_ to a _Callee_.',
259
+ formats: [
260
+ '[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict]',
261
+ '[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict, CALL.Arguments|list]',
262
+ '[INVOCATION, Request|id, REGISTERED.Registration|id, Details|dict, CALL.Arguments|list, CALL.ArgumentsKw|dict]'
263
+ ]
264
+ },
265
+ {
266
+ name: 'yield',
267
+ description: 'Actual yield from an endpoint sent by a _Callee_ to _Dealer_.',
268
+ formats: [
269
+ '[YIELD, INVOCATION.Request|id, Options|dict]',
270
+ '[YIELD, INVOCATION.Request|id, Options|dict, Arguments|list]',
271
+ '[YIELD, INVOCATION.Request|id, Options|dict, Arguments|list, ArgumentsKw|dict]'
272
+ ]
273
+ },
274
+ {
275
+ name: 'challenge',
276
+ description: 'The "CHALLENGE" message is used with certain Authentication Methods. During authenticated session establishment, a *Router* sends a challenge message.',
277
+ formats: [
278
+ '[CHALLENGE, AuthMethod|string, Extra|dict]'
279
+ ]
280
+ },
281
+ {
282
+ name: 'authenticate',
283
+ description: 'The "AUTHENTICATE" message is used with certain Authentication Methods. A *Client* having received a challenge is expected to respond by sending a signature or token.',
284
+ formats: [
285
+ '[AUTHENTICATE, Signature|string, Extra|dict]'
286
+ ]
287
+ },
288
+ {
289
+ name: 'cancel',
290
+ description: 'The "CANCEL" message is used with the Call Canceling advanced feature. A _Caller_ can cancel and issued call actively by sending a cancel message to the _Dealer_.',
291
+ formats: [
292
+ '[CANCEL, CALL.Request|id, Options|dict]'
293
+ ]
294
+ },
295
+ {
296
+ name: 'interrupt',
297
+ description: 'The "INTERRUPT" message is used with the Call Canceling advanced feature. Upon receiving a cancel for a pending call, a _Dealer_ will issue an interrupt to the _Callee_.',
298
+ formats: [
299
+ '[INTERRUPT, INVOCATION.Request|id, Options|dict]'
300
+ ]
301
+ }
302
+ ]
303
+
304
+ messages.each do |message|
305
+
306
+ ###############################################
307
+ # Generate Lookups
308
+ ###############################################
309
+ count = 0
310
+ params_lookup = {}
311
+ params = []
312
+ required_count = 0
313
+ param_formats = ''
314
+ message[:formats].each do |format|
315
+ param_formats += ' # ' + format + "\n"
316
+
317
+ # Generate the params
318
+ temp_format = format.delete(' ')
319
+ temp_format = temp_format.delete('[')
320
+ temp_format = temp_format.delete(']')
321
+ temp_format = temp_format.gsub('.', '_')
322
+ format_params = temp_format.split(',')
323
+ format_params.shift
324
+
325
+ format_params.each do |format_param|
326
+ parsed_param = format_param.split('|')
327
+ param_name = parsed_param[0].downcase
328
+ param_type = parsed_param[1]
329
+
330
+ if params_lookup[param_name].nil?
331
+ params.push(
332
+ {
333
+ name: param_name,
334
+ type: param_type,
335
+ required: count == 0
336
+ })
337
+ params_lookup[param_name] = true
338
+ end
339
+ end
340
+
341
+ if count == 0
342
+ required_count = params.count
343
+ end
344
+
345
+ count += 1
346
+ end
347
+
348
+ ###############################################
349
+ # Source File
350
+ ###############################################
351
+ source_file += "\n"
352
+ source_file += ' # ' + message[:name].capitalize + "\n"
353
+ source_file += ' # ' + message[:description] + "\n"
354
+ source_file += " # Formats:\n"
355
+ source_file += param_formats
356
+ source_file += ' class ' + message[:name].capitalize + " < Base\n"
357
+
358
+ # Generate the local variables
359
+ source_file += ' attr_accessor'
360
+ count = 0
361
+ params.each do |param|
362
+ source_file += ',' unless count == 0
363
+ source_file += " :#{param[:name]}"
364
+ count += 1
365
+ end
366
+ source_file += "\n"
367
+
368
+ # Generate the constructor
369
+ source_file += "\n def initialize("
370
+ count = 0
371
+ checks = ''
372
+ setters = ''
373
+ params.each do |param|
374
+ setters += " self.#{param[:name]} = #{param[:name]}\n"
375
+
376
+ source_file += ', ' if count > 0
377
+ if param[:required]
378
+ source_file += "#{param[:name]}"
379
+ checks += " self.class.check_#{param[:type]}('#{param[:name]}', #{param[:name]})\n"
380
+ else
381
+ source_file += "#{param[:name]}=nil"
382
+ checks += " self.class.check_#{param[:type]}('#{param[:name]}', #{param[:name]}, true)\n"
383
+ end
384
+
385
+ count += 1
386
+ end
387
+ source_file += ")\n\n"
388
+ source_file += checks + "\n"
389
+ source_file += setters + "\n"
390
+ source_file += " end\n"
391
+
392
+ # Generate the 'type' method
393
+ source_file += "\n def self.type\n Types::#{message[:name].upcase}\n end\n"
394
+
395
+ # Generate the parser
396
+ source_file += "\n def self.parse(params)\n"
397
+ source_file += "\n self.check_gte('params list', #{required_count+1}, params.count)\n"
398
+ source_file += " self.check_equal('message type', self.type, params[0])\n"
399
+ source_file += "\n params.shift\n self.new(*params)\n"
400
+ source_file += "\n end\n"
401
+
402
+ # Generate the payload
403
+ source_file += "\n def payload\n"
404
+ source_file += " payload = [self.class.type]\n"
405
+ params.each do |param|
406
+ if param[:required]
407
+ source_file += " payload.push(self.#{param[:name]})\n"
408
+ else
409
+ source_file += "\n return payload if (self.#{param[:name]}.nil? or self.#{param[:name]}.empty?)\n"
410
+ source_file += " payload.push(self.#{param[:name]})\n"
411
+ end
412
+ end
413
+ source_file += "\n payload\n"
414
+ source_file += " end\n"
415
+
416
+ # Generate the string
417
+ source_file += "\n def to_s\n"
418
+ source_file += " '#{message[:name].upcase} > ' + self.payload.to_s\n"
419
+ source_file += " end\n"
420
+
421
+
422
+ source_file += "\n end\n"
423
+
424
+ ###############################################
425
+ # Test File
426
+ ###############################################
427
+
428
+ value_array = []
429
+ params.each do |param|
430
+ if param[:required]
431
+ value_array.push(value_from_type(param[:type]))
432
+ end
433
+ end
434
+
435
+ class_name = "WampClient::Message::#{message[:name].capitalize}"
436
+
437
+ test_file += "\n describe #{class_name} do\n"
438
+
439
+ # Generate Constructor Test
440
+ test_file += "\n it 'creates the message object' do\n"
441
+ test_file += " params = [#{value_array.join(',')}]\n"
442
+ test_file += " object = #{class_name}.new(*params)\n\n"
443
+ params.each do |param|
444
+ if param[:required]
445
+ test_file += " expect(object.#{param[:name]}).to eq(#{value_from_type(param[:type])})\n"
446
+ end
447
+ end
448
+ test_file += " expect(object.is_a?(#{class_name})).to eq(true)\n"
449
+ test_file += " end\n"
450
+
451
+ # Generate Parser Test
452
+ test_file += "\n it 'parses the message and creates an object' do\n"
453
+ test_file += " params = [#{message_type_lookup[message[:name].upcase]},#{value_array.join(',')}]\n"
454
+ test_file += " object = #{class_name}.parse(params)\n\n"
455
+ params.each do |param|
456
+ if param[:required]
457
+ test_file += " expect(object.#{param[:name]}).to eq(#{value_from_type(param[:type])})\n"
458
+ end
459
+ end
460
+ test_file += " expect(object.is_a?(#{class_name})).to eq(true)\n"
461
+ test_file += " end\n"
462
+
463
+ # Generate Global Parser Test
464
+ test_file += "\n it 'globally parses the message and creates an object' do\n"
465
+ test_file += " params = [#{message_type_lookup[message[:name].upcase]},#{value_array.join(',')}]\n"
466
+ test_file += " object = WampClient::Message::Base.parse(params)\n\n"
467
+ params.each do |param|
468
+ if param[:required]
469
+ test_file += " expect(object.#{param[:name]}).to eq(#{value_from_type(param[:type])})\n"
470
+ end
471
+ end
472
+ test_file += " expect(object.is_a?(#{class_name})).to eq(true)\n"
473
+ test_file += " end\n"
474
+
475
+ # Generate Payload Test
476
+ test_file += "\n it 'generates the payload' do\n"
477
+ test_file += " params = [#{value_array.join(',')}]\n"
478
+ test_file += " object = #{class_name}.new(*params)\n"
479
+ test_file += " payload = object.payload\n\n"
480
+ count = 0
481
+ test_file += " expect(payload.count).to eq(#{value_array.count+1})\n"
482
+ test_file += " expect(payload[0]).to eq(#{message_type_lookup[message[:name].upcase]})\n"
483
+ value_array.each do |value|
484
+ test_file += " expect(payload[#{count+1}]).to eq(#{value})\n"
485
+ count += 1
486
+ end
487
+ test_file += " end\n"
488
+
489
+ # Generate non-required parameter tests
490
+ params.each do |param|
491
+ unless param[:required]
492
+ value_array.push(value_from_type(param[:type]))
493
+
494
+ test_file += "\n describe 'checks optional parameter #{param[:name]}' do\n"
495
+
496
+ # Generate Constructor Test
497
+ test_file += "\n it 'creates the message object' do\n"
498
+ test_file += " params = [#{value_array.join(',')}]\n"
499
+ test_file += " object = #{class_name}.new(*params)\n\n"
500
+ test_file += " expect(object.is_a?(#{class_name})).to eq(true)\n"
501
+ test_file += " end\n"
502
+
503
+ # Generate Parser Test
504
+ test_file += "\n it 'parses the message and creates an object' do\n"
505
+ test_file += " params = [#{message_type_lookup[message[:name].upcase]},#{value_array.join(',')}]\n"
506
+ test_file += " object = #{class_name}.parse(params)\n\n"
507
+ test_file += " expect(object.is_a?(#{class_name})).to eq(true)\n"
508
+ test_file += " end\n"
509
+
510
+ # Generate Payload Test
511
+ test_file += "\n it 'generates the payload' do\n"
512
+ test_file += " params = [#{value_array.join(',')}]\n"
513
+ test_file += " object = #{class_name}.new(*params)\n"
514
+ test_file += " payload = object.payload\n\n"
515
+ count = 0
516
+ test_file += " expect(payload.count).to eq(#{value_array.count+1})\n"
517
+ test_file += " expect(payload[0]).to eq(#{message_type_lookup[message[:name].upcase]})\n"
518
+ value_array.each do |value|
519
+ test_file += " expect(payload[#{count+1}]).to eq(#{value})\n"
520
+ count += 1
521
+ end
522
+ test_file += " end\n"
523
+
524
+ test_file += "\n end\n"
525
+ end
526
+ end
527
+
528
+ test_file += "\n end\n"
529
+
530
+ end
531
+
532
+ source_file += source_file_footer
533
+ test_file += test_file_footer
534
+
535
+ File.open('message.rb.tmp', 'w') { |file| file.write(source_file) }
536
+ File.open('message_spec.rb.tmp', 'w') { |file| file.write(test_file) }
537
+
data/spec/auth_spec.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe WampClient::Auth do
4
+
5
+ describe 'cra' do
6
+
7
+ it 'generates the signature' do
8
+
9
+ challenge = "{ \"nonce\": \"LHRTC9zeOIrt_9U3\", \"authprovider\": \"userdb\", \"authid\": \"peter\", \"timestamp\": \"2014-06-22T16:36:25.448Z\", \"authrole\": \"user\", \"authmethod\": \"wampcra\", \"session\": 3251278072152162}"
10
+ secret = 'secret'
11
+ signature = WampClient::Auth::Cra.sign(secret, challenge)
12
+ expect(signature).to eq('Pji30JC9tb/T9tbEwxw5i0RyRa5UVBxuoIVTgT7hnkE=')
13
+
14
+ end
15
+
16
+ end
17
+
18
+ end