protobuf 2.8.13 → 3.0.0.rc1

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 (116) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +84 -5
  3. data/CONTRIBUTING.md +3 -3
  4. data/Rakefile +46 -7
  5. data/lib/protobuf/cli.rb +2 -20
  6. data/lib/protobuf/decoder.rb +74 -0
  7. data/lib/protobuf/deprecator.rb +42 -0
  8. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +17 -16
  9. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +86 -85
  10. data/lib/protobuf/encoder.rb +62 -0
  11. data/lib/protobuf/enum.rb +298 -37
  12. data/lib/protobuf/field/base_field.rb +41 -27
  13. data/lib/protobuf/field/bool_field.rb +22 -4
  14. data/lib/protobuf/field/bytes_field.rb +36 -15
  15. data/lib/protobuf/field/double_field.rb +10 -3
  16. data/lib/protobuf/field/enum_field.rb +21 -18
  17. data/lib/protobuf/field/field_array.rb +26 -16
  18. data/lib/protobuf/field/fixed32_field.rb +10 -4
  19. data/lib/protobuf/field/fixed64_field.rb +10 -3
  20. data/lib/protobuf/field/float_field.rb +18 -5
  21. data/lib/protobuf/field/int32_field.rb +14 -4
  22. data/lib/protobuf/field/int64_field.rb +14 -4
  23. data/lib/protobuf/field/integer_field.rb +9 -4
  24. data/lib/protobuf/field/message_field.rb +16 -7
  25. data/lib/protobuf/field/sfixed32_field.rb +10 -3
  26. data/lib/protobuf/field/sfixed64_field.rb +12 -7
  27. data/lib/protobuf/field/signed_integer_field.rb +7 -0
  28. data/lib/protobuf/field/sint32_field.rb +14 -4
  29. data/lib/protobuf/field/sint64_field.rb +14 -4
  30. data/lib/protobuf/field/string_field.rb +11 -1
  31. data/lib/protobuf/field/uint32_field.rb +14 -4
  32. data/lib/protobuf/field/uint64_field.rb +14 -4
  33. data/lib/protobuf/field/varint_field.rb +11 -9
  34. data/lib/protobuf/field.rb +42 -25
  35. data/lib/protobuf/generators/enum_generator.rb +12 -1
  36. data/lib/protobuf/generators/field_generator.rb +1 -1
  37. data/lib/protobuf/lifecycle.rb +3 -4
  38. data/lib/protobuf/message/fields.rb +122 -0
  39. data/lib/protobuf/message/serialization.rb +84 -0
  40. data/lib/protobuf/message.rb +21 -221
  41. data/lib/protobuf/optionable.rb +23 -0
  42. data/lib/protobuf/rpc/client.rb +2 -4
  43. data/lib/protobuf/rpc/connector.rb +0 -2
  44. data/lib/protobuf/rpc/connectors/common.rb +2 -2
  45. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +14 -16
  46. data/lib/protobuf/rpc/env.rb +58 -0
  47. data/lib/protobuf/rpc/error.rb +8 -5
  48. data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
  49. data/lib/protobuf/rpc/middleware/logger.rb +91 -0
  50. data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
  51. data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
  52. data/lib/protobuf/rpc/middleware/runner.rb +18 -0
  53. data/lib/protobuf/rpc/middleware.rb +25 -0
  54. data/lib/protobuf/rpc/rpc.pb.rb +15 -16
  55. data/lib/protobuf/rpc/server.rb +14 -64
  56. data/lib/protobuf/rpc/servers/socket/server.rb +0 -2
  57. data/lib/protobuf/rpc/servers/socket/worker.rb +11 -15
  58. data/lib/protobuf/rpc/servers/zmq/util.rb +4 -1
  59. data/lib/protobuf/rpc/servers/zmq/worker.rb +5 -13
  60. data/lib/protobuf/rpc/servers/zmq_runner.rb +1 -1
  61. data/lib/protobuf/rpc/service.rb +38 -72
  62. data/lib/protobuf/rpc/service_dispatcher.rb +20 -108
  63. data/lib/protobuf/version.rb +1 -2
  64. data/lib/protobuf.rb +5 -13
  65. data/protobuf.gemspec +5 -5
  66. data/spec/benchmark/tasks.rb +2 -77
  67. data/spec/functional/zmq_server_spec.rb +13 -21
  68. data/spec/lib/protobuf/cli_spec.rb +5 -43
  69. data/spec/lib/protobuf/enum_spec.rb +194 -61
  70. data/spec/lib/protobuf/field_spec.rb +194 -0
  71. data/spec/lib/protobuf/generators/enum_generator_spec.rb +24 -1
  72. data/spec/lib/protobuf/generators/field_generator_spec.rb +6 -6
  73. data/spec/lib/protobuf/message_spec.rb +52 -70
  74. data/spec/lib/protobuf/optionable_spec.rb +46 -0
  75. data/spec/lib/protobuf/rpc/client_spec.rb +1 -93
  76. data/spec/lib/protobuf/rpc/connector_spec.rb +1 -7
  77. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +8 -0
  78. data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
  79. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
  80. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
  81. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
  82. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +0 -6
  83. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +10 -0
  84. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +30 -105
  85. data/spec/lib/protobuf/rpc/service_filters_spec.rb +4 -4
  86. data/spec/lib/protobuf/rpc/service_spec.rb +20 -24
  87. data/spec/lib/protobuf_spec.rb +3 -3
  88. data/spec/spec_helper.rb +5 -4
  89. data/spec/support/packed_field.rb +15 -14
  90. data/spec/support/server.rb +4 -21
  91. data/spec/support/test/defaults.pb.rb +4 -4
  92. data/spec/support/test/enum.pb.rb +13 -1
  93. data/spec/support/test/enum.proto +15 -0
  94. data/spec/support/test/extended.pb.rb +1 -1
  95. data/spec/support/test/google_unittest.pb.rb +239 -241
  96. data/spec/support/test/google_unittest_import.pb.rb +2 -2
  97. data/spec/support/test/multi_field_extensions.pb.rb +2 -2
  98. data/spec/support/test/resource.pb.rb +19 -18
  99. data/spec/support/test/resource.proto +1 -0
  100. data/spec/support/test/resource_service.rb +5 -0
  101. metadata +78 -57
  102. data/bin/rprotoc +0 -8
  103. data/lib/protobuf/enum_value.rb +0 -85
  104. data/lib/protobuf/evented.rb +0 -37
  105. data/lib/protobuf/ext/eventmachine.rb +0 -14
  106. data/lib/protobuf/field/extension_fields.rb +0 -32
  107. data/lib/protobuf/message/decoder.rb +0 -72
  108. data/lib/protobuf/message/message.rb +0 -1
  109. data/lib/protobuf/rpc/connectors/em_client.rb +0 -84
  110. data/lib/protobuf/rpc/connectors/eventmachine.rb +0 -87
  111. data/lib/protobuf/rpc/servers/evented/server.rb +0 -36
  112. data/lib/protobuf/rpc/servers/evented_runner.rb +0 -31
  113. data/spec/functional/embedded_service_spec.rb +0 -7
  114. data/spec/functional/evented_server_spec.rb +0 -64
  115. data/spec/lib/protobuf/enum_value_spec.rb +0 -29
  116. data/spec/lib/protobuf/rpc/servers/evented_server_spec.rb +0 -19
@@ -1,4 +1,5 @@
1
1
  require 'benchmark'
2
+ require 'protobuf/socket'
2
3
  require 'support/all'
3
4
  require 'support/test/resource_service'
4
5
 
@@ -28,43 +29,8 @@ namespace :benchmark do
28
29
  end
29
30
  end
30
31
 
31
- def em_client_em_server(number_tests, test_length, global_bench = nil)
32
- EM.stop if EM.reactor_running?
33
-
34
- EventMachine.fiber_run do
35
- StubServer.new(:server => Protobuf::Rpc::Evented::Server) do |server|
36
- benchmark_wrapper(global_bench) do |bench|
37
- bench.report("ES / EC") do
38
- (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
39
- end
40
- end
41
- end
42
-
43
- EM.stop
44
- end
45
- end
46
-
47
- def em_client_sock_server(number_tests, test_length, global_bench = nil)
48
- EM.stop if EM.reactor_running?
49
-
50
- EventMachine.fiber_run do
51
- StubServer.new(:server => Protobuf::Rpc::Socket::Server, :port => 9399) do |server|
52
- client = ::Test::ResourceService.client(:port => 9399)
53
-
54
- benchmark_wrapper(global_bench) do |bench|
55
- bench.report("SS / EC") do
56
- (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
57
- end
58
- end
59
- end
60
-
61
- EM.stop
62
- end
63
- end
64
-
65
32
  def sock_client_sock_server(number_tests, test_length, global_bench = nil)
66
33
  load "protobuf/socket.rb"
67
- EM.stop if EM.reactor_running?
68
34
 
69
35
  StubServer.new(:server => Protobuf::Rpc::Socket::Server, :port => 9399) do |server|
70
36
  client = ::Test::ResourceService.client(:port => 9399)
@@ -77,26 +43,6 @@ namespace :benchmark do
77
43
  end
78
44
  end
79
45
 
80
- def sock_client_em_server(number_tests, test_length, global_bench = nil)
81
- load "protobuf/socket.rb"
82
- EM.stop if EM.reactor_running?
83
- em_thread = Thread.new { EM.run }
84
- Thread.pass until EM.reactor_running?
85
-
86
- StubServer.new(:port => 9399) do |server|
87
- client = ::Test::ResourceService.client(:port => 9399)
88
-
89
- benchmark_wrapper(global_bench) do |bench|
90
- bench.report("ES / SC") do
91
- (1..number_tests.to_i).each { client.find(:name => "Test Name" * test_length.to_i, :active => true) }
92
- end
93
- end
94
- end
95
-
96
- EM.stop
97
- Thread.kill(em_thread) if em_thread
98
- end
99
-
100
46
  def zmq_client_zmq_server(number_tests, test_length, global_bench = nil)
101
47
  load "protobuf/zmq.rb"
102
48
  StubServer.new(:port => 9399, :server => Protobuf::Rpc::Zmq::Server) do |server|
@@ -149,40 +95,19 @@ namespace :benchmark do
149
95
  puts args[:profile_output]
150
96
  end
151
97
 
152
- desc "benchmark EventMachine client with EventMachine server"
153
- task :em_client_em_server, [:number, :length] do |t, args|
154
- args.with_defaults(:number => 1000, :length => 100)
155
- em_client_em_server(args[:number], args[:length])
156
- end
157
-
158
- desc "benchmark EventMachine client with Socket server"
159
- task :em_client_sock_server, [:number, :length] do |t, args|
160
- args.with_defaults(:number => 1000, :length => 100)
161
- em_client_sock_server(args[:number], args[:length])
162
- end
163
-
164
98
  desc "benchmark Socket client with Socket server"
165
99
  task :sock_client_sock_server, [:number, :length] do |t, args|
166
100
  args.with_defaults(:number => 1000, :length => 100)
167
101
  sock_client_sock_server(args[:number], args[:length])
168
102
  end
169
103
 
170
- desc "benchmark Socket client with EventMachine server"
171
- task :sock_client_em_server, [:number, :length] do |t, args|
172
- args.with_defaults(:number => 1000, :length => 100)
173
- sock_client_em_server(args[:number], args[:length])
174
- end
175
-
176
104
  desc "benchmark server performance"
177
105
  task :servers, [:number, :length] do |t, args|
178
106
  args.with_defaults(:number => 1000, :length => 100)
179
107
 
180
108
  Benchmark.bm(10) do |bench|
181
- # zmq_client_zmq_server(args[:number], args[:length], bench)
182
- # em_client_em_server(args[:number], args[:length], bench)
183
- # em_client_sock_server(args[:number], args[:length], bench)
109
+ zmq_client_zmq_server(args[:number], args[:length], bench)
184
110
  sock_client_sock_server(args[:number], args[:length], bench)
185
- # sock_client_em_server(args[:number], args[:length], bench)
186
111
  end
187
112
  end
188
113
  end
@@ -4,29 +4,21 @@ require 'spec/support/test/resource_service'
4
4
  require 'protobuf/rpc/service_directory'
5
5
 
6
6
  describe 'Functional ZMQ Client' do
7
- let(:options) {{
8
- :host => "127.0.0.1",
9
- :port => 9399,
10
- :worker_port => 9400,
11
- :backlog => 100,
12
- :threshold => 100,
13
- :threads => 5
14
- }}
15
-
16
- let(:server) { ::Protobuf::Rpc::Zmq::Server.new(options) }
17
- let!(:server_thread) { Thread.new(server) { |server| server.run } }
18
-
19
7
  before(:all) do
20
8
  load "protobuf/zmq.rb"
9
+ @runner = ::Protobuf::Rpc::ZmqRunner.new({ :host => "127.0.0.1",
10
+ :port => 9399,
11
+ :worker_port => 9408,
12
+ :backlog => 100,
13
+ :threshold => 100,
14
+ :threads => 5 })
15
+ @server_thread = Thread.new(@runner) { |runner| runner.run }
16
+ Thread.pass until @runner.running?
21
17
  end
22
18
 
23
- before do
24
- Thread.pass until server.running?
25
- end
26
-
27
- after do
28
- server.stop
29
- server_thread.join
19
+ after(:all) do
20
+ @runner.stop
21
+ @server_thread.join
30
22
  end
31
23
 
32
24
  it 'runs fine when required fields are set' do
@@ -47,8 +39,8 @@ describe 'Functional ZMQ Client' do
47
39
  end
48
40
 
49
41
  it 'runs under heavy load' do
50
- 100.times do |x|
51
- 50.times.map do |y|
42
+ 10.times do |x|
43
+ 5.times.map do |y|
52
44
  Thread.new do
53
45
  client = ::Test::ResourceService.client
54
46
 
@@ -7,28 +7,21 @@ describe ::Protobuf::CLI do
7
7
  File.expand_path('../../../support/test_app_file.rb', __FILE__)
8
8
  end
9
9
 
10
- let(:sock_runner) {
10
+ let(:sock_runner) {
11
11
  runner = double("SocketRunner", :register_signals => nil)
12
12
  runner.stub(:run) { ::ActiveSupport::Notifications.publish( "after_server_bind" ) }
13
13
  runner
14
14
  }
15
15
 
16
- let(:zmq_runner) {
16
+ let(:zmq_runner) {
17
17
  runner = double "ZmqRunner", register_signals: nil
18
18
  runner.stub(:run) { ::ActiveSupport::Notifications.publish( "after_server_bind" ) }
19
19
  runner
20
20
  }
21
21
 
22
- let(:evented_runner) {
23
- runner = double "EventedRunner", register_signals: nil
24
- runner.stub(:run) { ::Protobuf::Lifecycle.trigger( "after_server_bind" ) }
25
- runner
26
- }
27
-
28
22
  before(:each) do
29
23
  ::Protobuf::Rpc::SocketRunner.stub(:new) { sock_runner }
30
24
  ::Protobuf::Rpc::ZmqRunner.stub(:new) { zmq_runner }
31
- ::Protobuf::Rpc::EventedRunner.stub(:new) { evented_runner }
32
25
  end
33
26
 
34
27
  describe '#start' do
@@ -176,7 +169,6 @@ describe ::Protobuf::CLI do
176
169
  let(:runner) { ::Protobuf::Rpc::SocketRunner }
177
170
 
178
171
  before do
179
- ::Protobuf::Rpc::EventedRunner.should_not_receive(:new)
180
172
  ::Protobuf::Rpc::ZmqRunner.should_not_receive(:new)
181
173
  end
182
174
 
@@ -185,7 +177,7 @@ describe ::Protobuf::CLI do
185
177
  described_class.start(args)
186
178
  end
187
179
 
188
- it 'is activated by PB_SERVER_TYPE=Socket ENV variable' do
180
+ it 'is activated by PB_SERVER_TYPE=Socket ENV variable' do
189
181
  ENV['PB_SERVER_TYPE'] = "Socket"
190
182
  runner.should_receive(:new).and_return(sock_runner)
191
183
  described_class.start(args)
@@ -198,40 +190,12 @@ describe ::Protobuf::CLI do
198
190
  end
199
191
  end
200
192
 
201
- context 'evented' do
202
- let(:test_args) { [ '--evented' ] }
203
- let(:runner) { ::Protobuf::Rpc::EventedRunner }
204
-
205
- before do
206
- ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
207
- ::Protobuf::Rpc::ZmqRunner.should_not_receive(:new)
208
- end
209
-
210
- it 'is activated by the --evented switch' do
211
- runner.should_receive(:new).and_return(evented_runner)
212
- described_class.start(args)
213
- end
214
-
215
- it 'is activated by PB_SERVER_TYPE=Evented ENV variable' do
216
- ENV['PB_SERVER_TYPE'] = "Evented"
217
- runner.should_receive(:new).and_return(evented_runner)
218
- described_class.start(args)
219
- ENV.delete('PB_SERVER_TYPE')
220
- end
221
-
222
- it 'configures the connector type to be evented' do
223
- load "protobuf/evented.rb"
224
- ::Protobuf.connector_type.should == :evented
225
- end
226
- end
227
-
228
193
  context 'zmq workers only' do
229
194
  let(:test_args) { [ '--workers_only', '--zmq' ] }
230
195
  let(:runner) { ::Protobuf::Rpc::ZmqRunner }
231
196
 
232
197
  before do
233
198
  ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
234
- ::Protobuf::Rpc::EventedRunner.should_not_receive(:new)
235
199
  end
236
200
 
237
201
  it 'is activated by the --workers_only switch' do
@@ -242,7 +206,7 @@ describe ::Protobuf::CLI do
242
206
  described_class.start(args)
243
207
  end
244
208
 
245
- it 'is activated by PB_WORKERS_ONLY=1 ENV variable' do
209
+ it 'is activated by PB_WORKERS_ONLY=1 ENV variable' do
246
210
  ENV['PB_WORKERS_ONLY'] = "1"
247
211
  runner.should_receive(:new) do |options|
248
212
  options[:workers_only].should be_true
@@ -259,7 +223,6 @@ describe ::Protobuf::CLI do
259
223
 
260
224
  before do
261
225
  ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
262
- ::Protobuf::Rpc::EventedRunner.should_not_receive(:new)
263
226
  end
264
227
 
265
228
  it 'is activated by the --worker_port switch' do
@@ -277,7 +240,6 @@ describe ::Protobuf::CLI do
277
240
 
278
241
  before do
279
242
  ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
280
- ::Protobuf::Rpc::EventedRunner.should_not_receive(:new)
281
243
  end
282
244
 
283
245
  it 'is activated by the --zmq switch' do
@@ -285,7 +247,7 @@ describe ::Protobuf::CLI do
285
247
  described_class.start(args)
286
248
  end
287
249
 
288
- it 'is activated by PB_SERVER_TYPE=Zmq ENV variable' do
250
+ it 'is activated by PB_SERVER_TYPE=Zmq ENV variable' do
289
251
  ENV['PB_SERVER_TYPE'] = "Zmq"
290
252
  runner.should_receive(:new)
291
253
  described_class.start(args)
@@ -1,98 +1,231 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Protobuf::Enum do
4
- let(:name) { :THREE }
5
- let(:tag) { 3 }
6
4
 
7
- before(:all) do
8
- Test::EnumTestType.define(:MINUS_ONE, -1)
9
- Test::EnumTestType.define(:THREE, 3)
10
- end
5
+ describe 'class dsl' do
6
+ let(:name) { :THREE }
7
+ let(:tag) { 3 }
11
8
 
12
- describe '.define' do
13
- it 'defines a constant enum value on the parent class' do
14
- Test::EnumTestType.constants.should include(name)
15
- Test::EnumTestType::THREE.should be_a(Protobuf::EnumValue)
9
+ before(:all) do
10
+ Test::EnumTestType.define(:MINUS_ONE, -1)
11
+ Test::EnumTestType.define(:THREE, 3)
16
12
  end
17
- end
18
13
 
19
- describe '.fetch' do
20
- context 'when value is an EnumValue' do
21
- it 'responds with that object' do
22
- Test::EnumTestType.fetch(Test::EnumTestType::THREE).name.should eq Test::EnumTestType::THREE.name
14
+ before(:all) do
15
+ EnumAliasTest = ::Class.new(::Protobuf::Enum) do
16
+ set_option :allow_alias
17
+ define :FOO, 1
18
+ define :BAR, 1
19
+ define :BAZ, 2
23
20
  end
24
21
  end
25
22
 
26
- context 'when value can be coerced to a symbol' do
27
- it 'fetches based on the symbol name value' do
28
- Test::EnumTestType.fetch("ONE").should eq Test::EnumTestType::ONE
29
- Test::EnumTestType.fetch(:ONE).should eq Test::EnumTestType::ONE
23
+ describe '.aliases_allowed?' do
24
+ it 'is false when the option is not set' do
25
+ expect(Test::EnumTestType.aliases_allowed?).to be_false
30
26
  end
31
27
  end
32
28
 
33
- context 'when value can be coerced to an integer' do
34
- it 'fetches based on the integer tag value' do
35
- Test::EnumTestType.fetch(3.0).should eq Test::EnumTestType::THREE
36
- Test::EnumTestType.fetch(3).should eq Test::EnumTestType::THREE
29
+ describe '.define' do
30
+ it 'defines a constant enum on the parent class' do
31
+ expect(Test::EnumTestType.constants).to include(name)
32
+ expect(Test::EnumTestType::THREE).to be_a(Protobuf::Enum)
33
+ end
34
+
35
+ context 'when enum allows aliases' do
36
+ before(:all) do
37
+ DefineEnumAlias = ::Class.new(::Protobuf::Enum) do
38
+ set_option :allow_alias
39
+ end
40
+ end
41
+
42
+ it 'allows defining enums with the same tag number' do
43
+ expect {
44
+ DefineEnumAlias.define(:FOO, 1)
45
+ DefineEnumAlias.define(:BAR, 1)
46
+ }.not_to raise_error
47
+ end
37
48
  end
38
49
  end
39
50
 
40
- context 'when value is not an applicable type' do
41
- it 'returns a nil' do
42
- Test::EnumTestType.fetch(Test::Resource.new).should be_nil
43
- Test::EnumTestType.fetch(nil).should be_nil
44
- Test::EnumTestType.fetch(false).should be_nil
51
+ describe '.enums' do
52
+ it 'provides an array of defined Enums' do
53
+ expect(Test::EnumTestType.enums).to eq([
54
+ Test::EnumTestType::ONE,
55
+ Test::EnumTestType::TWO,
56
+ Test::EnumTestType::MINUS_ONE,
57
+ Test::EnumTestType::THREE
58
+ ])
59
+ end
60
+
61
+ context 'when enum allows aliases' do
62
+ it 'treats aliased enums as valid' do
63
+ expect(EnumAliasTest.enums).to eq([
64
+ EnumAliasTest::FOO,
65
+ EnumAliasTest::BAR,
66
+ EnumAliasTest::BAZ
67
+ ])
68
+ end
45
69
  end
46
70
  end
47
- end
48
71
 
49
- describe '.enum_by_value' do
50
- it 'gets the EnumValue corresponding to the given value (tag)' do
51
- Test::EnumTestType.enum_by_value(tag).should eq Test::EnumTestType.const_get(name)
72
+
73
+ describe '.enums_for_tag' do
74
+ it 'returns an array of Enums for the given tag, if any' do
75
+ expect(EnumAliasTest.enums_for_tag(1)).to eq([ EnumAliasTest::FOO, EnumAliasTest::BAR ])
76
+ expect(EnumAliasTest.enums_for_tag(2)).to eq([ EnumAliasTest::BAZ ])
77
+ expect(EnumAliasTest.enums_for_tag(3)).to eq([])
78
+ end
52
79
  end
53
- end
54
80
 
55
- describe '.name_by_value' do
56
- it 'get the name by value of the enum given the enum' do
57
- Test::EnumTestType.name_by_value(::Test::EnumTestType::THREE).should eq name
81
+ describe '.fetch' do
82
+ context 'when candidate is an Enum' do
83
+ it 'responds with the Enum' do
84
+ expect(Test::EnumTestType.fetch(Test::EnumTestType::THREE)).to eq(Test::EnumTestType::THREE)
85
+ end
86
+ end
87
+
88
+ context 'when candidate can be coerced to a symbol' do
89
+ it 'fetches based on the symbol name' do
90
+ expect(Test::EnumTestType.fetch("ONE")).to eq(Test::EnumTestType::ONE)
91
+ expect(Test::EnumTestType.fetch(:ONE)).to eq(Test::EnumTestType::ONE)
92
+ end
93
+ end
94
+
95
+ context 'when candidate can be coerced to an integer' do
96
+ it 'fetches based on the integer tag' do
97
+ expect(Test::EnumTestType.fetch(3.0)).to eq(Test::EnumTestType::THREE)
98
+ expect(Test::EnumTestType.fetch(3)).to eq(Test::EnumTestType::THREE)
99
+ end
100
+
101
+ context 'when enum allows aliases' do
102
+ it 'fetches the first defined Enum' do
103
+ expect(EnumAliasTest.fetch(1)).to eq(EnumAliasTest::FOO)
104
+ end
105
+ end
106
+ end
107
+
108
+ context 'when candidate is not an applicable type' do
109
+ it 'returns a nil' do
110
+ expect(Test::EnumTestType.fetch(EnumAliasTest::FOO)).to be_nil
111
+ expect(Test::EnumTestType.fetch(Test::Resource.new)).to be_nil
112
+ expect(Test::EnumTestType.fetch(nil)).to be_nil
113
+ expect(Test::EnumTestType.fetch(false)).to be_nil
114
+ expect(Test::EnumTestType.fetch(-10)).to be_nil
115
+ end
116
+ end
58
117
  end
59
118
 
60
- it 'gets the name of the enum corresponding to the given value (tag)' do
61
- Test::EnumTestType.name_by_value(tag).should eq name
119
+ describe '.enum_for_tag' do
120
+ it 'gets the Enum corresponding to the given tag' do
121
+ expect(Test::EnumTestType.enum_for_tag(tag)).to eq(Test::EnumTestType.const_get(name))
122
+ expect(Test::EnumTestType.enum_for_tag(-5)).to be_nil
123
+ end
62
124
  end
63
125
 
64
- context 'when given name is nil' do
65
- it 'returns a nil' do
66
- Test::EnumTestType.name_by_value(nil).should be_nil
126
+ describe '.name_for_tag' do
127
+ it 'get the name of the enum given the enum' do
128
+ expect(Test::EnumTestType.name_for_tag(::Test::EnumTestType::THREE)).to eq(name)
129
+ end
130
+
131
+ it 'gets the name of the enum corresponding to the given tag' do
132
+ expect(Test::EnumTestType.name_for_tag(tag)).to eq(name)
133
+ end
134
+
135
+ it 'gets the name when the tag is coercable to an int' do
136
+ expect(Test::EnumTestType.name_for_tag("3")).to eq(name)
137
+ end
138
+
139
+ it 'returns nil when tag does not correspond to a name' do
140
+ expect(Test::EnumTestType.name_for_tag(12345)).to be_nil
141
+ end
142
+
143
+ context 'when given name is nil' do
144
+ it 'returns a nil' do
145
+ expect(Test::EnumTestType.name_for_tag(nil)).to be_nil
146
+ end
147
+ end
148
+
149
+ context 'when enum allows aliases' do
150
+ it 'returns the first defined name for the given tag' do
151
+ expect(EnumAliasTest.name_for_tag(1)).to eq(:FOO)
152
+ end
153
+ end
154
+ end
155
+
156
+ describe '.valid_tag?' do
157
+ context 'when tag is defined' do
158
+ specify { expect(Test::EnumTestType.valid_tag?(tag)).to be_true }
159
+ end
160
+
161
+ context 'when tag is not defined' do
162
+ specify { expect(Test::EnumTestType.valid_tag?(300)).to be_false }
163
+ end
164
+
165
+ context 'is true for aliased enums' do
166
+ specify { expect(EnumAliasTest.valid_tag?(1)).to be_true }
67
167
  end
68
168
  end
69
- end
70
169
 
71
- describe '.valid_tag?' do
72
- context 'when tag is defined' do
73
- specify { Test::EnumTestType.valid_tag?(tag).should be_true }
170
+ describe '.enum_for_name' do
171
+ it 'gets the Enum corresponding to the given name' do
172
+ expect(Test::EnumTestType.enum_for_name(name)).to eq(Test::EnumTestType::THREE)
173
+ end
74
174
  end
75
175
 
76
- context 'when tag is not defined' do
77
- specify { Test::EnumTestType.valid_tag?(300).should be_false }
176
+ describe '.values' do
177
+ it 'provides a hash of defined Enums' do
178
+ expect(Test::EnumTestType.values).to eq({
179
+ :MINUS_ONE => Test::EnumTestType::MINUS_ONE,
180
+ :ONE => Test::EnumTestType::ONE,
181
+ :TWO => Test::EnumTestType::TWO,
182
+ :THREE => Test::EnumTestType::THREE
183
+ })
184
+ end
185
+
186
+ it 'contains aliased Enums' do
187
+ expect(EnumAliasTest.values).to eq({
188
+ :FOO => EnumAliasTest::FOO,
189
+ :BAR => EnumAliasTest::BAR,
190
+ :BAZ => EnumAliasTest::BAZ
191
+ })
192
+ end
78
193
  end
79
- end
80
194
 
81
- describe '.value_by_name' do
82
- it 'gets the EnumValue corresponding to the given name' do
83
- Test::EnumTestType.value_by_name(name).should eq Test::EnumTestType::THREE
195
+ describe '.all_tags' do
196
+ it 'provides a unique array of defined tags' do
197
+ expect(Test::EnumTestType.all_tags).to include(1, 2, -1, 3)
198
+ expect(EnumAliasTest.all_tags).to include(1, 2)
199
+ end
84
200
  end
85
201
  end
86
202
 
87
- describe '.values' do
88
- it 'provides a hash of defined EnumValues' do
89
- Test::EnumTestType.values.should eq({
90
- :MINUS_ONE => Test::EnumTestType::MINUS_ONE,
91
- :ONE => Test::EnumTestType::ONE,
92
- :TWO => Test::EnumTestType::TWO,
93
- :THREE => Test::EnumTestType::THREE
94
- })
95
- end
203
+ subject { Test::EnumTestType::ONE }
204
+ its(:class) { should eq(Fixnum) }
205
+ its(:parent_class) { should eq(Test::EnumTestType) }
206
+ its(:name) { should eq(:ONE) }
207
+ its(:tag) { should eq(1) }
208
+ its(:value) { should eq(1) }
209
+ its(:to_hash_value) { should eq(1) }
210
+ its(:to_s) { should eq("1") }
211
+ its(:inspect) { should eq('#<Protobuf::Enum(Test::EnumTestType)::ONE=1>') }
212
+ specify { subject.to_s(:tag).should eq("1") }
213
+ specify { subject.to_s(:name).should eq("ONE") }
214
+
215
+ it "can be used as the index to an array" do
216
+ array = [0, 1, 2, 3]
217
+ array[::Test::EnumTestType::ONE].should eq(1)
218
+ end
219
+
220
+ describe '#try' do
221
+ specify { subject.try(:parent_class).should eq(subject.parent_class) }
222
+ specify { subject.try(:class).should eq(subject.class) }
223
+ specify { subject.try(:name).should eq(subject.name) }
224
+ specify { subject.try(:tag).should eq(subject.tag) }
225
+ specify { subject.try(:value).should eq(subject.value) }
226
+ specify { subject.try(:to_i).should eq(subject.to_i) }
227
+ specify { subject.try(:to_int).should eq(subject.to_int) }
228
+ specify { subject.try { |yielded| yielded.should eq(subject) } }
96
229
  end
97
230
 
98
231
  context 'when coercing from enum' do
@@ -101,6 +234,6 @@ describe Protobuf::Enum do
101
234
  end
102
235
 
103
236
  context 'when coercing from integer' do
104
- specify { 0.should eq(Test::StatusType::PENDING) }
237
+ specify { expect(0).to eq(Test::StatusType::PENDING) }
105
238
  end
106
239
  end