bridge-ruby 0.2.0
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.
- data/LICENSE +19 -0
- data/README.md +31 -0
- data/Rakefile +24 -0
- data/bridge-ruby.gemspec +24 -0
- data/doc/Bridge.html +276 -0
- data/doc/Bridge/Bridge.html +1874 -0
- data/doc/Bridge/Bridge/SystemService.html +396 -0
- data/doc/Bridge/Client.html +271 -0
- data/doc/Bridge/Connection.html +1180 -0
- data/doc/Bridge/Connection/SockBuffer.html +322 -0
- data/doc/Bridge/Reference.html +605 -0
- data/doc/Bridge/Serializer.html +405 -0
- data/doc/Bridge/Serializer/Callback.html +498 -0
- data/doc/Bridge/Tcp.html +657 -0
- data/doc/Bridge/Util.html +643 -0
- data/doc/Bridge/Util/CallbackReference.html +557 -0
- data/doc/OpenSSL/X509/Certificate.html +275 -0
- data/doc/SSLCertificateVerification.html +446 -0
- data/doc/_index.html +239 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +106 -0
- data/doc/file_list.html +55 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +106 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +772 -0
- data/doc/top-level-namespace.html +112 -0
- data/examples/channels/client-writeable.rb +24 -0
- data/examples/channels/client.rb +23 -0
- data/examples/channels/server.rb +24 -0
- data/examples/chat/chatclient.rb +21 -0
- data/examples/chat/chatserver.rb +24 -0
- data/examples/client-context/client.rb +21 -0
- data/examples/client-context/server.rb +25 -0
- data/examples/secure/example.rb +8 -0
- data/examples/simple/channels.rb +47 -0
- data/examples/simple/services.rb +41 -0
- data/include/ssl/cacert.pem +3331 -0
- data/lib/bridge-ruby.rb +441 -0
- data/lib/client.rb +14 -0
- data/lib/connection.rb +162 -0
- data/lib/reference.rb +49 -0
- data/lib/serializer.rb +104 -0
- data/lib/ssl_utils.rb +68 -0
- data/lib/tcp.rb +73 -0
- data/lib/util.rb +101 -0
- data/lib/version.rb +3 -0
- data/rakelib/package.rake +4 -0
- data/rakelib/test.rake +8 -0
- data/test/regression/reconnect.rb +48 -0
- data/test/regression/rpc.rb +39 -0
- data/test/regression/test.rb +58 -0
- data/test/unit/bridge_dummy.rb +26 -0
- data/test/unit/connection_dummy.rb +21 -0
- data/test/unit/reference_dummy.rb +11 -0
- data/test/unit/tcp_dummy.rb +12 -0
- data/test/unit/test.rb +20 -0
- data/test/unit/test_reference.rb +30 -0
- data/test/unit/test_serializer.rb +109 -0
- data/test/unit/test_tcp.rb +51 -0
- data/test/unit/test_util.rb +59 -0
- metadata +162 -0
data/lib/util.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
module Bridge
|
7
|
+
module Util #:nodoc: all
|
8
|
+
|
9
|
+
@log = Logger.new(STDOUT)
|
10
|
+
|
11
|
+
def self.generate_guid
|
12
|
+
chars = (('a'..'z').to_a + (0..9).to_a)
|
13
|
+
(0...12).map{ chars[rand(26)] }.join
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.stringify obj
|
17
|
+
JSON::generate obj
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.parse str
|
21
|
+
JSON::parse str
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.info msg
|
25
|
+
@log.info msg
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.warn msg
|
29
|
+
@log.warn msg
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.error msg
|
33
|
+
@log.error msg
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.set_log_level level
|
37
|
+
if level > 2
|
38
|
+
@log.level = Logger::INFO
|
39
|
+
elsif level == 2
|
40
|
+
@log.level = Logger::WARN
|
41
|
+
elsif level == 1
|
42
|
+
@log.level = Logger::ERROR
|
43
|
+
else
|
44
|
+
@log.level = Logger::FATAL
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.ref_callback ref
|
49
|
+
CallbackReference.new ref do |*args, &blk|
|
50
|
+
args << blk if blk
|
51
|
+
self.call *args
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.find_ops obj
|
56
|
+
if obj.is_a? Module
|
57
|
+
return obj.methods false
|
58
|
+
else
|
59
|
+
return obj.class.instance_methods false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class CallbackReference < Proc
|
64
|
+
def initialize ref
|
65
|
+
@ref = ref
|
66
|
+
end
|
67
|
+
|
68
|
+
def callback *args, &blk
|
69
|
+
args << blk if blk
|
70
|
+
@ref.callback *args
|
71
|
+
end
|
72
|
+
|
73
|
+
def call *args, &blk
|
74
|
+
args << blk if blk
|
75
|
+
@ref.callback *args
|
76
|
+
end
|
77
|
+
|
78
|
+
def method atom
|
79
|
+
if atom.to_s == 'callback'
|
80
|
+
self
|
81
|
+
else
|
82
|
+
Class.method atom
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def methods bool
|
87
|
+
[:callback]
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_dict op = nil
|
91
|
+
@ref.to_dict op
|
92
|
+
end
|
93
|
+
|
94
|
+
def respond_to? atom
|
95
|
+
atom == :callback || atom == :to_dict || Class.respond_to?(atom)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
data/lib/version.rb
ADDED
data/rakelib/test.rake
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../../lib/bridge'
|
2
|
+
require_relative './test'
|
3
|
+
|
4
|
+
description = 'Reconnects';
|
5
|
+
failureMessage = 'This implementation of the Bridge API does not support reconnects.';
|
6
|
+
|
7
|
+
=begin
|
8
|
+
Passing this test means the following:
|
9
|
+
|
10
|
+
We can connect, reconnects (seem to) work. buffering between reconnects
|
11
|
+
works, services are preserved between these reconnects (i.e. should happen
|
12
|
+
in < 5s), and client ID is preserved.
|
13
|
+
=end
|
14
|
+
|
15
|
+
EM::run do
|
16
|
+
test = Test.new(failureMessage, 1, 4)
|
17
|
+
|
18
|
+
class T
|
19
|
+
def initialize(test, id)
|
20
|
+
@id = id
|
21
|
+
@test = test
|
22
|
+
@test.advance 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def cb(id)
|
26
|
+
if id != @id
|
27
|
+
@test.fail "ID not preserved."
|
28
|
+
end
|
29
|
+
@test.advance 3
|
30
|
+
@test.close
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
bridge = Bridge::Bridge.new({:api_key => 'abcdefgh'}).connect {
|
35
|
+
test.advance 0
|
36
|
+
}
|
37
|
+
|
38
|
+
bridge.ready {
|
39
|
+
svc = T.new(test, bridge.connection.client_id)
|
40
|
+
bridge.publish_service('test_reconn', svc) {
|
41
|
+
test.advance 2
|
42
|
+
bridge.connection.sock.close_connection
|
43
|
+
EM::Timer.new(0) {
|
44
|
+
bridge.get_service('test_reconn') {|service| service.cb(bridge.connection.client_id)}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../lib/bridge'
|
2
|
+
require_relative './test'
|
3
|
+
|
4
|
+
description = 'Basic RPC';
|
5
|
+
failureMessage = 'This implementation of the Bridge API is incapable of RPC.';
|
6
|
+
|
7
|
+
=begin
|
8
|
+
Passing this test means the following:
|
9
|
+
|
10
|
+
We can connect (it seems), we can publish a service, the callback to
|
11
|
+
publishService is called, and calling a method of getService works.
|
12
|
+
|
13
|
+
=end
|
14
|
+
|
15
|
+
EM::run do
|
16
|
+
test = Test.new(failureMessage, 2, 3)
|
17
|
+
|
18
|
+
bridge = Bridge::Bridge.new({:api_key => 'abcdefgh'}).connect {
|
19
|
+
test.advance 0
|
20
|
+
}
|
21
|
+
|
22
|
+
module ConsoleLogServer
|
23
|
+
def self.log(msg = "", test)
|
24
|
+
if msg == '123'
|
25
|
+
test.advance(2)
|
26
|
+
else
|
27
|
+
test.log('received ' + msg + ' but expected 123')
|
28
|
+
end
|
29
|
+
test.close
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
bridge.ready {
|
34
|
+
bridge.publish_service('test_consolelog', ConsoleLogServer) {
|
35
|
+
test.advance 1
|
36
|
+
bridge.get_service('test_consolelog') {|service| service.log('123', test)}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
class Test
|
4
|
+
def initialize failureMessage, logLevel, stages
|
5
|
+
@messages = []
|
6
|
+
@stages = stages
|
7
|
+
@stage = 0
|
8
|
+
@failureMessage = failureMessage
|
9
|
+
@timer = EM::Timer.new(5) { self.fail "timeout" }
|
10
|
+
if !(logLevel == 0 || logLevel == 1 || logLevel == 2)
|
11
|
+
raise "Invalid log level #{logLevel}"
|
12
|
+
end
|
13
|
+
@logLevel = logLevel
|
14
|
+
end
|
15
|
+
|
16
|
+
def advance expected
|
17
|
+
if @stage != expected
|
18
|
+
self.fail "out of order: at stage #{@stage}, not #{expected}"
|
19
|
+
else
|
20
|
+
@stage += 1
|
21
|
+
@timer.cancel
|
22
|
+
@timer = EM::Timer.new(5) { self.fail "timeout" }
|
23
|
+
if @logLevel > 0
|
24
|
+
puts "Advancing to stage #{@stage}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def close
|
30
|
+
if @stage != @stages
|
31
|
+
puts "Failure: reached stage #{@stage} of #{@stages}"
|
32
|
+
else
|
33
|
+
puts "Success; passed this test."
|
34
|
+
end
|
35
|
+
|
36
|
+
Process::exit
|
37
|
+
end
|
38
|
+
|
39
|
+
def fail(m = failureMessage)
|
40
|
+
puts "============================================"
|
41
|
+
puts " Description: ", m
|
42
|
+
if @logLevel != 0
|
43
|
+
puts " Message stack: "
|
44
|
+
@messages.each {|msg| puts msg}
|
45
|
+
end
|
46
|
+
self.close
|
47
|
+
end
|
48
|
+
|
49
|
+
def log msg
|
50
|
+
if @logLevel != 0
|
51
|
+
@messages += msg
|
52
|
+
if logLevel == 2
|
53
|
+
puts msg
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "reference_dummy.rb"
|
2
|
+
|
3
|
+
class BridgeDummy
|
4
|
+
|
5
|
+
attr_accessor :last_args, :last_dest, :stored, :options
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@options = {
|
9
|
+
:redirector => 'http://redirector.getbridge.com',
|
10
|
+
:reconnect => true,
|
11
|
+
:log => 2, # 0 for no output
|
12
|
+
}
|
13
|
+
@stored = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def store_object handler, ops
|
17
|
+
@stored << [handler, ops]
|
18
|
+
return ReferenceDummy.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def send args, destination
|
22
|
+
@last_args = args
|
23
|
+
@last_dest = destination
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ConnectionDummy
|
2
|
+
|
3
|
+
attr_accessor :messages, :onopened
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@messages = []
|
7
|
+
@onopened = false
|
8
|
+
end
|
9
|
+
|
10
|
+
def onopen *args
|
11
|
+
@onopened = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def onclose *args
|
15
|
+
end
|
16
|
+
|
17
|
+
def onmessage data, tcp
|
18
|
+
messages << data[:data]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/test/unit/test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter "/test/"
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
require_relative '../../lib/bridge'
|
9
|
+
require_relative '../../lib/connection'
|
10
|
+
require_relative '../../lib/reference'
|
11
|
+
require_relative '../../lib/serializer'
|
12
|
+
require_relative '../../lib/tcp'
|
13
|
+
require_relative '../../lib/util'
|
14
|
+
require_relative '../../lib/version'
|
15
|
+
|
16
|
+
require_relative 'test_util.rb'
|
17
|
+
require_relative 'test_serializer.rb'
|
18
|
+
require_relative 'test_tcp.rb'
|
19
|
+
require_relative 'test_reference.rb'
|
20
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "bridge"
|
2
|
+
require_relative "bridge_dummy.rb"
|
3
|
+
require "test/unit"
|
4
|
+
|
5
|
+
class TestReference < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
## Nothing really
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def test_reference
|
17
|
+
dummy = BridgeDummy.new
|
18
|
+
ref = Bridge::Reference.new dummy, ['x', 'y', 'z'], [:a, :b, :c]
|
19
|
+
assert_equal(['a', 'b', 'c'], ref.operations)
|
20
|
+
assert_equal({:ref => ['x', 'y', 'z'], :operations => ['a', 'b', 'c']}, ref.to_dict)
|
21
|
+
|
22
|
+
blk = lambda {}
|
23
|
+
ref.test 1, 2, &blk
|
24
|
+
assert_equal([1,2,blk], dummy.last_args)
|
25
|
+
assert_equal(['x', 'y', 'z', 'test'], dummy.last_dest[:ref])
|
26
|
+
assert(!dummy.last_dest.key?(:operations))
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require "bridge"
|
2
|
+
require_relative "bridge_dummy.rb"
|
3
|
+
require_relative "reference_dummy.rb"
|
4
|
+
require "test/unit"
|
5
|
+
|
6
|
+
class TestSerializer < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
## Nothing really
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def test_serialize
|
18
|
+
dummy = BridgeDummy.new
|
19
|
+
test2 = Test2.new
|
20
|
+
test3 = Test3.new
|
21
|
+
test4 = lambda {}
|
22
|
+
obj = {
|
23
|
+
:a => {
|
24
|
+
:b => Test1
|
25
|
+
},
|
26
|
+
:c => 5,
|
27
|
+
:d => true,
|
28
|
+
:e => 'abc',
|
29
|
+
:f => [test2, test3],
|
30
|
+
:g => test2,
|
31
|
+
:h => test3,
|
32
|
+
:i => test4
|
33
|
+
}
|
34
|
+
ser = Bridge::Serializer.serialize dummy, obj
|
35
|
+
|
36
|
+
assert(dummy.stored.include?([Test1, [:a]]))
|
37
|
+
assert(dummy.stored.include?([test2, [:c]]))
|
38
|
+
assert(dummy.stored.include?([test3, [:d, :e]]))
|
39
|
+
|
40
|
+
found = false
|
41
|
+
dummy.stored.each do | x |
|
42
|
+
if x[1] == ['callback']
|
43
|
+
assert_instance_of(Bridge::Serializer::Callback, x[0])
|
44
|
+
found = true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
assert found
|
49
|
+
|
50
|
+
expected_ser = {
|
51
|
+
:a => {
|
52
|
+
:b => "dummy"
|
53
|
+
},
|
54
|
+
:c => 5,
|
55
|
+
:d => true,
|
56
|
+
:e => 'abc',
|
57
|
+
:f => ["dummy", "dummy"],
|
58
|
+
:g => "dummy",
|
59
|
+
:h => "dummy",
|
60
|
+
:i => "dummy"
|
61
|
+
}
|
62
|
+
|
63
|
+
assert_equal(expected_ser, ser)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_unserialize
|
67
|
+
dummy = BridgeDummy.new
|
68
|
+
obj = {
|
69
|
+
:a => {'ref' => ['x','x','x'], 'operations' => ['a','b']},
|
70
|
+
:b => {
|
71
|
+
:i => {'ref' => ['z','z','z'], 'operations' => ['callback']}
|
72
|
+
},
|
73
|
+
:c => 5,
|
74
|
+
:d => true,
|
75
|
+
:e => 'abc',
|
76
|
+
:f => [1, {'ref' => ['y','y','y'], 'operations' => ['c','d']}],
|
77
|
+
:g => 2,
|
78
|
+
:h => 'foo'
|
79
|
+
}
|
80
|
+
|
81
|
+
unser = Bridge::Serializer.unserialize dummy, obj
|
82
|
+
|
83
|
+
assert_instance_of(Bridge::Reference, unser[:a])
|
84
|
+
assert_instance_of(Bridge::Reference, unser[:f][1])
|
85
|
+
assert_instance_of(Bridge::Util::CallbackReference, unser[:b][:i])
|
86
|
+
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
module Test1
|
91
|
+
def self.a
|
92
|
+
end
|
93
|
+
def b
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Test2
|
98
|
+
def c
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class Test3 < Test2
|
103
|
+
def d
|
104
|
+
end
|
105
|
+
def e
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|