protobuf 2.0.0.rc3 → 2.0.0.rc4

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 (43) hide show
  1. data/lib/protobuf/cli.rb +1 -2
  2. data/lib/protobuf/{common/exceptions.rb → exceptions.rb} +0 -0
  3. data/lib/protobuf/field/base_field.rb +1 -1
  4. data/lib/protobuf/{common/logger.rb → logger.rb} +21 -0
  5. data/lib/protobuf/message/decoder.rb +2 -2
  6. data/lib/protobuf/message/encoder.rb +6 -4
  7. data/lib/protobuf/rpc/buffer.rb +2 -2
  8. data/lib/protobuf/rpc/client.rb +18 -18
  9. data/lib/protobuf/rpc/connectors/base.rb +3 -8
  10. data/lib/protobuf/rpc/connectors/common.rb +29 -28
  11. data/lib/protobuf/rpc/connectors/em_client.rb +9 -9
  12. data/lib/protobuf/rpc/connectors/eventmachine.rb +11 -9
  13. data/lib/protobuf/rpc/connectors/socket.rb +13 -17
  14. data/lib/protobuf/rpc/connectors/zmq.rb +13 -17
  15. data/lib/protobuf/rpc/error.rb +3 -3
  16. data/lib/protobuf/rpc/server.rb +41 -93
  17. data/lib/protobuf/rpc/servers/evented/server.rb +7 -9
  18. data/lib/protobuf/rpc/servers/evented_runner.rb +0 -11
  19. data/lib/protobuf/rpc/servers/socket/server.rb +8 -7
  20. data/lib/protobuf/rpc/servers/socket/worker.rb +22 -15
  21. data/lib/protobuf/rpc/servers/zmq/server.rb +3 -3
  22. data/lib/protobuf/rpc/servers/zmq/util.rb +1 -1
  23. data/lib/protobuf/rpc/servers/zmq/worker.rb +6 -15
  24. data/lib/protobuf/rpc/service.rb +145 -228
  25. data/lib/protobuf/rpc/service_dispatcher.rb +114 -0
  26. data/lib/protobuf/rpc/stat.rb +46 -33
  27. data/lib/protobuf/version.rb +1 -1
  28. data/lib/protobuf/{common/wire_type.rb → wire_type.rb} +0 -0
  29. data/spec/benchmark/tasks.rb +18 -18
  30. data/spec/functional/evented_server_spec.rb +3 -4
  31. data/spec/functional/socket_server_spec.rb +3 -3
  32. data/spec/functional/zmq_server_spec.rb +3 -3
  33. data/spec/lib/protobuf/{common/logger_spec.rb → logger_spec.rb} +46 -36
  34. data/spec/lib/protobuf/rpc/client_spec.rb +10 -58
  35. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +1 -39
  36. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +3 -6
  37. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +0 -12
  38. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +1 -6
  39. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +94 -0
  40. data/spec/lib/protobuf/rpc/service_spec.rb +132 -45
  41. data/spec/spec_helper.rb +4 -3
  42. data/spec/support/server.rb +8 -4
  43. metadata +41 -35
@@ -0,0 +1,114 @@
1
+ require 'protobuf/logger'
2
+
3
+ module Protobuf
4
+ module Rpc
5
+ class ServiceDispatcher
6
+
7
+ include ::Protobuf::Logger::LogMethods
8
+
9
+ attr_accessor :service, :service_klass, :callable_method, :outer_request
10
+ attr_accessor :definition, :response, :error
11
+
12
+ def initialize(wrapper_request)
13
+ self.error = nil
14
+ self.outer_request = wrapper_request
15
+
16
+ init_service
17
+ init_method if service_klass.present?
18
+ register_rpc_failed if service.present?
19
+ end
20
+
21
+ # Call the given service method. If we get to this point and an error
22
+ # has already occurred, do not invoke the method and simply respond.
23
+ #
24
+ def invoke!
25
+ unless error?
26
+ callable_method.call
27
+ validate_response
28
+ end
29
+
30
+ return error || response
31
+ end
32
+
33
+ # We're successful if the error is not populated.
34
+ #
35
+ def success?
36
+ error.nil?
37
+ end
38
+
39
+ # We're in error if the error is populated.
40
+ #
41
+ def error?
42
+ ! success?
43
+ end
44
+
45
+ private
46
+
47
+ def assign_error(error_klass, message)
48
+ self.error = error_klass.new(message)
49
+ end
50
+
51
+ # Get the method for the current request.
52
+ #
53
+ def init_method
54
+ method_name = outer_request.method_name.underscore.to_sym
55
+ if service_klass.rpc_method?(method_name)
56
+ self.service = service_klass.new(method_name, outer_request.request_proto)
57
+ self.callable_method = service.method(method_name)
58
+ self.definition = service.rpcs[method_name]
59
+ else
60
+ assign_error(MethodNotFound, "#{service.class.name}##{method_name} is not a defined rpc method.")
61
+ end
62
+ rescue NameError => e
63
+ log_exception(e)
64
+ assign_error(MethodNotFound, "#{service.class.name}##{method_name} is not implemented.")
65
+ end
66
+
67
+ # Constantize the service for this request. Initialization of the service
68
+ # happens when we verify that the method is callable for this service.
69
+ #
70
+ def init_service
71
+ self.service_klass = outer_request.service_name.constantize
72
+ rescue NameError => e
73
+ log_exception(e)
74
+ assign_error(ServiceNotFound, "Service class #{outer_request.service_name} is not defined.")
75
+ end
76
+
77
+ # Make sure we get rpc errors back.
78
+ #
79
+ def register_rpc_failed
80
+ service.on_rpc_failed(method(:rpc_failed_callback))
81
+ end
82
+
83
+ # Receive the failure message from the service. This method is registered
84
+ # as the callable to the service when an `rpc_failed` call is invoked.
85
+ #
86
+ def rpc_failed_callback(message)
87
+ assign_error(RpcFailed, (message.respond_to?(:message) ? message.message : message))
88
+ log_error { sign_message("RPC Failed: #{error.message}") }
89
+ end
90
+
91
+ # Ensure that the response candidate we've been given is of the type
92
+ # we expect so that deserialization on the client side works.
93
+ #
94
+ def validate_response
95
+ expected = definition.response_type
96
+
97
+ candidate = service.response
98
+ candidate = expected.new(candidate) if candidate.is_a?(Hash)
99
+
100
+ actual = candidate.class
101
+ log_debug { sign_message("response (should/actual): #{expected.name}/#{actual.name}") }
102
+
103
+ # Determine if the service tried to change response types on us
104
+ if expected != actual
105
+ assign_error(BadResponseProto, "Response proto changed from #{expected.name} to #{actual.name}")
106
+ else
107
+ self.response = candidate
108
+ end
109
+ end
110
+
111
+ end
112
+ end
113
+ end
114
+
@@ -1,69 +1,82 @@
1
1
  require 'date'
2
- require 'protobuf/common/logger'
2
+ require 'protobuf/logger'
3
3
 
4
4
  module Protobuf
5
5
  module Rpc
6
6
  class Stat
7
- attr_accessor :type, :start_time, :end_time, :request_size, :response_size, :client, :server, :service, :method
8
-
9
- TYPES = [:SERVER, :CLIENT]
10
-
11
- def initialize type=:SERVER, do_start=true
12
- @type = type
13
- start if do_start
7
+ attr_accessor :mode, :start_time, :end_time, :request_size, :dispatcher
8
+ attr_accessor :response_size, :client, :server, :service, :method
9
+
10
+ MODES = [:SERVER, :CLIENT].freeze
11
+
12
+ def initialize(mode = :SERVER)
13
+ @mode = mode
14
+ start
14
15
  end
15
-
16
- def client= peer
16
+
17
+ def client=(peer)
17
18
  @client = {:port => peer[0], :ip => peer[1]}
18
19
  end
19
-
20
+
20
21
  def client
21
- @client ? '%s:%d' % [@client[:ip], @client[:port]] : nil
22
+ @client ? "#{@client[:ip]}:#{@client[:port]}" : nil
23
+ end
24
+
25
+ def method
26
+ @method ||= @dispatcher.try(:callable_method).try(:name)
22
27
  end
23
-
24
- def server= peer
28
+
29
+ def server=(peer)
25
30
  @server = {:port => peer[0], :ip => peer[1]}
26
31
  end
27
-
32
+
28
33
  def server
29
- @server ? '%s:%d' % [@server[:ip], @server[:port]] : nil
34
+ @server ? "#{@server[:ip]}:#{@server[:port]}" : nil
35
+ end
36
+
37
+ def service
38
+ @service ||= @dispatcher.try(:service).class.name
30
39
  end
31
-
40
+
32
41
  def sizes
33
- '%dB/%dB' % [@request_size || 0, @response_size || 0]
42
+ "#{@request_size || 0}B/#{@response_size || 0}B"
34
43
  end
35
-
44
+
36
45
  def start
37
46
  @start_time ||= Time.now
38
47
  end
39
-
40
- def end
48
+
49
+ def stop
41
50
  start if !@start_time
42
51
  @end_time ||= Time.now
43
52
  end
44
-
53
+
45
54
  def rpc
46
- service && method ? '%s#%s' % [service, method] : nil
55
+ service && method ? "#{service}##{method}" : nil
47
56
  end
48
-
57
+
49
58
  def elapsed_time
50
- (start_time && end_time ? '%ss' % (end_time - start_time).round(4) : nil)
59
+ (start_time && end_time ? "#{(end_time - start_time).round(4)}s" : nil)
51
60
  end
52
-
53
- def log_stats
54
- Protobuf::Logger.info(self.to_s)
61
+
62
+ def server?
63
+ @mode == :SERVER
64
+ end
65
+
66
+ def client?
67
+ @mode == :CLIENT
55
68
  end
56
-
69
+
57
70
  def to_s
58
71
  [
59
- @type == :SERVER ? "[SRV-#{self.class}]" : "[CLT-#{self.class}]",
72
+ server? ? "[SRV-#{self.class}]" : "[CLT-#{self.class}]",
60
73
  rpc,
61
74
  elapsed_time,
62
75
  sizes,
63
- @type == :SERVER ? server : client
64
- ].delete_if{|v| v.nil? }.join(' - ')
76
+ server? ? server : client
77
+ ].compact.join(' - ')
65
78
  end
66
-
79
+
67
80
  end
68
81
  end
69
82
  end
@@ -1,4 +1,4 @@
1
1
  module Protobuf
2
- VERSION = '2.0.0.rc3'
2
+ VERSION = '2.0.0.rc4'
3
3
  PROTOC_VERSION = '2.4.1'
4
4
  end
@@ -4,7 +4,7 @@ require 'support/test/resource_service'
4
4
  require 'perftools'
5
5
 
6
6
  # Including a way to turn on debug logger for spec runs
7
- if ENV["DEBUG"]
7
+ if ENV["DEBUG"]
8
8
  puts 'debugging'
9
9
  debug_log = File.expand_path('../debug_bench.log', File.dirname(__FILE__) )
10
10
  Protobuf::Logger.configure(:file => debug_log, :level => ::Logger::DEBUG)
@@ -25,12 +25,12 @@ namespace :benchmark do
25
25
  def em_client_em_server(number_tests, test_length, global_bench = nil)
26
26
  EM.stop if EM.reactor_running?
27
27
 
28
- EventMachine.fiber_run do
28
+ EventMachine.fiber_run do
29
29
  StubServer.new do |server|
30
- client = ::Test::ResourceService.client(:async => false)
30
+ client = ::Test::ResourceService.client
31
31
 
32
32
  benchmark_wrapper(global_bench) do |bench|
33
- bench.report("ES / EC") do
33
+ bench.report("ES / EC") do
34
34
  (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
35
35
  end
36
36
  end
@@ -44,11 +44,11 @@ namespace :benchmark do
44
44
  EM.stop if EM.reactor_running?
45
45
 
46
46
  EventMachine.fiber_run do
47
- StubServer.new(:server => Protobuf::Rpc::Socket::Server, :port => 9399) do |server|
48
- client = ::Test::ResourceService.client(:async => false, :port => 9399)
47
+ StubServer.new(:server => Protobuf::Rpc::Socket::Server, :port => 9399) do |server|
48
+ client = ::Test::ResourceService.client(:port => 9399)
49
49
 
50
50
  benchmark_wrapper(global_bench) do |bench|
51
- bench.report("SS / EC") do
51
+ bench.report("SS / EC") do
52
52
  (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
53
53
  end
54
54
  end
@@ -63,11 +63,11 @@ namespace :benchmark do
63
63
  ::Protobuf::Rpc::Connector.connector_for_client(true)
64
64
  EM.stop if EM.reactor_running?
65
65
 
66
- StubServer.new(:server => Protobuf::Rpc::Socket::Server, :port => 9399) do |server|
67
- client = ::Test::ResourceService.client(:async => false, :port => 9399)
66
+ StubServer.new(:server => Protobuf::Rpc::Socket::Server, :port => 9399) do |server|
67
+ client = ::Test::ResourceService.client(:port => 9399)
68
68
 
69
69
  benchmark_wrapper(global_bench) do |bench|
70
- bench.report("SS / SC") do
70
+ bench.report("SS / SC") do
71
71
  (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
72
72
  end
73
73
  end
@@ -81,11 +81,11 @@ namespace :benchmark do
81
81
  em_thread = Thread.new { EM.run }
82
82
  Thread.pass until EM.reactor_running?
83
83
 
84
- StubServer.new(:port => 9399) do |server|
85
- client = ::Test::ResourceService.client(:async => false, :port => 9399)
84
+ StubServer.new(:port => 9399) do |server|
85
+ client = ::Test::ResourceService.client(:port => 9399)
86
86
 
87
87
  benchmark_wrapper(global_bench) do |bench|
88
- bench.report("ES / SC") do
88
+ bench.report("ES / SC") do
89
89
  (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
90
90
  end
91
91
  end
@@ -98,11 +98,11 @@ namespace :benchmark do
98
98
  def zmq_client_zmq_server(number_tests, test_length, global_bench = nil)
99
99
  load "protobuf/zmq.rb"
100
100
  ::Protobuf::Rpc::Connector.connector_for_client(true)
101
- StubServer.new(:port => 9399, :server => Protobuf::Rpc::Zmq::Server) do |server|
102
- client = ::Test::ResourceService.client(:async => false, :port => 9399)
101
+ StubServer.new(:port => 9399, :server => Protobuf::Rpc::Zmq::Server) do |server|
102
+ client = ::Test::ResourceService.client(:port => 9399)
103
103
 
104
104
  benchmark_wrapper(global_bench) do |bench|
105
- bench.report("ZS / ZC") do
105
+ bench.report("ZS / ZC") do
106
106
  (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
107
107
  end
108
108
  end
@@ -119,7 +119,7 @@ namespace :benchmark do
119
119
  desc "benchmark ZMQ client with ZMQ server and profile"
120
120
  task :zmq_profile, [:number, :length, :profile_output] do |t, args|
121
121
  args.with_defaults(:number => 1000, :length => 100, :profile_output => "/tmp/zmq_profiler_#{Time.now.to_i}")
122
- ::PerfTools::CpuProfiler.start(args[:profile_output]) do
122
+ ::PerfTools::CpuProfiler.start(args[:profile_output]) do
123
123
  zmq_client_zmq_server(args[:number], args[:length])
124
124
  end
125
125
 
@@ -130,7 +130,7 @@ namespace :benchmark do
130
130
  task :profile_protobuf_new, [:number, :profile_output] do |t, args|
131
131
  args.with_defaults(:number => 1000, :profile_output => "/tmp/profiler_new_#{Time.now.to_i}")
132
132
  create_params = { :name => "The name that we set", :date_created => Time.now.to_i, :status => 2 }
133
- ::PerfTools::CpuProfiler.start(args[:profile_output]) do
133
+ ::PerfTools::CpuProfiler.start(args[:profile_output]) do
134
134
  args[:number].to_i.times { Test::Resource.new(create_params) }
135
135
  end
136
136
 
@@ -5,14 +5,13 @@ describe 'Functional EventMachine Client' do
5
5
  before(:each) do
6
6
  load 'protobuf/evented.rb'
7
7
  ::Protobuf::Rpc::Connector.connector_for_client(true)
8
- ::Test::ResourceService.configure(::Test::ResourceService::DEFAULT_LOCATION)
9
8
  end
10
9
 
11
10
  it 'runs fine when required fields are set' do
12
11
  expect {
13
12
  EventMachine.fiber_run do
14
13
  StubServer.new do |server|
15
- client = ::Test::ResourceService.client(:async => false, :timeout => 5)
14
+ client = ::Test::ResourceService.client(:timeout => 5)
16
15
 
17
16
  client.find(:name => 'Test Name', :active => true) do |c|
18
17
  c.on_success do |succ|
@@ -35,7 +34,7 @@ describe 'Functional EventMachine Client' do
35
34
  EventMachine.fiber_run do
36
35
  StubServer.new do |server|
37
36
  request = ::Test::ResourceFindRequest.new(:active => true)
38
- client = ::Test::ResourceService.client(:async => false)
37
+ client = ::Test::ResourceService.client
39
38
 
40
39
  client.find(request) do |c|
41
40
  c.on_success { raise "shouldn't pass"}
@@ -52,7 +51,7 @@ describe 'Functional EventMachine Client' do
52
51
  EventMachine.fiber_run do
53
52
  StubServer.new do |server|
54
53
  request = ::Test::Resource.new(:name => 'Test Name')
55
- client = ::Test::ResourceService.client(:async => false)
54
+ client = ::Test::ResourceService.client
56
55
 
57
56
  client.find(request) do |c|
58
57
  c.on_success { raise "shouldn't pass"}
@@ -18,7 +18,7 @@ describe 'Functional Socket Client' do
18
18
 
19
19
  it 'runs fine when required fields are set' do
20
20
  expect {
21
- client = ::Test::ResourceService.client(:async => false)
21
+ client = ::Test::ResourceService.client
22
22
 
23
23
  client.find(:name => 'Test Name', :active => true) do |c|
24
24
  c.on_success do |succ|
@@ -36,7 +36,7 @@ describe 'Functional Socket Client' do
36
36
  it 'calls the on_failure callback when a message is malformed' do
37
37
  error = nil
38
38
  request = ::Test::ResourceFindRequest.new(:active => true)
39
- client = ::Test::ResourceService.client(:async => false)
39
+ client = ::Test::ResourceService.client
40
40
 
41
41
  client.find(request) do |c|
42
42
  c.on_success { raise "shouldn't pass"}
@@ -48,7 +48,7 @@ describe 'Functional Socket Client' do
48
48
  it 'calls the on_failure callback when the request type is wrong' do
49
49
  error = nil
50
50
  request = ::Test::Resource.new(:name => 'Test Name')
51
- client = ::Test::ResourceService.client(:async => false)
51
+ client = ::Test::ResourceService.client
52
52
 
53
53
  client.find(request) do |c|
54
54
  c.on_success { raise "shouldn't pass"}
@@ -18,7 +18,7 @@ describe 'Functional ZMQ Client' do
18
18
 
19
19
  it 'runs fine when required fields are set' do
20
20
  expect {
21
- client = ::Test::ResourceService.client(:async => false)
21
+ client = ::Test::ResourceService.client
22
22
 
23
23
  client.find(:name => 'Test Name', :active => true) do |c|
24
24
  c.on_success do |succ|
@@ -36,7 +36,7 @@ describe 'Functional ZMQ Client' do
36
36
  it 'calls the on_failure callback when a message is malformed' do
37
37
  error = nil
38
38
  request = ::Test::ResourceFindRequest.new(:active => true)
39
- client = ::Test::ResourceService.client(:async => false)
39
+ client = ::Test::ResourceService.client
40
40
 
41
41
  client.find(request) do |c|
42
42
  c.on_success { raise "shouldn't pass"}
@@ -48,7 +48,7 @@ describe 'Functional ZMQ Client' do
48
48
  it 'calls the on_failure callback when the request type is wrong' do
49
49
  error = nil
50
50
  request = ::Test::Resource.new(:name => 'Test Name')
51
- client = ::Test::ResourceService.client(:async => false)
51
+ client = ::Test::ResourceService.client
52
52
 
53
53
  client.find(request) do |c|
54
54
  c.on_success { raise "shouldn't pass"}
@@ -1,40 +1,40 @@
1
- require 'protobuf/common/logger'
1
+ require 'protobuf/logger'
2
2
  require 'stringio'
3
3
 
4
4
  describe Protobuf::Logger do
5
-
5
+
6
6
  subject { Protobuf::Logger }
7
-
7
+
8
8
  before(:each) do
9
9
  Protobuf::Logger.reset_device!
10
10
  Protobuf::Logger.file = '/dev/null'
11
11
  Protobuf::Logger.level = ::Logger::INFO
12
12
  end
13
-
13
+
14
14
  describe '.instance' do
15
-
15
+
16
16
  it 'doesn\'t create a logger if the file was not set' do
17
17
  subject.file = nil
18
18
  subject.instance.should be_nil
19
19
  end
20
-
20
+
21
21
  it 'doesn\'t create a logger if the level was not set' do
22
22
  subject.level = nil
23
23
  subject.instance.should be_nil
24
24
  end
25
-
25
+
26
26
  it 'gets a new instance of the logger when file and level are set' do
27
27
  subject.file.should_not be_nil
28
28
  subject.level.should_not be_nil
29
29
  subject.instance.should_not be_nil
30
30
  end
31
-
31
+
32
32
  it 'keeps the same object from multiple calls to instance' do
33
33
  subject.instance === subject.instance
34
34
  end
35
-
35
+
36
36
  end
37
-
37
+
38
38
  describe '.configure' do
39
39
  before(:each) { subject.reset_device! }
40
40
  it 'sets the file and level in one call' do
@@ -46,11 +46,11 @@ describe Protobuf::Logger do
46
46
  subject.level.should == ::Logger::WARN
47
47
  subject.instance.level.should == ::Logger::WARN
48
48
  end
49
-
49
+
50
50
  end
51
-
51
+
52
52
  describe '.reset_device!' do
53
-
53
+
54
54
  it 'resets the logger instance, file, and level' do
55
55
  subject.instance.should be
56
56
  subject.file.should be
@@ -60,11 +60,11 @@ describe Protobuf::Logger do
60
60
  subject.file.should_not be
61
61
  subject.level.should_not be
62
62
  end
63
-
63
+
64
64
  end
65
-
65
+
66
66
  context 'when logging' do
67
-
67
+
68
68
  it 'doesn\'t raise errors when log instance is nil' do
69
69
  subject.reset_device!
70
70
  subject.instance.should be_nil
@@ -78,44 +78,54 @@ describe Protobuf::Logger do
78
78
  subject.log 'No errors here'
79
79
  }.to_not raise_error
80
80
  end
81
-
81
+
82
82
  it 'logs correctly when instance is valid' do
83
83
  subject.instance.should_not be_nil
84
84
  subject.instance.should_receive(:info).with('Should log great')
85
85
  subject.info 'Should log great'
86
86
  end
87
-
87
+
88
88
  end
89
-
89
+
90
90
  describe Protobuf::Logger::LogMethods do
91
-
91
+
92
92
  context 'when included in another class' do
93
-
93
+
94
94
  before(:all) do
95
95
  class MyTestClass
96
96
  include Protobuf::Logger::LogMethods
97
97
  end
98
98
  end
99
-
99
+
100
100
  subject { MyTestClass.new }
101
-
102
- it 'responds to all logger methods' do
103
- subject.should respond_to :log_debug
104
- subject.should respond_to :log_info
105
- subject.should respond_to :log_warn
106
- subject.should respond_to :log_error
107
- subject.should respond_to :log_fatal
108
- subject.should respond_to :log_add
109
- subject.should respond_to :log_log
101
+
102
+ it { should respond_to(:log_debug) }
103
+ it { should respond_to(:log_info) }
104
+ it { should respond_to(:log_warn) }
105
+ it { should respond_to(:log_error) }
106
+ it { should respond_to(:log_fatal) }
107
+ it { should respond_to(:log_add) }
108
+ it { should respond_to(:log_log) }
109
+
110
+ context '#log_exception' do
111
+ it 'logs the exception message as an error and backtrace as debug' do
112
+ subject.should_receive(:log_error).twice
113
+ subject.should_receive(:log_debug)
114
+ subject.log_exception(RuntimeError.new('this is an exception'))
115
+ end
110
116
  end
111
-
117
+
118
+ its(:log_signature) { should eq "[MyTestClass]" }
119
+ describe '#sign_message' do
120
+ specify { subject.sign_message("this is a test").should eq "[MyTestClass] this is a test" }
121
+ specify { subject.class.sign_message("this is a test").should eq "[MyTestClass] this is a test" }
122
+ end
123
+
112
124
  it 'passes all embedded log calls to Logger instance' do
113
- Protobuf::Logger.instance.should_receive(:debug).with('log this')
125
+ Protobuf::Logger.instance.should_receive(:debug).with('[MyTestClass] log this')
114
126
  subject.log_debug('log this')
115
127
  end
116
-
128
+
117
129
  end
118
-
119
130
  end
120
-
121
131
  end