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,267 @@
1
+ require 'spec_helper'
2
+ require 'protobuf/cli'
3
+
4
+ describe ::Protobuf::CLI do
5
+
6
+ let(:app_file) do
7
+ File.expand_path('../../../support/test_app_file.rb', __FILE__)
8
+ end
9
+
10
+ let(:sock_runner) {
11
+ runner = double("SocketRunner", :register_signals => nil)
12
+ runner.stub(:run) { ::ActiveSupport::Notifications.publish( "after_server_bind" ) }
13
+ runner
14
+ }
15
+
16
+ let(:zmq_runner) {
17
+ runner = double "ZmqRunner", register_signals: nil
18
+ runner.stub(:run) { ::ActiveSupport::Notifications.publish( "after_server_bind" ) }
19
+ runner
20
+ }
21
+
22
+ before(:each) do
23
+ ::Protobuf::Rpc::SocketRunner.stub(:new) { sock_runner }
24
+ ::Protobuf::Rpc::ZmqRunner.stub(:new) { zmq_runner }
25
+ end
26
+
27
+ describe '#start' do
28
+ let(:base_args) { [ 'start', app_file ] }
29
+ let(:test_args) { [] }
30
+ let(:args) { base_args + test_args }
31
+
32
+ context 'host option' do
33
+ let(:test_args) { [ '--host=123.123.123.123' ] }
34
+
35
+ it 'sends the host option to the runner' do
36
+ ::Protobuf::Rpc::SocketRunner.should_receive(:new) do |options|
37
+ options[:host].should eq '123.123.123.123'
38
+ end.and_return(sock_runner)
39
+ described_class.start(args)
40
+ end
41
+ end
42
+
43
+ context 'port option' do
44
+ let(:test_args) { [ '--port=12345' ] }
45
+
46
+ it 'sends the port option to the runner' do
47
+ ::Protobuf::Rpc::SocketRunner.should_receive(:new) do |options|
48
+ options[:port].should eq 12345
49
+ end.and_return(sock_runner)
50
+ described_class.start(args)
51
+ end
52
+ end
53
+
54
+ context 'threads option' do
55
+ let(:test_args) { [ '--threads=500' ] }
56
+
57
+ it 'sends the threads option to the runner' do
58
+ ::Protobuf::Rpc::SocketRunner.should_receive(:new) do |options|
59
+ options[:threads].should eq 500
60
+ end.and_return(sock_runner)
61
+ described_class.start(args)
62
+ end
63
+ end
64
+
65
+ context 'backlog option' do
66
+ let(:test_args) { [ '--backlog=500' ] }
67
+
68
+ it 'sends the backlog option to the runner' do
69
+ ::Protobuf::Rpc::SocketRunner.should_receive(:new) do |options|
70
+ options[:backlog].should eq 500
71
+ end.and_return(sock_runner)
72
+ described_class.start(args)
73
+ end
74
+ end
75
+
76
+ context 'threshold option' do
77
+ let(:test_args) { [ '--threshold=500' ] }
78
+
79
+ it 'sends the backlog option to the runner' do
80
+ ::Protobuf::Rpc::SocketRunner.should_receive(:new) do |options|
81
+ options[:threshold].should eq 500
82
+ end.and_return(sock_runner)
83
+ described_class.start(args)
84
+ end
85
+ end
86
+
87
+ context 'log options' do
88
+ let(:test_args) { [ '--log=mylog.log', '--level=0' ] }
89
+
90
+ it 'sends the log file and level options to the runner' do
91
+ ::Protobuf::Logger.should_receive(:configure) do |options|
92
+ options[:file].should eq 'mylog.log'
93
+ options[:level].should eq 0
94
+ end
95
+ described_class.start(args)
96
+ end
97
+ end
98
+
99
+ context 'gc options' do
100
+
101
+ context 'when gc options are not present' do
102
+ let(:test_args) { [] }
103
+
104
+ it 'sets both request and serialization pausing to false' do
105
+ described_class.start(args)
106
+ ::Protobuf.should_not be_gc_pause_server_request
107
+ end
108
+ end
109
+
110
+ unless defined?(JRUBY_VERSION)
111
+ context 'request pausing' do
112
+ let(:test_args) { [ '--gc_pause_request' ] }
113
+
114
+ it 'sets the configuration option to GC pause server request' do
115
+ described_class.start(args)
116
+ ::Protobuf.should be_gc_pause_server_request
117
+ end
118
+ end
119
+ end
120
+ end
121
+
122
+ context 'deprecation options' do
123
+ context 'when not given' do
124
+ let(:test_args) { [] }
125
+
126
+ context 'when no ENV is present and no command line option' do
127
+ before { ENV.delete("PB_IGNORE_DEPRECATIONS") }
128
+
129
+ it 'sets the deprecation warning flag to true' do
130
+ described_class.start(args)
131
+ ::Protobuf.print_deprecation_warnings?.should be_true
132
+ end
133
+ end
134
+
135
+ context 'if ENV["PB_IGNORE_DEPRECATIONS"] is present' do
136
+ before { ENV["PB_IGNORE_DEPRECATIONS"] = "1" }
137
+ after { ENV.delete("PB_IGNORE_DEPRECATIONS") }
138
+
139
+ it 'sets the deprecation warning flag to false ' do
140
+ described_class.start(args)
141
+ ::Protobuf.print_deprecation_warnings?.should be_false
142
+ end
143
+ end
144
+ end
145
+
146
+ context 'when enabled' do
147
+ let(:test_args) { [ '--print_deprecation_warnings' ] }
148
+
149
+ it 'sets the deprecation warning flag to true' do
150
+ described_class.start(args)
151
+ ::Protobuf.print_deprecation_warnings?.should be_true
152
+ end
153
+ end
154
+
155
+ context 'when disabled' do
156
+ let(:test_args) { [ '--no-print_deprecation_warnings' ] }
157
+
158
+ it 'sets the deprecation warning flag to false' do
159
+ described_class.start(args)
160
+ ::Protobuf.print_deprecation_warnings?.should be_false
161
+ end
162
+ end
163
+ end
164
+
165
+ context 'run modes' do
166
+
167
+ context 'socket' do
168
+ let(:test_args) { [ '--socket' ] }
169
+ let(:runner) { ::Protobuf::Rpc::SocketRunner }
170
+
171
+ before do
172
+ ::Protobuf::Rpc::ZmqRunner.should_not_receive(:new)
173
+ end
174
+
175
+ it 'is activated by the --socket switch' do
176
+ runner.should_receive(:new)
177
+ described_class.start(args)
178
+ end
179
+
180
+ it 'is activated by PB_SERVER_TYPE=Socket ENV variable' do
181
+ ENV['PB_SERVER_TYPE'] = "Socket"
182
+ runner.should_receive(:new).and_return(sock_runner)
183
+ described_class.start(args)
184
+ ENV.delete('PB_SERVER_TYPE')
185
+ end
186
+
187
+ it 'configures the connector type to be socket' do
188
+ load "protobuf/socket.rb"
189
+ ::Protobuf.connector_type.should == :socket
190
+ end
191
+ end
192
+
193
+ context 'zmq workers only' do
194
+ let(:test_args) { [ '--workers_only', '--zmq' ] }
195
+ let(:runner) { ::Protobuf::Rpc::ZmqRunner }
196
+
197
+ before do
198
+ ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
199
+ end
200
+
201
+ it 'is activated by the --workers_only switch' do
202
+ runner.should_receive(:new) do |options|
203
+ options[:workers_only].should be_true
204
+ end.and_return(zmq_runner)
205
+
206
+ described_class.start(args)
207
+ end
208
+
209
+ it 'is activated by PB_WORKERS_ONLY=1 ENV variable' do
210
+ ENV['PB_WORKERS_ONLY'] = "1"
211
+ runner.should_receive(:new) do |options|
212
+ options[:workers_only].should be_true
213
+ end.and_return(zmq_runner)
214
+
215
+ described_class.start(args)
216
+ ENV.delete('PB_WORKERS_ONLY')
217
+ end
218
+ end
219
+
220
+ context 'zmq worker port' do
221
+ let(:test_args) { [ '--worker_port=1234', '--zmq' ] }
222
+ let(:runner) { ::Protobuf::Rpc::ZmqRunner }
223
+
224
+ before do
225
+ ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
226
+ end
227
+
228
+ it 'is activated by the --worker_port switch' do
229
+ runner.should_receive(:new) do |options|
230
+ options[:worker_port].should eq(1234)
231
+ end.and_return(zmq_runner)
232
+
233
+ described_class.start(args)
234
+ end
235
+ end
236
+
237
+ context 'zmq' do
238
+ let(:test_args) { [ '--zmq' ] }
239
+ let(:runner) { ::Protobuf::Rpc::ZmqRunner }
240
+
241
+ before do
242
+ ::Protobuf::Rpc::SocketRunner.should_not_receive(:new)
243
+ end
244
+
245
+ it 'is activated by the --zmq switch' do
246
+ runner.should_receive(:new)
247
+ described_class.start(args)
248
+ end
249
+
250
+ it 'is activated by PB_SERVER_TYPE=Zmq ENV variable' do
251
+ ENV['PB_SERVER_TYPE'] = "Zmq"
252
+ runner.should_receive(:new)
253
+ described_class.start(args)
254
+ ENV.delete('PB_SERVER_TYPE')
255
+ end
256
+
257
+ it 'configures the connector type to be zmq' do
258
+ load "protobuf/zmq.rb"
259
+ ::Protobuf.connector_type.should == :zmq
260
+ end
261
+ end
262
+
263
+ end
264
+
265
+ end
266
+
267
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ require 'protobuf/code_generator'
4
+
5
+ describe ::Protobuf::CodeGenerator do
6
+
7
+ # Some constants to shorten things up
8
+ DESCRIPTOR = ::Google::Protobuf
9
+ COMPILER = ::Google::Protobuf::Compiler
10
+
11
+ describe '#response_bytes' do
12
+ let(:input_file1) { DESCRIPTOR::FileDescriptorProto.new(:name => 'test/foo.proto') }
13
+ let(:input_file2) { DESCRIPTOR::FileDescriptorProto.new(:name => 'test/bar.proto') }
14
+
15
+ let(:output_file1) { COMPILER::CodeGeneratorResponse::File.new(:name => 'test/foo.pb.rb') }
16
+ let(:output_file2) { COMPILER::CodeGeneratorResponse::File.new(:name => 'test/bar.pb.rb') }
17
+
18
+ let(:file_generator1) { double('file generator 1', :generate_output_file => output_file1) }
19
+ let(:file_generator2) { double('file generator 2', :generate_output_file => output_file2) }
20
+
21
+ let(:request_bytes) do
22
+ COMPILER::CodeGeneratorRequest.encode(:proto_file => [ input_file1, input_file2 ])
23
+ end
24
+
25
+ let(:expected_response_bytes) do
26
+ COMPILER::CodeGeneratorResponse.encode(:file => [ output_file1, output_file2 ])
27
+ end
28
+
29
+ before do
30
+ ::Protobuf::Generators::FileGenerator.should_receive(:new).with(input_file1).and_return(file_generator1)
31
+ ::Protobuf::Generators::FileGenerator.should_receive(:new).with(input_file2).and_return(file_generator2)
32
+ end
33
+
34
+ it 'returns the serialized CodeGeneratorResponse which contains the generated file contents' do
35
+ generator = described_class.new(request_bytes)
36
+ generator.response_bytes.should eq expected_response_bytes
37
+ end
38
+ end
39
+
40
+ context 'class-level printing methods' do
41
+ describe '.fatal' do
42
+ it 'raises a CodeGeneratorFatalError error' do
43
+ expect {
44
+ described_class.fatal("something is wrong")
45
+ }.to raise_error(
46
+ ::Protobuf::CodeGenerator::CodeGeneratorFatalError,
47
+ "something is wrong"
48
+ )
49
+ end
50
+ end
51
+
52
+ describe '.warn' do
53
+ it 'prints a warning to stderr' do
54
+ STDERR.should_receive(:puts).with("[WARN] a warning")
55
+ described_class.warn("a warning")
56
+ end
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,239 @@
1
+ require 'spec_helper'
2
+
3
+ describe Protobuf::Enum do
4
+
5
+ describe 'class dsl' do
6
+ let(:name) { :THREE }
7
+ let(:tag) { 3 }
8
+
9
+ before(:all) do
10
+ Test::EnumTestType.define(:MINUS_ONE, -1)
11
+ Test::EnumTestType.define(:THREE, 3)
12
+ end
13
+
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
20
+ end
21
+ end
22
+
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
26
+ end
27
+ end
28
+
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
48
+ end
49
+ end
50
+
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
69
+ end
70
+ end
71
+
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
79
+ end
80
+
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
117
+ end
118
+
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
124
+ end
125
+
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 }
167
+ end
168
+ end
169
+
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
174
+ end
175
+
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
193
+ end
194
+
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
200
+ end
201
+ end
202
+
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) } }
229
+ end
230
+
231
+ context 'when coercing from enum' do
232
+ subject { Test::StatusType::PENDING }
233
+ it { should eq(0) }
234
+ end
235
+
236
+ context 'when coercing from integer' do
237
+ specify { expect(0).to eq(Test::StatusType::PENDING) }
238
+ end
239
+ end