protobuf 2.0.0.rc3 → 2.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
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