protobuf-core 3.5.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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +23 -0
- data/Rakefile +5 -0
- data/bin/protoc-gen-ruby +16 -0
- data/lib/protobuf.rb +27 -0
- data/lib/protobuf/code_generator.rb +44 -0
- data/lib/protobuf/core.rb +2 -0
- data/lib/protobuf/core/version.rb +5 -0
- data/lib/protobuf/decoder.rb +73 -0
- data/lib/protobuf/deprecation.rb +112 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +54 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +251 -0
- data/lib/protobuf/encoder.rb +67 -0
- data/lib/protobuf/enum.rb +303 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/field/base_field.rb +267 -0
- data/lib/protobuf/field/bool_field.rb +59 -0
- data/lib/protobuf/field/bytes_field.rb +82 -0
- data/lib/protobuf/field/double_field.rb +25 -0
- data/lib/protobuf/field/enum_field.rb +68 -0
- data/lib/protobuf/field/field_array.rb +87 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +28 -0
- data/lib/protobuf/field/float_field.rb +41 -0
- data/lib/protobuf/field/int32_field.rb +21 -0
- data/lib/protobuf/field/int64_field.rb +21 -0
- data/lib/protobuf/field/integer_field.rb +23 -0
- data/lib/protobuf/field/message_field.rb +65 -0
- data/lib/protobuf/field/sfixed32_field.rb +27 -0
- data/lib/protobuf/field/sfixed64_field.rb +28 -0
- data/lib/protobuf/field/signed_integer_field.rb +29 -0
- data/lib/protobuf/field/sint32_field.rb +21 -0
- data/lib/protobuf/field/sint64_field.rb +21 -0
- data/lib/protobuf/field/string_field.rb +34 -0
- data/lib/protobuf/field/uint32_field.rb +21 -0
- data/lib/protobuf/field/uint64_field.rb +21 -0
- data/lib/protobuf/field/varint_field.rb +73 -0
- data/lib/protobuf/generators/base.rb +70 -0
- data/lib/protobuf/generators/enum_generator.rb +41 -0
- data/lib/protobuf/generators/extension_generator.rb +27 -0
- data/lib/protobuf/generators/field_generator.rb +131 -0
- data/lib/protobuf/generators/file_generator.rb +132 -0
- data/lib/protobuf/generators/group_generator.rb +105 -0
- data/lib/protobuf/generators/message_generator.rb +98 -0
- data/lib/protobuf/generators/printable.rb +160 -0
- data/lib/protobuf/logging.rb +39 -0
- data/lib/protobuf/message.rb +193 -0
- data/lib/protobuf/message/fields.rb +133 -0
- data/lib/protobuf/message/serialization.rb +89 -0
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/proto/dynamic_discovery.proto +44 -0
- data/proto/google/protobuf/compiler/plugin.proto +147 -0
- data/proto/google/protobuf/descriptor.proto +620 -0
- data/proto/rpc.proto +62 -0
- data/protobuf-core.gemspec +31 -0
- data/spec/bin/protoc-gen-ruby_spec.rb +23 -0
- data/spec/data/data.bin +3 -0
- data/spec/data/types.bin +0 -0
- data/spec/encoding/all_types_spec.rb +105 -0
- data/spec/encoding/extreme_values_spec.rb +0 -0
- data/spec/functional/class_inheritance_spec.rb +52 -0
- data/spec/functional/compile_and_require_spec.rb +29 -0
- data/spec/lib/protobuf/base_spec.rb +84 -0
- data/spec/lib/protobuf/code_generator_spec.rb +60 -0
- data/spec/lib/protobuf/enum_generator_spec.rb +73 -0
- data/spec/lib/protobuf/enum_spec.rb +265 -0
- data/spec/lib/protobuf/extension_generator_spec.rb +42 -0
- data/spec/lib/protobuf/field/bool_field_spec.rb +51 -0
- data/spec/lib/protobuf/field/field_array_spec.rb +69 -0
- data/spec/lib/protobuf/field/float_field_spec.rb +55 -0
- data/spec/lib/protobuf/field/int32_field_spec.rb +90 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +45 -0
- data/spec/lib/protobuf/field_generator_spec.rb +102 -0
- data/spec/lib/protobuf/field_spec.rb +191 -0
- data/spec/lib/protobuf/file_generator_spec.rb +32 -0
- data/spec/lib/protobuf/message_generator_spec.rb +0 -0
- data/spec/lib/protobuf/message_spec.rb +526 -0
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf_spec.rb +45 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/packed_field.rb +22 -0
- data/spec/support/test/all_types.data.bin +0 -0
- data/spec/support/test/all_types.data.txt +119 -0
- data/spec/support/test/bacon.proto +14 -0
- data/spec/support/test/defaults.pb.rb +27 -0
- data/spec/support/test/defaults.proto +9 -0
- data/spec/support/test/enum.pb.rb +61 -0
- data/spec/support/test/enum.proto +34 -0
- data/spec/support/test/extended.pb.rb +24 -0
- data/spec/support/test/extended.proto +10 -0
- data/spec/support/test/extreme_values.data.bin +0 -0
- data/spec/support/test/google_unittest.pb.rb +530 -0
- data/spec/support/test/google_unittest.proto +713 -0
- data/spec/support/test/google_unittest_import.pb.rb +39 -0
- data/spec/support/test/google_unittest_import.proto +64 -0
- data/spec/support/test/google_unittest_import_public.pb.rb +10 -0
- data/spec/support/test/google_unittest_import_public.proto +38 -0
- data/spec/support/test/multi_field_extensions.pb.rb +58 -0
- data/spec/support/test/multi_field_extensions.proto +33 -0
- data/spec/support/test/resource.pb.rb +106 -0
- data/spec/support/test/resource.proto +94 -0
- metadata +306 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'protobuf/generators/file_generator'
|
4
|
+
|
5
|
+
RSpec.describe ::Protobuf::Generators::FileGenerator do
|
6
|
+
|
7
|
+
let(:base_descriptor_fields) { { :name => 'test/foo.proto' } }
|
8
|
+
let(:descriptor_fields) { base_descriptor_fields }
|
9
|
+
let(:file_descriptor) { ::Google::Protobuf::FileDescriptorProto.new(descriptor_fields) }
|
10
|
+
|
11
|
+
subject { described_class.new(file_descriptor) }
|
12
|
+
specify { expect(subject.file_name).to eq('test/foo.pb.rb') }
|
13
|
+
|
14
|
+
describe '#print_import_requires' do
|
15
|
+
let(:descriptor_fields) do
|
16
|
+
base_descriptor_fields.merge(
|
17
|
+
:dependency => [
|
18
|
+
'test/bar.proto',
|
19
|
+
'test/baz.proto',
|
20
|
+
],
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'prints a ruby require for each dependency' do
|
25
|
+
expect(subject).to receive(:print_require).with('test/bar.pb')
|
26
|
+
expect(subject).to receive(:print_require).with('test/baz.pb')
|
27
|
+
subject.print_import_requires
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
File without changes
|
@@ -0,0 +1,526 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require 'spec_helper'
|
5
|
+
|
6
|
+
RSpec.describe Protobuf::Message do
|
7
|
+
|
8
|
+
describe '.decode' do
|
9
|
+
let(:message) { ::Test::Resource.new(:name => "Jim") }
|
10
|
+
|
11
|
+
it 'creates a new message object decoded from the given bytes' do
|
12
|
+
expect(::Test::Resource.decode(message.encode)).to eq message
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'with a new enum value' do
|
16
|
+
let(:older_message) do
|
17
|
+
Class.new(Protobuf::Message) do
|
18
|
+
enum_class = Class.new(::Protobuf::Enum) do
|
19
|
+
define :YAY, 1
|
20
|
+
end
|
21
|
+
|
22
|
+
optional enum_class, :enum_field, 1
|
23
|
+
repeated enum_class, :enum_list, 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:newer_message) do
|
28
|
+
Class.new(Protobuf::Message) do
|
29
|
+
enum_class = Class.new(::Protobuf::Enum) do
|
30
|
+
define :YAY, 1
|
31
|
+
define :HOORAY, 2
|
32
|
+
end
|
33
|
+
|
34
|
+
optional enum_class, :enum_field, 1
|
35
|
+
repeated enum_class, :enum_list, 2
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with a singular field' do
|
40
|
+
it 'treats the field as if it was unset when decoding' do
|
41
|
+
newer = newer_message.new(:enum_field => :HOORAY).serialize
|
42
|
+
|
43
|
+
expect(older_message.decode(newer).enum_field!).to be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'rejects an unknown value when using the constructor' do
|
47
|
+
expect { older_message.new(:enum_field => :HOORAY) }.to raise_error
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'rejects an unknown value when the setter' do
|
51
|
+
older = older_message.new
|
52
|
+
expect { older.enum_field = :HOORAY }.to raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with a repeated field' do
|
57
|
+
it 'treats the field as if it was unset when decoding' do
|
58
|
+
newer = newer_message.new(:enum_list => [:HOORAY]).serialize
|
59
|
+
|
60
|
+
expect(older_message.decode(newer).enum_list).to eq([])
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'rejects an unknown value when using the constructor' do
|
64
|
+
expect { older_message.new(:enum_list => [:HOORAY]) }.to raise_error
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'rejects an unknown value when the setter' do
|
68
|
+
older = older_message.new
|
69
|
+
expect { older.enum_field = [:HOORAY] }.to raise_error
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '.decode_from' do
|
76
|
+
let(:message) { ::Test::Resource.new(:name => "Jim") }
|
77
|
+
|
78
|
+
it 'creates a new message object decoded from the given byte stream' do
|
79
|
+
stream = ::StringIO.new(message.encode)
|
80
|
+
expect(::Test::Resource.decode_from(stream)).to eq message
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'defining a new field' do
|
85
|
+
context 'when defining a field with a tag that has already been used' do
|
86
|
+
it 'raises a TagCollisionError' do
|
87
|
+
expect do
|
88
|
+
Class.new(Protobuf::Message) do
|
89
|
+
optional ::Protobuf::Field::Int32Field, :foo, 1
|
90
|
+
optional ::Protobuf::Field::Int32Field, :bar, 1
|
91
|
+
end
|
92
|
+
end.to raise_error(Protobuf::TagCollisionError, /Field number 1 has already been used/)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when defining an extension field with a tag that has already been used' do
|
97
|
+
it 'raises a TagCollisionError' do
|
98
|
+
expect do
|
99
|
+
Class.new(Protobuf::Message) do
|
100
|
+
extensions 100...110
|
101
|
+
optional ::Protobuf::Field::Int32Field, :foo, 100
|
102
|
+
optional ::Protobuf::Field::Int32Field, :bar, 100, :extension => true
|
103
|
+
end
|
104
|
+
end.to raise_error(Protobuf::TagCollisionError, /Field number 100 has already been used/)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'when defining a field with a name that has already been used' do
|
109
|
+
it 'raises a DuplicateFieldNameError' do
|
110
|
+
expect do
|
111
|
+
Class.new(Protobuf::Message) do
|
112
|
+
optional ::Protobuf::Field::Int32Field, :foo, 1
|
113
|
+
optional ::Protobuf::Field::Int32Field, :foo, 2
|
114
|
+
end
|
115
|
+
end.to raise_error(Protobuf::DuplicateFieldNameError, /Field name foo has already been used/)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'when defining an extension field with a name that has already been used' do
|
120
|
+
it 'raises a DuplicateFieldNameError' do
|
121
|
+
expect do
|
122
|
+
Class.new(Protobuf::Message) do
|
123
|
+
extensions 100...110
|
124
|
+
optional ::Protobuf::Field::Int32Field, :foo, 1
|
125
|
+
optional ::Protobuf::Field::Int32Field, :foo, 100, :extension => true
|
126
|
+
end
|
127
|
+
end.to raise_error(Protobuf::DuplicateFieldNameError, /Field name foo has already been used/)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '.encode' do
|
133
|
+
let(:values) { { :name => "Jim" } }
|
134
|
+
|
135
|
+
it 'creates a new message object with the given values and returns the encoded bytes' do
|
136
|
+
expect(::Test::Resource.encode(values)).to eq ::Test::Resource.new(values).encode
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#initialize' do
|
141
|
+
it "defaults to the first value listed in the enum's type definition" do
|
142
|
+
test_enum = Test::EnumTestMessage.new
|
143
|
+
expect(test_enum.non_default_enum).to eq(1)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "defaults to a a value with a name" do
|
147
|
+
test_enum = Test::EnumTestMessage.new
|
148
|
+
expect(test_enum.non_default_enum.name).to eq(:ONE)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "exposes the enum getter raw value through ! method" do
|
152
|
+
test_enum = Test::EnumTestMessage.new
|
153
|
+
expect(test_enum.non_default_enum!).to be_nil
|
154
|
+
end
|
155
|
+
|
156
|
+
it "exposes the enum getter raw value through ! method (when set)" do
|
157
|
+
test_enum = Test::EnumTestMessage.new
|
158
|
+
test_enum.non_default_enum = 1
|
159
|
+
expect(test_enum.non_default_enum!).to eq(1)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "does not try to set attributes which have nil values" do
|
163
|
+
expect_any_instance_of(Test::EnumTestMessage).not_to receive("non_default_enum=")
|
164
|
+
Test::EnumTestMessage.new(:non_default_enum => nil)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "takes a hash as an initialization argument" do
|
168
|
+
test_enum = Test::EnumTestMessage.new(:non_default_enum => 2)
|
169
|
+
expect(test_enum.non_default_enum).to eq(2)
|
170
|
+
end
|
171
|
+
|
172
|
+
it "initializes with an object that responds to #to_hash" do
|
173
|
+
hashie_object = OpenStruct.new(:to_hash => { :non_default_enum => 2 })
|
174
|
+
test_enum = Test::EnumTestMessage.new(hashie_object)
|
175
|
+
expect(test_enum.non_default_enum).to eq(2)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "initializes with an object with a block" do
|
179
|
+
test_enum = Test::EnumTestMessage.new { |p| p.non_default_enum = 2 }
|
180
|
+
expect(test_enum.non_default_enum).to eq(2)
|
181
|
+
end
|
182
|
+
|
183
|
+
context 'ignoring unknown fields' do
|
184
|
+
before { ::Protobuf.ignore_unknown_fields = true }
|
185
|
+
|
186
|
+
context 'with valid fields' do
|
187
|
+
let(:values) { { :name => "Jim" } }
|
188
|
+
|
189
|
+
it "does not raise an error" do
|
190
|
+
expect { ::Test::Resource.new(values) }.to_not raise_error
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'with non-existent field' do
|
195
|
+
let(:values) { { :name => "Jim", :othername => "invalid" } }
|
196
|
+
|
197
|
+
it "does not raise an error" do
|
198
|
+
expect { ::Test::Resource.new(values) }.to_not raise_error
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context 'not ignoring unknown fields' do
|
204
|
+
before { ::Protobuf.ignore_unknown_fields = false }
|
205
|
+
after { ::Protobuf.ignore_unknown_fields = true }
|
206
|
+
|
207
|
+
context 'with valid fields' do
|
208
|
+
let(:values) { { :name => "Jim" } }
|
209
|
+
|
210
|
+
it "does not raise an error" do
|
211
|
+
expect { ::Test::Resource.new(values) }.to_not raise_error
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context 'with non-existent field' do
|
216
|
+
let(:values) { { :name => "Jim", :othername => "invalid" } }
|
217
|
+
|
218
|
+
it "raises an error and mentions the erroneous field" do
|
219
|
+
expect { ::Test::Resource.new(values) }.to raise_error(::Protobuf::FieldNotDefinedError, /othername/)
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'with a nil value' do
|
223
|
+
let(:values) { { :name => "Jim", :othername => nil } }
|
224
|
+
|
225
|
+
it "raises an error and mentions the erroneous field" do
|
226
|
+
expect { ::Test::Resource.new(values) }.to raise_error(::Protobuf::FieldNotDefinedError, /othername/)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe '#encode' do
|
234
|
+
context "encoding" do
|
235
|
+
it "accepts UTF-8 strings into string fields" do
|
236
|
+
message = ::Test::Resource.new(:name => "Kyle Redfearn\u0060s iPad")
|
237
|
+
|
238
|
+
expect { message.encode }.to_not raise_error
|
239
|
+
end
|
240
|
+
|
241
|
+
it "keeps utf-8 when utf-8 is input for string fields" do
|
242
|
+
name = 'my name💩'
|
243
|
+
name.force_encoding(Encoding::UTF_8)
|
244
|
+
|
245
|
+
message = ::Test::Resource.new(:name => name)
|
246
|
+
new_message = ::Test::Resource.decode(message.encode)
|
247
|
+
expect(new_message.name == name).to be true
|
248
|
+
end
|
249
|
+
|
250
|
+
it "trims binary when binary is input for string fields" do
|
251
|
+
name = "my name\xC3"
|
252
|
+
name.force_encoding(Encoding::BINARY)
|
253
|
+
|
254
|
+
message = ::Test::Resource.new(:name => name)
|
255
|
+
new_message = ::Test::Resource.decode(message.encode)
|
256
|
+
expect(new_message.name == "my name").to be true
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
context "when there's no value for a required field" do
|
261
|
+
let(:message) { ::Test::ResourceWithRequiredField.new }
|
262
|
+
|
263
|
+
it "raises a 'message not initialized' error" do
|
264
|
+
expect do
|
265
|
+
message.encode
|
266
|
+
end.to raise_error(Protobuf::SerializationError, /required/i)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context "repeated fields" do
|
271
|
+
let(:message) { ::Test::Resource.new(:name => "something") }
|
272
|
+
|
273
|
+
it "does not raise an error when repeated fields are []" do
|
274
|
+
expect do
|
275
|
+
message.repeated_enum = []
|
276
|
+
message.encode
|
277
|
+
end.to_not raise_error
|
278
|
+
end
|
279
|
+
|
280
|
+
it "sets the value to nil when empty array is passed" do
|
281
|
+
message.repeated_enum = []
|
282
|
+
expect(message.instance_variable_get("@values")[:repeated_enum]).to be_nil
|
283
|
+
end
|
284
|
+
|
285
|
+
it "does not compact the edit original array" do
|
286
|
+
a = [nil].freeze
|
287
|
+
message.repeated_enum = a
|
288
|
+
expect(message.repeated_enum).to eq([])
|
289
|
+
expect(a).to eq([nil].freeze)
|
290
|
+
end
|
291
|
+
|
292
|
+
it "compacts the set array" do
|
293
|
+
message.repeated_enum = [nil]
|
294
|
+
expect(message.repeated_enum).to eq([])
|
295
|
+
end
|
296
|
+
|
297
|
+
it "raises TypeError when a non-array replaces it" do
|
298
|
+
expect do
|
299
|
+
message.repeated_enum = 2
|
300
|
+
end.to raise_error(/value of type/)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe "boolean predicate methods" do
|
306
|
+
subject { Test::ResourceFindRequest.new(:name => "resource") }
|
307
|
+
|
308
|
+
it { is_expected.to respond_to(:active?) }
|
309
|
+
|
310
|
+
it "sets the predicate to true when the boolean value is true" do
|
311
|
+
subject.active = true
|
312
|
+
expect(subject.active?).to be true
|
313
|
+
end
|
314
|
+
|
315
|
+
it "sets the predicate to false when the boolean value is false" do
|
316
|
+
subject.active = false
|
317
|
+
expect(subject.active?).to be false
|
318
|
+
end
|
319
|
+
|
320
|
+
it "does not put predicate methods on non-boolean fields" do
|
321
|
+
expect(Test::ResourceFindRequest.new(:name => "resource")).to_not respond_to(:name?)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
describe "#respond_to_and_has?" do
|
326
|
+
subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
|
327
|
+
|
328
|
+
it "is false when the message does not have the field" do
|
329
|
+
expect(subject.respond_to_and_has?(:other_field)).to be false
|
330
|
+
end
|
331
|
+
|
332
|
+
it "is true when the message has the field" do
|
333
|
+
expect(subject.respond_to_and_has?(:non_default_enum)).to be true
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "#respond_to_has_and_present?" do
|
338
|
+
subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
|
339
|
+
|
340
|
+
it "is false when the message does not have the field" do
|
341
|
+
expect(subject.respond_to_and_has_and_present?(:other_field)).to be false
|
342
|
+
end
|
343
|
+
|
344
|
+
it "is false when the field is repeated and a value is not present" do
|
345
|
+
expect(subject.respond_to_and_has_and_present?(:repeated_enums)).to be false
|
346
|
+
end
|
347
|
+
|
348
|
+
it "is false when the field is repeated and the value is empty array" do
|
349
|
+
subject.repeated_enums = []
|
350
|
+
expect(subject.respond_to_and_has_and_present?(:repeated_enums)).to be false
|
351
|
+
end
|
352
|
+
|
353
|
+
it "is true when the field is repeated and a value is present" do
|
354
|
+
subject.repeated_enums = [2]
|
355
|
+
expect(subject.respond_to_and_has_and_present?(:repeated_enums)).to be true
|
356
|
+
end
|
357
|
+
|
358
|
+
it "is true when the message has the field" do
|
359
|
+
expect(subject.respond_to_and_has_and_present?(:non_default_enum)).to be true
|
360
|
+
end
|
361
|
+
|
362
|
+
context "#API" do
|
363
|
+
subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
|
364
|
+
|
365
|
+
specify { expect(subject).to respond_to(:respond_to_and_has_and_present?) }
|
366
|
+
specify { expect(subject).to respond_to(:responds_to_and_has_and_present?) }
|
367
|
+
specify { expect(subject).to respond_to(:responds_to_has?) }
|
368
|
+
specify { expect(subject).to respond_to(:respond_to_has?) }
|
369
|
+
specify { expect(subject).to respond_to(:respond_to_has_present?) }
|
370
|
+
specify { expect(subject).to respond_to(:responds_to_has_present?) }
|
371
|
+
specify { expect(subject).to respond_to(:respond_to_and_has_present?) }
|
372
|
+
specify { expect(subject).to respond_to(:responds_to_and_has_present?) }
|
373
|
+
end
|
374
|
+
|
375
|
+
end
|
376
|
+
|
377
|
+
describe '#inspect' do
|
378
|
+
let(:klass) do
|
379
|
+
Class.new(Protobuf::Message) do |klass|
|
380
|
+
enum_class = Class.new(Protobuf::Enum) do
|
381
|
+
define :YAY, 1
|
382
|
+
end
|
383
|
+
|
384
|
+
klass.const_set(:EnumKlass, enum_class)
|
385
|
+
|
386
|
+
optional :string, :name, 1
|
387
|
+
repeated :int32, :counts, 2
|
388
|
+
optional enum_class, :enum, 3
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
before { stub_const('MyMessage', klass) }
|
393
|
+
|
394
|
+
it 'lists the fields' do
|
395
|
+
proto = klass.new(:name => 'wooo', :counts => [1, 2, 3], :enum => klass::EnumKlass::YAY)
|
396
|
+
expect(proto.inspect).to eq('#<MyMessage name="wooo" counts=[1, 2, 3] enum=#<Protobuf::Enum(MyMessage::EnumKlass)::YAY=1>>')
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
describe '#to_hash' do
|
401
|
+
context 'generating values for an ENUM field' do
|
402
|
+
it 'converts the enum to its tag representation' do
|
403
|
+
hash = Test::EnumTestMessage.new(:non_default_enum => :TWO).to_hash
|
404
|
+
expect(hash).to eq(:non_default_enum => 2)
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'does not populate default values' do
|
408
|
+
hash = Test::EnumTestMessage.new.to_hash
|
409
|
+
expect(hash).to eq({})
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'converts repeated enum fields to an array of the tags' do
|
413
|
+
hash = Test::EnumTestMessage.new(:repeated_enums => [:ONE, :TWO, :TWO, :ONE]).to_hash
|
414
|
+
expect(hash).to eq(:repeated_enums => [1, 2, 2, 1])
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
context 'generating values for a Message field' do
|
419
|
+
it 'recursively hashes field messages' do
|
420
|
+
hash = Test::Nested.new(:resource => { :name => 'Nested' }).to_hash
|
421
|
+
expect(hash).to eq(:resource => { :name => 'Nested' })
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'recursively hashes a repeated set of messages' do
|
425
|
+
proto = Test::Nested.new(
|
426
|
+
:multiple_resources => [
|
427
|
+
Test::Resource.new(:name => 'Resource 1'),
|
428
|
+
Test::Resource.new(:name => 'Resource 2'),
|
429
|
+
],
|
430
|
+
)
|
431
|
+
|
432
|
+
expect(proto.to_hash).to eq(
|
433
|
+
:multiple_resources => [
|
434
|
+
{ :name => 'Resource 1' },
|
435
|
+
{ :name => 'Resource 2' },
|
436
|
+
],
|
437
|
+
)
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
describe '#to_json' do
|
443
|
+
subject do
|
444
|
+
::Test::ResourceFindRequest.new(:name => 'Test Name', :active => false)
|
445
|
+
end
|
446
|
+
|
447
|
+
specify { expect(subject.to_json).to eq '{"name":"Test Name","active":false}' }
|
448
|
+
end
|
449
|
+
|
450
|
+
describe '.to_json' do
|
451
|
+
it 'returns the class name of the message for use in json encoding' do
|
452
|
+
expect do
|
453
|
+
::Timeout.timeout(0.1) do
|
454
|
+
expect(::Test::Resource.to_json).to eq("Test::Resource")
|
455
|
+
end
|
456
|
+
end.not_to raise_error
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
describe "#define_setter" do
|
461
|
+
subject { ::Test::Resource.new }
|
462
|
+
|
463
|
+
it "allows string fields to be set to nil" do
|
464
|
+
expect { subject.name = nil }.to_not raise_error
|
465
|
+
end
|
466
|
+
|
467
|
+
it "does not allow string fields to be set to Numeric" do
|
468
|
+
expect { subject.name = 1 }.to raise_error(/name/)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
describe '.get_extension_field' do
|
473
|
+
it 'fetches an extension field by its tag' do
|
474
|
+
field = ::Test::Resource.get_extension_field(100)
|
475
|
+
expect(field).to be_a(::Protobuf::Field::BoolField)
|
476
|
+
expect(field.tag).to eq(100)
|
477
|
+
expect(field.name).to eq(:ext_is_searchable)
|
478
|
+
expect(field).to be_extension
|
479
|
+
end
|
480
|
+
|
481
|
+
it 'fetches an extension field by its symbolized name' do
|
482
|
+
expect(::Test::Resource.get_extension_field(:ext_is_searchable)).to be_a(::Protobuf::Field::BoolField)
|
483
|
+
expect(::Test::Resource.get_extension_field('ext_is_searchable')).to be_a(::Protobuf::Field::BoolField)
|
484
|
+
end
|
485
|
+
|
486
|
+
it 'returns nil when attempting to get a non-extension field' do
|
487
|
+
expect(::Test::Resource.get_extension_field(1)).to be_nil
|
488
|
+
end
|
489
|
+
|
490
|
+
it 'returns nil when field is not found' do
|
491
|
+
expect(::Test::Resource.get_extension_field(-1)).to be_nil
|
492
|
+
expect(::Test::Resource.get_extension_field(nil)).to be_nil
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
describe '.get_field' do
|
497
|
+
it 'fetches a non-extension field by its tag' do
|
498
|
+
field = ::Test::Resource.get_field(1)
|
499
|
+
expect(field).to be_a(::Protobuf::Field::StringField)
|
500
|
+
expect(field.tag).to eq(1)
|
501
|
+
expect(field.name).to eq(:name)
|
502
|
+
expect(field).not_to be_extension
|
503
|
+
end
|
504
|
+
|
505
|
+
it 'fetches a non-extension field by its symbolized name' do
|
506
|
+
expect(::Test::Resource.get_field(:name)).to be_a(::Protobuf::Field::StringField)
|
507
|
+
expect(::Test::Resource.get_field('name')).to be_a(::Protobuf::Field::StringField)
|
508
|
+
end
|
509
|
+
|
510
|
+
it 'fetches an extension field when forced' do
|
511
|
+
expect(::Test::Resource.get_field(100, true)).to be_a(::Protobuf::Field::BoolField)
|
512
|
+
expect(::Test::Resource.get_field(:ext_is_searchable, true)).to be_a(::Protobuf::Field::BoolField)
|
513
|
+
expect(::Test::Resource.get_field('ext_is_searchable', true)).to be_a(::Protobuf::Field::BoolField)
|
514
|
+
end
|
515
|
+
|
516
|
+
it 'returns nil when attempting to get an extension field' do
|
517
|
+
expect(::Test::Resource.get_field(100)).to be_nil
|
518
|
+
end
|
519
|
+
|
520
|
+
it 'returns nil when field is not defined' do
|
521
|
+
expect(::Test::Resource.get_field(-1)).to be_nil
|
522
|
+
expect(::Test::Resource.get_field(nil)).to be_nil
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
end
|