wamp_client 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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