protobuf 1.1.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile.lock +44 -25
  3. data/README.md +2 -2
  4. data/Rakefile +15 -0
  5. data/bin/rpc_server +52 -11
  6. data/lib/protobuf.rb +22 -10
  7. data/lib/protobuf/common/logger.rb +26 -25
  8. data/lib/protobuf/descriptor/file_descriptor.rb +1 -1
  9. data/lib/protobuf/message/field.rb +2 -2
  10. data/lib/protobuf/rpc/buffer.rb +30 -25
  11. data/lib/protobuf/rpc/client.rb +8 -8
  12. data/lib/protobuf/rpc/connector.rb +2 -0
  13. data/lib/protobuf/rpc/connectors/base.rb +0 -1
  14. data/lib/protobuf/rpc/connectors/common.rb +48 -48
  15. data/lib/protobuf/rpc/connectors/em_client.rb +53 -27
  16. data/lib/protobuf/rpc/connectors/eventmachine.rb +14 -17
  17. data/lib/protobuf/rpc/connectors/socket.rb +23 -16
  18. data/lib/protobuf/rpc/connectors/zmq.rb +73 -0
  19. data/lib/protobuf/rpc/error.rb +1 -2
  20. data/lib/protobuf/rpc/error/client_error.rb +4 -4
  21. data/lib/protobuf/rpc/server.rb +31 -43
  22. data/lib/protobuf/rpc/servers/evented/server.rb +43 -0
  23. data/lib/protobuf/rpc/servers/evented_runner.rb +1 -1
  24. data/lib/protobuf/rpc/servers/socket/server.rb +108 -0
  25. data/lib/protobuf/rpc/servers/socket/worker.rb +59 -0
  26. data/lib/protobuf/rpc/servers/socket_runner.rb +3 -3
  27. data/lib/protobuf/rpc/servers/zmq/broker.rb +85 -0
  28. data/lib/protobuf/rpc/servers/zmq/server.rb +50 -0
  29. data/lib/protobuf/rpc/servers/zmq/util.rb +27 -0
  30. data/lib/protobuf/rpc/servers/zmq/worker.rb +72 -0
  31. data/lib/protobuf/rpc/servers/zmq_runner.rb +26 -0
  32. data/lib/protobuf/rpc/service.rb +5 -5
  33. data/lib/protobuf/version.rb +1 -1
  34. data/protobuf.gemspec +12 -10
  35. data/spec/benchmark/tasks.rb +37 -5
  36. data/spec/functional/evented_server_spec.rb +64 -0
  37. data/spec/functional/socket_server_spec.rb +63 -0
  38. data/spec/functional/zmq_server_spec.rb +63 -0
  39. data/spec/helper/server.rb +32 -12
  40. data/spec/lib/protobuf/message/encoder_spec.rb +19 -0
  41. data/spec/proto/test.pb.rb +3 -3
  42. data/spec/proto/test.proto +3 -3
  43. data/spec/proto/test_service.rb +1 -0
  44. data/spec/spec_helper.rb +6 -0
  45. data/spec/unit/message_spec.rb +1 -1
  46. data/spec/unit/rpc/client_spec.rb +11 -3
  47. data/spec/unit/rpc/connectors/common_spec.rb +0 -1
  48. data/spec/unit/rpc/connectors/eventmachine_client_spec.rb +32 -0
  49. data/spec/unit/rpc/connectors/socket_spec.rb +2 -4
  50. data/spec/unit/rpc/connectors/zmq_spec.rb +27 -0
  51. data/spec/unit/rpc/servers/evented_server_spec.rb +3 -3
  52. data/spec/unit/rpc/servers/socket_server_spec.rb +14 -13
  53. data/spec/unit/rpc/servers/zmq/broker_spec.rb +27 -0
  54. data/spec/unit/rpc/servers/zmq/server_spec.rb +37 -0
  55. data/spec/unit/rpc/servers/zmq/util_spec.rb +41 -0
  56. data/spec/unit/rpc/servers/zmq/worker_spec.rb +36 -0
  57. data/spec/unit/rpc/service_spec.rb +22 -18
  58. metadata +87 -40
  59. data/lib/protobuf/rpc/servers/evented_server.rb +0 -28
  60. data/lib/protobuf/rpc/servers/socket_server.rb +0 -146
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+ require 'spec/proto/test_service_impl'
3
+
4
+ describe 'Functional EventMachine Client' do
5
+ before(:each) do
6
+ ::Spec::Proto::TestService.configure(::Spec::Proto::TestService::DEFAULT_LOCATION)
7
+ end
8
+
9
+ it 'runs fine when required fields are set' do
10
+ expect {
11
+ EventMachine.fiber_run do
12
+ StubServer.new do |server|
13
+ client = ::Spec::Proto::TestService.client(:async => false, :timeout => 5)
14
+
15
+ client.find(:name => 'Test Name', :active => true) do |c|
16
+ c.on_success do |succ|
17
+ succ.name.should eq("Test Name")
18
+ succ.status.should eq(::Spec::Proto::StatusType::ENABLED)
19
+ end
20
+
21
+ c.on_failure do |err|
22
+ raise err.inspect
23
+ end
24
+ end
25
+ end
26
+ EM.stop
27
+ end
28
+ }.to_not raise_error
29
+ end
30
+
31
+ it 'calls the on_failure callback when a message is malformed' do
32
+ error = nil
33
+ EventMachine.fiber_run do
34
+ StubServer.new do |server|
35
+ request = ::Spec::Proto::ResourceFindRequest.new(:active => true)
36
+ client = ::Spec::Proto::TestService.client(:async => false)
37
+
38
+ client.find(request) do |c|
39
+ c.on_success { raise "shouldn't pass"}
40
+ c.on_failure {|e| error = e}
41
+ end
42
+ end
43
+ EM.stop
44
+ end
45
+ error.message.should =~ /ResourceFindRequest.*fields.*improperly set.*"name"/
46
+ end
47
+
48
+ it 'calls the on_failure callback when the request type is wrong' do
49
+ error = nil
50
+ EventMachine.fiber_run do
51
+ StubServer.new do |server|
52
+ request = ::Spec::Proto::Resource.new(:name => 'Test Name')
53
+ client = ::Spec::Proto::TestService.client(:async => false)
54
+
55
+ client.find(request) do |c|
56
+ c.on_success { raise "shouldn't pass"}
57
+ c.on_failure {|e| error = e}
58
+ end
59
+ end
60
+ EM.stop
61
+ end
62
+ error.message.should =~ /expected request.*ResourceFindRequest.*Resource instead/i
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'spec/proto/test_service_impl'
3
+
4
+ describe 'Functional Socket Client' do
5
+ before(:all) do
6
+ Thread.abort_on_exception = true
7
+ server = OpenStruct.new(:server => "127.0.0.1", :port => 9399, :backlog => 100, :threshold => 100)
8
+ @server_thread = Thread.new(server) { |s| Protobuf::Rpc::SocketRunner.run(s) }
9
+ Thread.pass until Protobuf::Rpc::Socket::Server.running?
10
+ end
11
+
12
+ after(:all) do
13
+ Protobuf::Rpc::SocketRunner.stop
14
+ @server_thread.join
15
+ end
16
+
17
+ it 'runs fine when required fields are set' do
18
+ expect {
19
+ with_constants "Protobuf::ClientType" => "Socket" do
20
+ client = ::Spec::Proto::TestService.client(:async => false)
21
+
22
+ client.find(:name => 'Test Name', :active => true) do |c|
23
+ c.on_success do |succ|
24
+ succ.name.should eq("Test Name")
25
+ succ.status.should eq(::Spec::Proto::StatusType::ENABLED)
26
+ end
27
+
28
+ c.on_failure do |err|
29
+ raise err.inspect
30
+ end
31
+ end
32
+ end
33
+ }.to_not raise_error
34
+ end
35
+
36
+ it 'calls the on_failure callback when a message is malformed' do
37
+ error = nil
38
+ with_constants "Protobuf::ClientType" => "Socket" do
39
+ request = ::Spec::Proto::ResourceFindRequest.new(:active => true)
40
+ client = ::Spec::Proto::TestService.client(:async => false)
41
+
42
+ client.find(request) do |c|
43
+ c.on_success { raise "shouldn't pass"}
44
+ c.on_failure {|e| error = e}
45
+ end
46
+ end
47
+ error.message.should =~ /ResourceFindRequest.*fields.*improperly set.*"name"/
48
+ end
49
+
50
+ it 'calls the on_failure callback when the request type is wrong' do
51
+ error = nil
52
+ with_constants "Protobuf::ClientType" => "Socket" do
53
+ request = ::Spec::Proto::Resource.new(:name => 'Test Name')
54
+ client = ::Spec::Proto::TestService.client(:async => false)
55
+
56
+ client.find(request) do |c|
57
+ c.on_success { raise "shouldn't pass"}
58
+ c.on_failure {|e| error = e}
59
+ end
60
+ end
61
+ error.message.should =~ /expected request.*ResourceFindRequest.*Resource instead/i
62
+ end
63
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'spec/proto/test_service_impl'
3
+
4
+ describe 'Functional ZMQ Client' do
5
+ before(:all) do
6
+ Thread.abort_on_exception = true
7
+ server = OpenStruct.new(:server => "127.0.0.1", :port => 9399, :backlog => 100, :threshold => 100)
8
+ @server_thread = Thread.new(server) { |s| Protobuf::Rpc::ZmqRunner.run(s) }
9
+ Thread.pass until Protobuf::Rpc::Zmq::Server.running?
10
+ end
11
+
12
+ after(:all) do
13
+ ::Protobuf::Rpc::Zmq::Server.stop
14
+ @server_thread.join
15
+ end
16
+
17
+ it 'runs fine when required fields are set' do
18
+ expect {
19
+ with_constants "Protobuf::ClientType" => "Zmq" do
20
+ client = ::Spec::Proto::TestService.client(:async => false)
21
+
22
+ client.find(:name => 'Test Name', :active => true) do |c|
23
+ c.on_success do |succ|
24
+ succ.name.should eq("Test Name")
25
+ succ.status.should eq(::Spec::Proto::StatusType::ENABLED)
26
+ end
27
+
28
+ c.on_failure do |err|
29
+ raise err.inspect
30
+ end
31
+ end
32
+ end
33
+ }.to_not raise_error
34
+ end
35
+
36
+ it 'calls the on_failure callback when a message is malformed' do
37
+ error = nil
38
+ with_constants "Protobuf::ClientType" => "Zmq" do
39
+ request = ::Spec::Proto::ResourceFindRequest.new(:active => true)
40
+ client = ::Spec::Proto::TestService.client(:async => false)
41
+
42
+ client.find(request) do |c|
43
+ c.on_success { raise "shouldn't pass"}
44
+ c.on_failure {|e| error = e}
45
+ end
46
+ end
47
+ error.message.should =~ /ResourceFindRequest.*fields.*improperly set.*"name"/
48
+ end
49
+
50
+ it 'calls the on_failure callback when the request type is wrong' do
51
+ error = nil
52
+ with_constants "Protobuf::ClientType" => "Zmq" do
53
+ request = ::Spec::Proto::Resource.new(:name => 'Test Name')
54
+ client = ::Spec::Proto::TestService.client(:async => false)
55
+
56
+ client.find(request) do |c|
57
+ c.on_success { raise "shouldn't pass"}
58
+ c.on_failure {|e| error = e}
59
+ end
60
+ end
61
+ error.message.should =~ /expected request.*ResourceFindRequest.*Resource instead/i
62
+ end
63
+ end
@@ -1,13 +1,18 @@
1
1
  require 'ostruct'
2
2
  require 'protobuf/common/logger'
3
3
  require 'protobuf/rpc/server'
4
- require 'protobuf/rpc/servers/socket_server'
4
+ require 'protobuf/rpc/servers/socket/server'
5
5
  require 'protobuf/rpc/servers/socket_runner'
6
+ require 'protobuf/rpc/servers/zmq/server'
7
+ require 'protobuf/rpc/servers/zmq_runner'
6
8
  require 'spec/proto/test_service_impl'
7
9
 
10
+ # Want to abort if server dies?
11
+ Thread.abort_on_exception = true
12
+
8
13
  module StubProtobufServerFactory
9
14
  def self.build(delay)
10
- new_server = Class.new(Protobuf::Rpc::EventedServer) do
15
+ new_server = Class.new(Protobuf::Rpc::Evented::Server) do
11
16
  def self.sleep_interval
12
17
  @sleep_interval
13
18
  end
@@ -38,7 +43,7 @@ class StubServer
38
43
  :host => "127.0.0.1",
39
44
  :port => 9399,
40
45
  :delay => 0,
41
- :server => Protobuf::Rpc::EventedServer
46
+ :server => Protobuf::Rpc::Evented::Server
42
47
  }.merge(opts))
43
48
 
44
49
  start
@@ -48,14 +53,13 @@ class StubServer
48
53
  end
49
54
 
50
55
  def start
51
- if @options.server == Protobuf::Rpc::EventedServer
52
- start_em_server
56
+ case
57
+ when @options.server == Protobuf::Rpc::Evented::Server then start_em_server
58
+ when @options.server == Protobuf::Rpc::Zmq::Server then start_zmq_server
53
59
  else
54
- @sock_server = Thread.new(@options) { |opt| Protobuf::Rpc::SocketRunner.run(opt) }
55
- @sock_server.abort_on_exception = true # Set for testing purposes
56
- Thread.pass until Protobuf::Rpc::SocketServer.running?
60
+ start_socket_server
57
61
  end
58
- log_debug "[stub-server] Server started #{@options.host}:#{@options.port}"
62
+ log_debug { "[stub-server] Server started #{@options.host}:#{@options.port}" }
59
63
  rescue => ex
60
64
  if ex =~ /no acceptor/ # Means EM didn't shutdown in the next_tick yet
61
65
  stop
@@ -64,16 +68,32 @@ class StubServer
64
68
  end
65
69
 
66
70
  def start_em_server
67
- @server_handle = EventMachine::start_server(@options.host, @options.port, StubProtobufServerFactory.build(@options.delay))
71
+ @server_handle = EventMachine.start_server(@options.host, @options.port, StubProtobufServerFactory.build(@options.delay))
72
+ end
73
+
74
+ def start_socket_server
75
+ @sock_server = Thread.new(@options) { |opt| Protobuf::Rpc::SocketRunner.run(opt) }
76
+ @sock_server.abort_on_exception = true # Set for testing purposes
77
+ Thread.pass until Protobuf::Rpc::Socket::Server.running?
78
+ end
79
+
80
+ def start_zmq_server
81
+ @zmq_server = Thread.new(@options) { |opt| Protobuf::Rpc::ZmqRunner.run(opt) }
82
+ Thread.pass until Protobuf::Rpc::Zmq::Server.running?
68
83
  end
69
84
 
70
85
  def stop
71
- if @options.server == Protobuf::Rpc::EventedServer
86
+ case
87
+ when @options.server == Protobuf::Rpc::Evented::Server then
72
88
  EventMachine.stop_server(@server_handle) if @server_handle
89
+ when @options.server == Protobuf::Rpc::Zmq::Server then
90
+ Protobuf::Rpc::ZmqRunner.stop
91
+ @zmq_server.join if(@zmq_server)
73
92
  else
74
93
  Protobuf::Rpc::SocketRunner.stop
75
- Thread.kill(@sock_server) if @sock_server
94
+ @sock_server.join if(@sock_server)
76
95
  end
96
+
77
97
  @running = false
78
98
  end
79
99
  end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ class EncoderTest
4
+ extend ::Protobuf::Encoder
5
+ end
6
+
7
+ describe Protobuf::Encoder do
8
+ describe '#encode' do
9
+ context "when there's no value for a required field" do
10
+ let(:message) { ::Spec::Proto::Resource.new }
11
+ let(:stream) { StringIO.new }
12
+ it "raises a 'message not initialized' error" do
13
+ expect {
14
+ EncoderTest.__send__(:encode, stream, message)
15
+ }.to raise_error(Protobuf::NotInitializedError, /message.*not initialized/i)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -12,11 +12,11 @@ module Spec
12
12
  define :DELETED, 3
13
13
  end
14
14
  class ResourceFindRequest < ::Protobuf::Message
15
- optional :string, :name, 1
15
+ required :string, :name, 1
16
16
  optional :bool, :active, 2
17
17
  end
18
18
  class Resource < ::Protobuf::Message
19
- optional :string, :name, 1
19
+ required :string, :name, 1
20
20
  optional :int64, :date_created, 2
21
21
  optional :StatusType, :status, 3
22
22
  repeated :StatusType, :repeated_enum, 4
@@ -28,4 +28,4 @@ module Spec
28
28
  optional :StatusType, :status, 4
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -8,12 +8,12 @@ enum StatusType {
8
8
  }
9
9
 
10
10
  message ResourceFindRequest {
11
- optional string name = 1;
11
+ required string name = 1;
12
12
  optional bool active = 2;
13
13
  }
14
14
 
15
15
  message Resource {
16
- optional string name = 1;
16
+ required string name = 1;
17
17
  optional int64 date_created = 2;
18
18
  optional StatusType status = 3;
19
19
  repeated StatusType repeated_enum = 4;
@@ -28,4 +28,4 @@ message Nested {
28
28
 
29
29
  service TestService {
30
30
  rpc Find (ResourceFindRequest) returns (Resource);
31
- }
31
+ }
@@ -1,4 +1,5 @@
1
1
  require 'protobuf/rpc/service'
2
+ require 'spec/proto/test.pb'
2
3
 
3
4
  ## !! DO NOT EDIT THIS FILE !!
4
5
  ##
@@ -11,6 +11,12 @@ $:.push File.expand_path('../lib', File.dirname(__FILE__))
11
11
  require 'protobuf'
12
12
  require 'protobuf/rpc/client'
13
13
  require File.dirname(__FILE__) + '/helper/all'
14
+ require 'pry'
15
+
16
+ # these aren't explicitly required in lib/protobuf.rb. We require them here for
17
+ # testing purposes
18
+ require 'ffi-rzmq'
19
+ require 'protobuf/rpc/connectors/zmq'
14
20
 
15
21
  # Including a way to turn on debug logger for spec runs
16
22
  if ENV["DEBUG"]
@@ -64,4 +64,4 @@ describe Protobuf::Message do
64
64
 
65
65
  end
66
66
 
67
- end
67
+ end
@@ -2,6 +2,9 @@ require 'spec_helper'
2
2
  require 'spec/proto/test_service_impl'
3
3
 
4
4
  describe Protobuf::Rpc::Client do
5
+ before(:each) do
6
+ ::Spec::Proto::TestService.configure(::Spec::Proto::TestService::DEFAULT_LOCATION)
7
+ end
5
8
 
6
9
  context "when using fiber based calls" do
7
10
  it "waits for response when running synchronously" do
@@ -55,17 +58,22 @@ describe Protobuf::Rpc::Client do
55
58
  end
56
59
 
57
60
  it "throws a timeout when client timeout is exceeded" do
58
- subject = Proc.new do
61
+ error = nil
62
+ test_proc = Proc.new do
59
63
  EventMachine.fiber_run do
60
64
  StubServer.new(:delay => 2) do |server|
61
65
  client = Spec::Proto::TestService.client(:async => false, :timeout => 1)
62
- client.find(:name => "Test Name", :active => true)
66
+ client.find(:name => "Test Name", :active => true) do |cl|
67
+ cl.on_success {}
68
+ cl.on_failure {|f| error = f}
69
+ end
63
70
  end
64
71
  EM.stop
65
72
  end
66
73
  end
67
74
 
68
- subject.should raise_error(RuntimeError, /timeout/i)
75
+ test_proc.call
76
+ error.message.should =~ /timeout/i
69
77
  end
70
78
 
71
79
  context "without reactor_running?" do
@@ -19,7 +19,6 @@ describe Protobuf::Rpc::Connectors::Common do
19
19
  specify{ subject.respond_to?(:fail).should be_true }
20
20
  specify{ subject.respond_to?(:complete).should be_true }
21
21
  specify{ subject.respond_to?(:parse_response).should be_true }
22
- specify{ subject.respond_to?(:_send_request).should be_true }
23
22
  specify{ subject.respond_to?(:verify_options).should be_true }
24
23
  specify{ subject.respond_to?(:verify_callbacks).should be_true }
25
24
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::Protobuf::Rpc::Connectors::EMClient do
4
+ describe '#send_data' do
5
+ context 'when sending data errs' do
6
+ let(:buffer_double) do
7
+ bd = double(Protobuf::Rpc::Buffer)
8
+ bd.should_receive(:set_data)
9
+ bd
10
+ end
11
+
12
+ it 'sets the error instance' do
13
+ buffer_double.should_receive(:write).and_raise(RuntimeError.new('Failure for testing'))
14
+ Protobuf::Rpc::Buffer.stub(:new).with(:read).and_return(Protobuf::Rpc::Buffer.new(:read))
15
+ Protobuf::Rpc::Buffer.stub(:new).with(:write).and_return(buffer_double)
16
+ error = nil
17
+ test_proc = Proc.new do
18
+ StubServer.new do |server|
19
+ client = ::Spec::Proto::TestService.client
20
+ client.find(:name => 'Test Name', :active => true) do |c|
21
+ c.on_failure do |f|
22
+ error = f
23
+ end
24
+ end
25
+ end
26
+ end
27
+ test_proc.call
28
+ error.should_not be_nil
29
+ end
30
+ end
31
+ end
32
+ end
@@ -24,13 +24,12 @@ describe Protobuf::Rpc::Connectors::Socket do
24
24
 
25
25
  it "fills the buffer with data from the socket" do
26
26
  socket = StringIO.new("#{data.bytesize}-#{data}")
27
- subject.instance_variable_set(:@buffer, Protobuf::Rpc::Buffer.new(:read))
28
27
  subject.instance_variable_set(:@socket, socket)
28
+ subject.instance_variable_set(:@stats, OpenStruct.new)
29
29
  subject.should_receive(:parse_response).and_return(true)
30
30
 
31
31
  subject.__send__(:read_response)
32
- subject.instance_variable_get(:@buffer).flushed?.should be_true
33
- subject.instance_variable_get(:@buffer).data.should eq(data)
32
+ subject.instance_variable_get(:@response_data).should eq(data)
34
33
  end
35
34
  end
36
35
 
@@ -45,5 +44,4 @@ describe Protobuf::Rpc::Connectors::Socket do
45
44
  expect{ conn.__send__(:check_async) }.to_not raise_error
46
45
  end
47
46
  end
48
-
49
47
  end