protobuffy 3.1.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.
Files changed (192) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +12 -0
  4. data/.yardopts +5 -0
  5. data/CHANGES.md +261 -0
  6. data/CONTRIBUTING.md +16 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +14 -0
  9. data/README.md +58 -0
  10. data/Rakefile +61 -0
  11. data/bin/protoc-gen-ruby +17 -0
  12. data/bin/rpc_server +4 -0
  13. data/examples/bin/reverse-client-http +4 -0
  14. data/examples/bin/reverse-client-socket +4 -0
  15. data/examples/bin/reverse-client-zmq +4 -0
  16. data/examples/config.ru +6 -0
  17. data/examples/definitions/example/reverse.proto +12 -0
  18. data/examples/lib/example/reverse-client.rb +23 -0
  19. data/examples/lib/example/reverse-service.rb +9 -0
  20. data/examples/lib/example/reverse.pb.rb +36 -0
  21. data/lib/protobuf.rb +106 -0
  22. data/lib/protobuf/cli.rb +249 -0
  23. data/lib/protobuf/code_generator.rb +41 -0
  24. data/lib/protobuf/decoder.rb +74 -0
  25. data/lib/protobuf/deprecator.rb +42 -0
  26. data/lib/protobuf/descriptors.rb +3 -0
  27. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
  28. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
  29. data/lib/protobuf/encoder.rb +62 -0
  30. data/lib/protobuf/enum.rb +319 -0
  31. data/lib/protobuf/exceptions.rb +9 -0
  32. data/lib/protobuf/field.rb +74 -0
  33. data/lib/protobuf/field/base_field.rb +280 -0
  34. data/lib/protobuf/field/bool_field.rb +53 -0
  35. data/lib/protobuf/field/bytes_field.rb +81 -0
  36. data/lib/protobuf/field/double_field.rb +26 -0
  37. data/lib/protobuf/field/enum_field.rb +57 -0
  38. data/lib/protobuf/field/field_array.rb +86 -0
  39. data/lib/protobuf/field/fixed32_field.rb +25 -0
  40. data/lib/protobuf/field/fixed64_field.rb +29 -0
  41. data/lib/protobuf/field/float_field.rb +38 -0
  42. data/lib/protobuf/field/int32_field.rb +22 -0
  43. data/lib/protobuf/field/int64_field.rb +22 -0
  44. data/lib/protobuf/field/integer_field.rb +24 -0
  45. data/lib/protobuf/field/message_field.rb +66 -0
  46. data/lib/protobuf/field/sfixed32_field.rb +28 -0
  47. data/lib/protobuf/field/sfixed64_field.rb +29 -0
  48. data/lib/protobuf/field/signed_integer_field.rb +30 -0
  49. data/lib/protobuf/field/sint32_field.rb +22 -0
  50. data/lib/protobuf/field/sint64_field.rb +22 -0
  51. data/lib/protobuf/field/string_field.rb +35 -0
  52. data/lib/protobuf/field/uint32_field.rb +22 -0
  53. data/lib/protobuf/field/uint64_field.rb +22 -0
  54. data/lib/protobuf/field/varint_field.rb +68 -0
  55. data/lib/protobuf/generators/base.rb +71 -0
  56. data/lib/protobuf/generators/enum_generator.rb +42 -0
  57. data/lib/protobuf/generators/extension_generator.rb +28 -0
  58. data/lib/protobuf/generators/field_generator.rb +132 -0
  59. data/lib/protobuf/generators/file_generator.rb +140 -0
  60. data/lib/protobuf/generators/group_generator.rb +113 -0
  61. data/lib/protobuf/generators/message_generator.rb +99 -0
  62. data/lib/protobuf/generators/printable.rb +161 -0
  63. data/lib/protobuf/generators/service_generator.rb +27 -0
  64. data/lib/protobuf/http.rb +20 -0
  65. data/lib/protobuf/lifecycle.rb +46 -0
  66. data/lib/protobuf/logger.rb +86 -0
  67. data/lib/protobuf/message.rb +182 -0
  68. data/lib/protobuf/message/fields.rb +122 -0
  69. data/lib/protobuf/message/serialization.rb +84 -0
  70. data/lib/protobuf/optionable.rb +23 -0
  71. data/lib/protobuf/rpc/buffer.rb +79 -0
  72. data/lib/protobuf/rpc/client.rb +168 -0
  73. data/lib/protobuf/rpc/connector.rb +21 -0
  74. data/lib/protobuf/rpc/connectors/base.rb +54 -0
  75. data/lib/protobuf/rpc/connectors/common.rb +172 -0
  76. data/lib/protobuf/rpc/connectors/http.rb +90 -0
  77. data/lib/protobuf/rpc/connectors/socket.rb +73 -0
  78. data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
  79. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
  80. data/lib/protobuf/rpc/env.rb +58 -0
  81. data/lib/protobuf/rpc/error.rb +28 -0
  82. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  83. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  84. data/lib/protobuf/rpc/middleware.rb +25 -0
  85. data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
  86. data/lib/protobuf/rpc/middleware/logger.rb +91 -0
  87. data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
  88. data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
  89. data/lib/protobuf/rpc/middleware/runner.rb +18 -0
  90. data/lib/protobuf/rpc/rpc.pb.rb +53 -0
  91. data/lib/protobuf/rpc/server.rb +39 -0
  92. data/lib/protobuf/rpc/servers/http/server.rb +101 -0
  93. data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
  94. data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
  95. data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
  96. data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
  97. data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
  98. data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
  99. data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
  100. data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
  101. data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
  102. data/lib/protobuf/rpc/service.rb +179 -0
  103. data/lib/protobuf/rpc/service_directory.rb +245 -0
  104. data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
  105. data/lib/protobuf/rpc/service_filters.rb +273 -0
  106. data/lib/protobuf/rpc/stat.rb +148 -0
  107. data/lib/protobuf/socket.rb +22 -0
  108. data/lib/protobuf/tasks.rb +1 -0
  109. data/lib/protobuf/tasks/compile.rake +61 -0
  110. data/lib/protobuf/version.rb +3 -0
  111. data/lib/protobuf/wire_type.rb +10 -0
  112. data/lib/protobuf/zmq.rb +21 -0
  113. data/proto/dynamic_discovery.proto +44 -0
  114. data/proto/google/protobuf/compiler/plugin.proto +147 -0
  115. data/proto/google/protobuf/descriptor.proto +620 -0
  116. data/proto/rpc.proto +62 -0
  117. data/protobuffy.gemspec +37 -0
  118. data/spec/benchmark/tasks.rb +113 -0
  119. data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
  120. data/spec/data/data.bin +3 -0
  121. data/spec/data/types.bin +0 -0
  122. data/spec/encoding/all_types_spec.rb +91 -0
  123. data/spec/encoding/extreme_values_spec.rb +0 -0
  124. data/spec/functional/socket_server_spec.rb +59 -0
  125. data/spec/functional/zmq_server_spec.rb +103 -0
  126. data/spec/lib/protobuf/cli_spec.rb +267 -0
  127. data/spec/lib/protobuf/code_generator_spec.rb +60 -0
  128. data/spec/lib/protobuf/enum_spec.rb +239 -0
  129. data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
  130. data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
  131. data/spec/lib/protobuf/field_spec.rb +194 -0
  132. data/spec/lib/protobuf/generators/base_spec.rb +87 -0
  133. data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
  134. data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
  135. data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
  136. data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
  137. data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
  138. data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
  139. data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
  140. data/spec/lib/protobuf/logger_spec.rb +136 -0
  141. data/spec/lib/protobuf/message_spec.rb +368 -0
  142. data/spec/lib/protobuf/optionable_spec.rb +46 -0
  143. data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
  144. data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
  145. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
  146. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
  147. data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
  148. data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
  149. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
  150. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
  151. data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
  152. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
  153. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
  154. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
  155. data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
  156. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
  157. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
  158. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
  159. data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
  160. data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
  161. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
  162. data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
  163. data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
  164. data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
  165. data/spec/lib/protobuf_spec.rb +78 -0
  166. data/spec/spec_helper.rb +57 -0
  167. data/spec/support/all.rb +7 -0
  168. data/spec/support/packed_field.rb +22 -0
  169. data/spec/support/server.rb +94 -0
  170. data/spec/support/test/all_types.data.bin +0 -0
  171. data/spec/support/test/all_types.data.txt +119 -0
  172. data/spec/support/test/defaults.pb.rb +25 -0
  173. data/spec/support/test/defaults.proto +9 -0
  174. data/spec/support/test/enum.pb.rb +59 -0
  175. data/spec/support/test/enum.proto +34 -0
  176. data/spec/support/test/extended.pb.rb +22 -0
  177. data/spec/support/test/extended.proto +10 -0
  178. data/spec/support/test/extreme_values.data.bin +0 -0
  179. data/spec/support/test/google_unittest.pb.rb +543 -0
  180. data/spec/support/test/google_unittest.proto +713 -0
  181. data/spec/support/test/google_unittest_import.pb.rb +37 -0
  182. data/spec/support/test/google_unittest_import.proto +64 -0
  183. data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
  184. data/spec/support/test/google_unittest_import_public.proto +38 -0
  185. data/spec/support/test/multi_field_extensions.pb.rb +56 -0
  186. data/spec/support/test/multi_field_extensions.proto +33 -0
  187. data/spec/support/test/resource.pb.rb +117 -0
  188. data/spec/support/test/resource.proto +94 -0
  189. data/spec/support/test/resource_service.rb +26 -0
  190. data/spec/support/test_app_file.rb +2 -0
  191. data/spec/support/tolerance_matcher.rb +40 -0
  192. metadata +367 -0
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'spec/support/test/resource_service'
3
+ require 'protobuf/rpc/servers/socket_runner'
4
+ require 'protobuf/socket'
5
+
6
+ describe Protobuf::Rpc::Socket::Server do
7
+ before(:each) do
8
+ load 'protobuf/socket.rb'
9
+ end
10
+
11
+ before(:all) do
12
+ load 'protobuf/socket.rb'
13
+ Thread.abort_on_exception = true
14
+ @options = OpenStruct.new(:host => "127.0.0.1", :port => 9399, :backlog => 100, :threshold => 100)
15
+ @runner = ::Protobuf::Rpc::SocketRunner.new(@options)
16
+ @server = @runner.instance_variable_get(:@server)
17
+ @server_thread = Thread.new(@runner) { |runner| runner.run }
18
+ Thread.pass until @server.running?
19
+ end
20
+
21
+ after(:all) do
22
+ @server.stop
23
+ @server_thread.join
24
+ end
25
+
26
+ it "Runner provides a stop method" do
27
+ @runner.should respond_to(:stop)
28
+ end
29
+
30
+ it "provides a stop method" do
31
+ @server.should respond_to(:stop)
32
+ end
33
+
34
+ it "signals the Server is running" do
35
+ @server.should be_running
36
+ end
37
+
38
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'protobuf/rpc/servers/zmq/server'
3
+
4
+ describe Protobuf::Rpc::Zmq::Server do
5
+ subject { described_class.new(options) }
6
+
7
+ let(:options) {{
8
+ :host => '127.0.0.1',
9
+ :port => 9399,
10
+ :worker_port => 9400,
11
+ :workers_only => true
12
+ }}
13
+
14
+ before do
15
+ load 'protobuf/zmq.rb'
16
+ end
17
+
18
+ after do
19
+ subject.teardown
20
+ end
21
+
22
+ describe '.running?' do
23
+ it 'returns true if running' do
24
+ subject.instance_variable_set(:@running, true)
25
+ subject.running?.should be_true
26
+ end
27
+
28
+ it 'returns false if not running' do
29
+ subject.instance_variable_set(:@running, false)
30
+ subject.running?.should be_false
31
+ end
32
+ end
33
+
34
+ describe '.stop' do
35
+ it 'sets running to false' do
36
+ subject.instance_variable_set(:@workers, [])
37
+ subject.stop
38
+ subject.instance_variable_get(:@running).should be_false
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ class UtilTest
4
+ include ::Protobuf::Rpc::Zmq::Util
5
+ end
6
+
7
+ describe ::Protobuf::Rpc::Zmq::Util do
8
+ before(:each) do
9
+ load 'protobuf/zmq.rb'
10
+ end
11
+
12
+ subject { UtilTest.new }
13
+ describe '#zmq_error_check' do
14
+ it 'raises when the error code is less than 0' do
15
+ expect {
16
+ subject.zmq_error_check(-1, :test)
17
+ }.to raise_error(/test/)
18
+ end
19
+
20
+ it 'retrieves the error string from ZeroMQ' do
21
+ ZMQ::Util.stub(:error_string).and_return('an error from zmq')
22
+ expect {
23
+ subject.zmq_error_check(-1, :test)
24
+ }.to raise_error(RuntimeError, /an error from zmq/i)
25
+ end
26
+
27
+ it 'does nothing if the error code is > 0' do
28
+ expect {
29
+ subject.zmq_error_check(1, :test)
30
+ }.to_not raise_error
31
+ end
32
+
33
+ it 'does nothing if the error code is == 0' do
34
+ expect {
35
+ subject.zmq_error_check(0, :test)
36
+ }.to_not raise_error
37
+ end
38
+ end
39
+
40
+ describe '#log_signature' do
41
+ it 'returns the signature for the log' do
42
+ subject.log_signature.should include('server', 'UtilTest')
43
+ end
44
+ end
45
+
46
+ describe '.resolve_ip' do
47
+ it 'resolves ips' do
48
+ expect(subject.resolve_ip('127.0.0.1')).to eq('127.0.0.1')
49
+ end
50
+
51
+ it 'resolves non ips' do
52
+ expect(subject.resolve_ip('localhost')).to eq('127.0.0.1')
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Protobuf::Rpc::Zmq::Worker do
4
+ before(:each) do
5
+ load 'protobuf/zmq.rb'
6
+
7
+ fake_socket = double
8
+ fake_socket.should_receive(:connect).and_return(0)
9
+ fake_socket.should_receive(:send_string).and_return(0)
10
+
11
+ fake_context = double
12
+ fake_context.should_receive(:socket).and_return( fake_socket )
13
+ ::ZMQ::Context.should_receive(:new).and_return( fake_context )
14
+ end
15
+
16
+ subject do
17
+ described_class.new({ :host => '127.0.0.1', :port => 9400 })
18
+ end
19
+
20
+ describe '#run' do
21
+ # not tested via unit tests
22
+ end
23
+
24
+ describe '#handle_request' do
25
+ # not tested via unit tests
26
+ end
27
+
28
+ describe '#initialize_buffers' do
29
+ # not tested via unit tests
30
+ end
31
+
32
+ describe '#send_data' do
33
+ # not tested via unit tests
34
+ end
35
+ end
@@ -0,0 +1,295 @@
1
+ require 'spec_helper'
2
+
3
+ require 'protobuf/rpc/service_directory'
4
+
5
+ describe ::Protobuf::Rpc::ServiceDirectory do
6
+ subject { described_class.instance }
7
+
8
+ let(:echo_server) {
9
+ ::Protobuf::Rpc::DynamicDiscovery::Server.new(
10
+ :uuid => 'echo',
11
+ :address => '127.0.0.1',
12
+ :port => '1111',
13
+ :ttl => 10,
14
+ :services => %w[EchoService]
15
+ )
16
+ }
17
+
18
+ let(:hello_server) {
19
+ ::Protobuf::Rpc::DynamicDiscovery::Server.new(
20
+ :uuid => "hello",
21
+ :address => '127.0.0.1',
22
+ :port => "1112",
23
+ :ttl => 10,
24
+ :services => %w[HelloService]
25
+ )
26
+ }
27
+
28
+ let(:hello_server_with_short_ttl) {
29
+ ::Protobuf::Rpc::DynamicDiscovery::Server.new(
30
+ :uuid => "hello_server_with_short_ttl",
31
+ :address => '127.0.0.1',
32
+ :port => '1113',
33
+ :ttl => 1,
34
+ :services => %w[HelloService]
35
+ )
36
+ }
37
+
38
+ let(:combo_server) {
39
+ ::Protobuf::Rpc::DynamicDiscovery::Server.new(
40
+ :uuid => "combo",
41
+ :address => '127.0.0.1',
42
+ :port => '1114',
43
+ :ttl => 10,
44
+ :services => %w[HelloService EchoService]
45
+ )
46
+ }
47
+
48
+ before(:all) do
49
+ @address = "127.0.0.1"
50
+ @port = 33333
51
+ @socket = UDPSocket.new
52
+ EchoService = Class.new
53
+
54
+ described_class.address = @address
55
+ described_class.port = @port
56
+ end
57
+
58
+ def expect_event_trigger(event)
59
+ ::ActiveSupport::Notifications
60
+ .should_receive(:instrument)
61
+ .with(event, hash_including(:listing => an_instance_of(::Protobuf::Rpc::ServiceDirectory::Listing)))
62
+ .once
63
+ end
64
+
65
+ def send_beacon(type, server)
66
+ type = type.to_s.upcase
67
+ beacon = ::Protobuf::Rpc::DynamicDiscovery::Beacon.new(
68
+ :server => server,
69
+ :beacon_type => ::Protobuf::Rpc::DynamicDiscovery::BeaconType.fetch(type)
70
+ )
71
+
72
+ @socket.send(beacon.encode, 0, @address, @port)
73
+ sleep 0.01 # give the service directory time to process the beacon
74
+ end
75
+
76
+ it "should be a singleton" do
77
+ subject.should be_a_kind_of(Singleton)
78
+ end
79
+
80
+ it "should be configured to listen to address 127.0.0.1" do
81
+ described_class.address.should eq '127.0.0.1'
82
+ end
83
+
84
+ it "should be configured to listen to port 33333" do
85
+ described_class.port.should eq 33333
86
+ end
87
+
88
+ it "should defer .start to the instance#start" do
89
+ described_class.instance.should_receive(:start)
90
+ described_class.start
91
+ end
92
+
93
+ it "should yeild itself to blocks passed to .start" do
94
+ described_class.instance.stub(:start)
95
+ expect { |b| described_class.start(&b) }.to yield_with_args(described_class)
96
+ end
97
+
98
+ it "should defer .stop to the instance#stop" do
99
+ described_class.instance.should_receive(:stop)
100
+ described_class.stop
101
+ end
102
+
103
+ context "stopped" do
104
+ before { subject.stop }
105
+
106
+ describe "#lookup" do
107
+ it "should return nil" do
108
+ send_beacon(:heartbeat, echo_server)
109
+ subject.lookup("EchoService").should be_nil
110
+ end
111
+ end
112
+
113
+ describe "#restart" do
114
+ it "should start the service" do
115
+ subject.restart
116
+ subject.should be_running
117
+ end
118
+ end
119
+
120
+ describe "#running" do
121
+ it "should be false" do
122
+ subject.should_not be_running
123
+ end
124
+ end
125
+
126
+ describe "#stop" do
127
+ it "has no effect" do
128
+ subject.stop
129
+ end
130
+ end
131
+ end
132
+
133
+ context "started" do
134
+ before { subject.start }
135
+ after { subject.stop }
136
+
137
+ it { should be_running }
138
+
139
+ it "should trigger added events" do
140
+ expect_event_trigger("directory.listing.added")
141
+ send_beacon(:heartbeat, echo_server)
142
+ end
143
+
144
+ it "should trigger updated events" do
145
+ send_beacon(:heartbeat, echo_server)
146
+ expect_event_trigger("directory.listing.updated")
147
+ send_beacon(:heartbeat, echo_server)
148
+ end
149
+
150
+ it "should trigger removed events" do
151
+ send_beacon(:heartbeat, echo_server)
152
+ expect_event_trigger("directory.listing.removed")
153
+ send_beacon(:flatline, echo_server)
154
+ end
155
+
156
+ describe "#all_listings_for" do
157
+ context "when listings are present" do
158
+ it "returns all listings for a given service" do
159
+ send_beacon(:heartbeat, hello_server)
160
+ send_beacon(:heartbeat, combo_server)
161
+
162
+ subject.all_listings_for("HelloService").size.should eq(2)
163
+ end
164
+ end
165
+
166
+ context "when no listings are present" do
167
+ it "returns and empty array" do
168
+ subject.all_listings_for("HelloService").size.should eq(0)
169
+ end
170
+ end
171
+ end
172
+
173
+ describe "#each_listing" do
174
+ it "should yield to a block for each listing" do
175
+ send_beacon(:heartbeat, hello_server)
176
+ send_beacon(:heartbeat, echo_server)
177
+ send_beacon(:heartbeat, combo_server)
178
+
179
+ expect { |block|
180
+ subject.each_listing(&block)
181
+ }.to yield_control.exactly(3).times
182
+ end
183
+ end
184
+
185
+ describe "#lookup" do
186
+ it "should provide listings by service" do
187
+ send_beacon(:heartbeat, hello_server)
188
+ subject.lookup("HelloService").to_hash.should eq hello_server.to_hash
189
+ end
190
+
191
+ it "should return random listings" do
192
+ send_beacon(:heartbeat, hello_server)
193
+ send_beacon(:heartbeat, combo_server)
194
+
195
+ uuids = 100.times.map { subject.lookup("HelloService").uuid }
196
+ uuids.count("hello").should be_within(25).of(50)
197
+ uuids.count("combo").should be_within(25).of(50)
198
+ end
199
+
200
+ it "should not return expired listings" do
201
+ send_beacon(:heartbeat, hello_server_with_short_ttl)
202
+ sleep 1
203
+ subject.lookup("HelloService").should be_nil
204
+ end
205
+
206
+ it "should not return flatlined servers" do
207
+ send_beacon(:heartbeat, echo_server)
208
+ send_beacon(:heartbeat, combo_server)
209
+ send_beacon(:flatline, echo_server)
210
+
211
+ uuids = 100.times.map { subject.lookup("EchoService").uuid }
212
+ uuids.count("combo").should eq 100
213
+ end
214
+
215
+ it "should return up-to-date listings" do
216
+ send_beacon(:heartbeat, echo_server)
217
+ echo_server.port = "7777"
218
+ send_beacon(:heartbeat, echo_server)
219
+
220
+ subject.lookup("EchoService").port.should eq "7777"
221
+ end
222
+
223
+ context 'when given service identifier is a class name' do
224
+ it 'returns the listing corresponding to the class name' do
225
+ send_beacon(:heartbeat, echo_server)
226
+ subject.lookup(EchoService).uuid.should eq echo_server.uuid
227
+ end
228
+ end
229
+ end
230
+
231
+ describe "#restart" do
232
+ it "should clear all listings" do
233
+ send_beacon(:heartbeat, echo_server)
234
+ send_beacon(:heartbeat, combo_server)
235
+ subject.restart
236
+ subject.lookup("EchoService").should be_nil
237
+ end
238
+ end
239
+
240
+ describe "#running" do
241
+ it "should be true" do
242
+ subject.should be_running
243
+ end
244
+ end
245
+
246
+ describe "#stop" do
247
+ it "should clear all listings" do
248
+ send_beacon(:heartbeat, echo_server)
249
+ send_beacon(:heartbeat, combo_server)
250
+ subject.stop
251
+ subject.lookup("EchoService").should be_nil
252
+ end
253
+
254
+ it "should stop the server" do
255
+ subject.stop
256
+ subject.should_not be_running
257
+ end
258
+ end
259
+ end
260
+
261
+ if ENV.key?("BENCH")
262
+ context "performance" do
263
+ let(:servers) {
264
+ 100.times.collect do |x|
265
+ ::Protobuf::Rpc::DynamicDiscovery::Server.new(
266
+ :uuid => "performance_server#{x + 1}",
267
+ :address => '127.0.0.1',
268
+ :port => (5555 + x).to_s,
269
+ :ttl => rand(1..5),
270
+ :services => 10.times.collect { |y| "PerformanceService#{y}" }
271
+ )
272
+ end
273
+ }
274
+
275
+ before do
276
+ require 'benchmark'
277
+ subject.start
278
+ servers.each { |server| send_beacon(:heartbeat, server) }
279
+ end
280
+
281
+ after do
282
+ subject.stop
283
+ end
284
+
285
+ it "should perform lookups in constant time" do
286
+ print "\n\n"
287
+ Benchmark.bm(17) do |x|
288
+ x.report(" 1_000 lookups:") { 1_000.times { subject.lookup("PerformanceService#{rand(0..9)}") } }
289
+ x.report(" 10_000 lookups:") { 10_000.times { subject.lookup("PerformanceService#{rand(0..9)}") } }
290
+ x.report("100_000 lookups:") { 100_000.times { subject.lookup("PerformanceService#{rand(0..9)}") } }
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end