google-protoc 3.0.0.alpha.6.0.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.
@@ -0,0 +1,76 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2008 Google Inc. All rights reserved.
3
+ # https://developers.google.com/protocol-buffers/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following disclaimer
13
+ # in the documentation and/or other materials provided with the
14
+ # distribution.
15
+ # * Neither the name of Google Inc. nor the names of its
16
+ # contributors may be used to endorse or promote products derived from
17
+ # this software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ # require mixins before we hook them into the java & c code
32
+ require 'google/protobuf/message_exts'
33
+
34
+ # We define these before requiring the platform-specific modules.
35
+ # That way the module init can grab references to these.
36
+ module Google
37
+ module Protobuf
38
+ class Error < StandardError; end
39
+ class ParseError < Error; end
40
+ end
41
+ end
42
+
43
+ if RUBY_PLATFORM == "java"
44
+ require 'json'
45
+ require 'google/protobuf_java'
46
+ else
47
+ begin
48
+ require "google/#{RUBY_VERSION.sub(/\.\d$/, '')}/protobuf_c"
49
+ rescue LoadError
50
+ require 'google/protobuf_c'
51
+ end
52
+ end
53
+
54
+ require 'google/protobuf/repeated_field'
55
+
56
+ module Google
57
+ module Protobuf
58
+
59
+ def self.encode(msg)
60
+ msg.to_proto
61
+ end
62
+
63
+ def self.encode_json(msg)
64
+ msg.to_json
65
+ end
66
+
67
+ def self.decode(klass, proto)
68
+ klass.decode(proto)
69
+ end
70
+
71
+ def self.decode_json(klass, json)
72
+ klass.decode_json(json)
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,53 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2008 Google Inc. All rights reserved.
3
+ # https://developers.google.com/protocol-buffers/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following disclaimer
13
+ # in the documentation and/or other materials provided with the
14
+ # distribution.
15
+ # * Neither the name of Google Inc. nor the names of its
16
+ # contributors may be used to endorse or promote products derived from
17
+ # this software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module Google
32
+ module Protobuf
33
+ module MessageExts
34
+
35
+ #this is only called in jruby; mri loades the ClassMethods differently
36
+ def self.included(klass)
37
+ klass.extend(ClassMethods)
38
+ end
39
+
40
+ module ClassMethods
41
+ end
42
+
43
+ def to_json
44
+ self.class.encode_json(self)
45
+ end
46
+
47
+ def to_proto
48
+ self.class.encode(self)
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,188 @@
1
+ # Protocol Buffers - Google's data interchange format
2
+ # Copyright 2008 Google Inc. All rights reserved.
3
+ # https://developers.google.com/protocol-buffers/
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are
7
+ # met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above
12
+ # copyright notice, this list of conditions and the following disclaimer
13
+ # in the documentation and/or other materials provided with the
14
+ # distribution.
15
+ # * Neither the name of Google Inc. nor the names of its
16
+ # contributors may be used to endorse or promote products derived from
17
+ # this software without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'forwardable'
32
+
33
+ #
34
+ # This class makes RepeatedField act (almost-) like a Ruby Array.
35
+ # It has convenience methods that extend the core C or Java based
36
+ # methods.
37
+ #
38
+ # This is a best-effort to mirror Array behavior. Two comments:
39
+ # 1) patches always welcome :)
40
+ # 2) if performance is an issue, feel free to rewrite the method
41
+ # in jruby and C. The source code has plenty of examples
42
+ #
43
+ # KNOWN ISSUES
44
+ # - #[]= doesn't allow less used approaches such as `arr[1, 2] = 'fizz'`
45
+ # - #concat should return the orig array
46
+ # - #push should accept multiple arguments and push them all at the same time
47
+ #
48
+ module Google
49
+ module Protobuf
50
+ class RepeatedField
51
+ extend Forwardable
52
+
53
+ # methods defined in C or Java:
54
+ # +
55
+ # [], at
56
+ # []=
57
+ # concat
58
+ # clear
59
+ # dup, clone
60
+ # each
61
+ # push, <<
62
+ # replace
63
+ # length, size
64
+ # ==
65
+ # to_ary, to_a
66
+ # also all enumerable
67
+ #
68
+ # NOTE: using delegators rather than method_missing to make the
69
+ # relationship explicit instead of implicit
70
+ def_delegators :to_ary,
71
+ :&, :*, :-, :'<=>',
72
+ :assoc, :bsearch, :bsearch_index, :combination, :compact, :count,
73
+ :cycle, :dig, :drop, :drop_while, :eql?, :fetch, :find_index, :flatten,
74
+ :include?, :index, :inspect, :join,
75
+ :pack, :permutation, :product, :pretty_print, :pretty_print_cycle,
76
+ :rassoc, :repeated_combination, :repeated_permutation, :reverse,
77
+ :rindex, :rotate, :sample, :shuffle, :shelljoin, :slice,
78
+ :to_s, :transpose, :uniq, :|
79
+
80
+
81
+ def first(n=nil)
82
+ n ? self[0..n] : self[0]
83
+ end
84
+
85
+
86
+ def last(n=nil)
87
+ n ? self[(self.size-n-1)..-1] : self[-1]
88
+ end
89
+
90
+
91
+ def pop(n=nil)
92
+ if n
93
+ results = []
94
+ n.times{ results << pop_one }
95
+ return results
96
+ else
97
+ return pop_one
98
+ end
99
+ end
100
+
101
+
102
+ def empty?
103
+ self.size == 0
104
+ end
105
+
106
+ # array aliases into enumerable
107
+ alias_method :each_index, :each_with_index
108
+ alias_method :slice, :[]
109
+ alias_method :values_at, :select
110
+ alias_method :map, :collect
111
+
112
+
113
+ class << self
114
+ def define_array_wrapper_method(method_name)
115
+ define_method(method_name) do |*args, &block|
116
+ arr = self.to_a
117
+ result = arr.send(method_name, *args)
118
+ self.replace(arr)
119
+ return result if result
120
+ return block ? block.call : result
121
+ end
122
+ end
123
+ private :define_array_wrapper_method
124
+
125
+
126
+ def define_array_wrapper_with_result_method(method_name)
127
+ define_method(method_name) do |*args, &block|
128
+ # result can be an Enumerator, Array, or nil
129
+ # Enumerator can sometimes be returned if a block is an optional argument and it is not passed in
130
+ # nil usually specifies that no change was made
131
+ result = self.to_a.send(method_name, *args, &block)
132
+ if result
133
+ new_arr = result.to_a
134
+ self.replace(new_arr)
135
+ if result.is_a?(Enumerator)
136
+ # generate a fresh enum; rewinding the exiting one, in Ruby 2.2, will
137
+ # reset the enum with the same length, but all the #next calls will
138
+ # return nil
139
+ result = new_arr.to_enum
140
+ # generate a wrapper enum so any changes which occur by a chained
141
+ # enum can be captured
142
+ ie = ProxyingEnumerator.new(self, result)
143
+ result = ie.to_enum
144
+ end
145
+ end
146
+ result
147
+ end
148
+ end
149
+ private :define_array_wrapper_with_result_method
150
+ end
151
+
152
+
153
+ %w(delete delete_at delete_if shift slice! unshift).each do |method_name|
154
+ define_array_wrapper_method(method_name)
155
+ end
156
+
157
+
158
+ %w(collect! compact! fill flatten! insert reverse!
159
+ rotate! select! shuffle! sort! sort_by! uniq!).each do |method_name|
160
+ define_array_wrapper_with_result_method(method_name)
161
+ end
162
+ alias_method :keep_if, :select!
163
+ alias_method :map!, :collect!
164
+ alias_method :reject!, :delete_if
165
+
166
+
167
+ # propagates changes made by user of enumerator back to the original repeated field.
168
+ # This only applies in cases where the calling function which created the enumerator,
169
+ # such as #sort!, modifies itself rather than a new array, such as #sort
170
+ class ProxyingEnumerator < Struct.new(:repeated_field, :external_enumerator)
171
+ def each(*args, &block)
172
+ results = []
173
+ external_enumerator.each_with_index do |val, i|
174
+ result = yield(val)
175
+ results << result
176
+ #nil means no change occured from yield; usually occurs when #to_a is called
177
+ if result
178
+ repeated_field[i] = result if result != val
179
+ end
180
+ end
181
+ results
182
+ end
183
+ end
184
+
185
+
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,1174 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'google/protobuf'
4
+ require 'test/unit'
5
+
6
+ # ------------- generated code --------------
7
+
8
+ module BasicTest
9
+ pool = Google::Protobuf::DescriptorPool.new
10
+ pool.build do
11
+ add_message "Foo" do
12
+ optional :bar, :message, 1, "Bar"
13
+ repeated :baz, :message, 2, "Baz"
14
+ end
15
+
16
+ add_message "Bar" do
17
+ optional :msg, :string, 1
18
+ end
19
+
20
+ add_message "Baz" do
21
+ optional :msg, :string, 1
22
+ end
23
+
24
+ add_message "TestMessage" do
25
+ optional :optional_int32, :int32, 1
26
+ optional :optional_int64, :int64, 2
27
+ optional :optional_uint32, :uint32, 3
28
+ optional :optional_uint64, :uint64, 4
29
+ optional :optional_bool, :bool, 5
30
+ optional :optional_float, :float, 6
31
+ optional :optional_double, :double, 7
32
+ optional :optional_string, :string, 8
33
+ optional :optional_bytes, :bytes, 9
34
+ optional :optional_msg, :message, 10, "TestMessage2"
35
+ optional :optional_enum, :enum, 11, "TestEnum"
36
+
37
+ repeated :repeated_int32, :int32, 12
38
+ repeated :repeated_int64, :int64, 13
39
+ repeated :repeated_uint32, :uint32, 14
40
+ repeated :repeated_uint64, :uint64, 15
41
+ repeated :repeated_bool, :bool, 16
42
+ repeated :repeated_float, :float, 17
43
+ repeated :repeated_double, :double, 18
44
+ repeated :repeated_string, :string, 19
45
+ repeated :repeated_bytes, :bytes, 20
46
+ repeated :repeated_msg, :message, 21, "TestMessage2"
47
+ repeated :repeated_enum, :enum, 22, "TestEnum"
48
+ end
49
+ add_message "TestMessage2" do
50
+ optional :foo, :int32, 1
51
+ end
52
+
53
+ add_message "Recursive1" do
54
+ optional :foo, :message, 1, "Recursive2"
55
+ end
56
+ add_message "Recursive2" do
57
+ optional :foo, :message, 1, "Recursive1"
58
+ end
59
+
60
+ add_enum "TestEnum" do
61
+ value :Default, 0
62
+ value :A, 1
63
+ value :B, 2
64
+ value :C, 3
65
+ end
66
+
67
+ add_message "BadFieldNames" do
68
+ optional :dup, :int32, 1
69
+ optional :class, :int32, 2
70
+ optional :"a.b", :int32, 3
71
+ end
72
+
73
+ add_message "MapMessage" do
74
+ map :map_string_int32, :string, :int32, 1
75
+ map :map_string_msg, :string, :message, 2, "TestMessage2"
76
+ end
77
+ add_message "MapMessageWireEquiv" do
78
+ repeated :map_string_int32, :message, 1, "MapMessageWireEquiv_entry1"
79
+ repeated :map_string_msg, :message, 2, "MapMessageWireEquiv_entry2"
80
+ end
81
+ add_message "MapMessageWireEquiv_entry1" do
82
+ optional :key, :string, 1
83
+ optional :value, :int32, 2
84
+ end
85
+ add_message "MapMessageWireEquiv_entry2" do
86
+ optional :key, :string, 1
87
+ optional :value, :message, 2, "TestMessage2"
88
+ end
89
+
90
+ add_message "OneofMessage" do
91
+ oneof :my_oneof do
92
+ optional :a, :string, 1
93
+ optional :b, :int32, 2
94
+ optional :c, :message, 3, "TestMessage2"
95
+ optional :d, :enum, 4, "TestEnum"
96
+ end
97
+ end
98
+ end
99
+
100
+ Foo = pool.lookup("Foo").msgclass
101
+ Bar = pool.lookup("Bar").msgclass
102
+ Baz = pool.lookup("Baz").msgclass
103
+ TestMessage = pool.lookup("TestMessage").msgclass
104
+ TestMessage2 = pool.lookup("TestMessage2").msgclass
105
+ Recursive1 = pool.lookup("Recursive1").msgclass
106
+ Recursive2 = pool.lookup("Recursive2").msgclass
107
+ TestEnum = pool.lookup("TestEnum").enummodule
108
+ BadFieldNames = pool.lookup("BadFieldNames").msgclass
109
+ MapMessage = pool.lookup("MapMessage").msgclass
110
+ MapMessageWireEquiv = pool.lookup("MapMessageWireEquiv").msgclass
111
+ MapMessageWireEquiv_entry1 =
112
+ pool.lookup("MapMessageWireEquiv_entry1").msgclass
113
+ MapMessageWireEquiv_entry2 =
114
+ pool.lookup("MapMessageWireEquiv_entry2").msgclass
115
+ OneofMessage = pool.lookup("OneofMessage").msgclass
116
+
117
+ # ------------ test cases ---------------
118
+
119
+ class MessageContainerTest < Test::Unit::TestCase
120
+
121
+ def test_defaults
122
+ m = TestMessage.new
123
+ assert m.optional_int32 == 0
124
+ assert m.optional_int64 == 0
125
+ assert m.optional_uint32 == 0
126
+ assert m.optional_uint64 == 0
127
+ assert m.optional_bool == false
128
+ assert m.optional_float == 0.0
129
+ assert m.optional_double == 0.0
130
+ assert m.optional_string == ""
131
+ assert m.optional_bytes == ""
132
+ assert m.optional_msg == nil
133
+ assert m.optional_enum == :Default
134
+ end
135
+
136
+ def test_setters
137
+ m = TestMessage.new
138
+ m.optional_int32 = -42
139
+ assert m.optional_int32 == -42
140
+ m.optional_int64 = -0x1_0000_0000
141
+ assert m.optional_int64 == -0x1_0000_0000
142
+ m.optional_uint32 = 0x9000_0000
143
+ assert m.optional_uint32 == 0x9000_0000
144
+ m.optional_uint64 = 0x9000_0000_0000_0000
145
+ assert m.optional_uint64 == 0x9000_0000_0000_0000
146
+ m.optional_bool = true
147
+ assert m.optional_bool == true
148
+ m.optional_float = 0.5
149
+ assert m.optional_float == 0.5
150
+ m.optional_double = 0.5
151
+ m.optional_string = "hello"
152
+ assert m.optional_string == "hello"
153
+ m.optional_bytes = "world".encode!('ASCII-8BIT')
154
+ assert m.optional_bytes == "world"
155
+ m.optional_msg = TestMessage2.new(:foo => 42)
156
+ assert m.optional_msg == TestMessage2.new(:foo => 42)
157
+ m.optional_msg = nil
158
+ assert m.optional_msg == nil
159
+ end
160
+
161
+ def test_ctor_args
162
+ m = TestMessage.new(:optional_int32 => -42,
163
+ :optional_msg => TestMessage2.new,
164
+ :optional_enum => :C,
165
+ :repeated_string => ["hello", "there", "world"])
166
+ assert m.optional_int32 == -42
167
+ assert m.optional_msg.class == TestMessage2
168
+ assert m.repeated_string.length == 3
169
+ assert m.optional_enum == :C
170
+ assert m.repeated_string[0] == "hello"
171
+ assert m.repeated_string[1] == "there"
172
+ assert m.repeated_string[2] == "world"
173
+ end
174
+
175
+ def test_inspect
176
+ m = TestMessage.new(:optional_int32 => -42,
177
+ :optional_enum => :A,
178
+ :optional_msg => TestMessage2.new,
179
+ :repeated_string => ["hello", "there", "world"])
180
+ expected = '<BasicTest::TestMessage: optional_int32: -42, optional_int64: 0, optional_uint32: 0, optional_uint64: 0, optional_bool: false, optional_float: 0.0, optional_double: 0.0, optional_string: "", optional_bytes: "", optional_msg: <BasicTest::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: ["hello", "there", "world"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>'
181
+ assert_equal expected, m.inspect
182
+ end
183
+
184
+ def test_hash
185
+ m1 = TestMessage.new(:optional_int32 => 42)
186
+ m2 = TestMessage.new(:optional_int32 => 102)
187
+ assert m1.hash != 0
188
+ assert m2.hash != 0
189
+ # relying on the randomness here -- if hash function changes and we are
190
+ # unlucky enough to get a collision, then change the values above.
191
+ assert m1.hash != m2.hash
192
+ end
193
+
194
+ def test_unknown_field_errors
195
+ e = assert_raise NoMethodError do
196
+ TestMessage.new.hello
197
+ end
198
+ assert_match(/hello/, e.message)
199
+
200
+ e = assert_raise NoMethodError do
201
+ TestMessage.new.hello = "world"
202
+ end
203
+ assert_match(/hello/, e.message)
204
+ end
205
+
206
+ def test_initialization_map_errors
207
+ e = assert_raise ArgumentError do
208
+ TestMessage.new(:hello => "world")
209
+ end
210
+ assert_match(/hello/, e.message)
211
+
212
+ e = assert_raise ArgumentError do
213
+ MapMessage.new(:map_string_int32 => "hello")
214
+ end
215
+ assert_equal e.message, "Expected Hash object as initializer value for map field 'map_string_int32'."
216
+
217
+ e = assert_raise ArgumentError do
218
+ TestMessage.new(:repeated_uint32 => "hello")
219
+ end
220
+ assert_equal e.message, "Expected array as initializer value for repeated field 'repeated_uint32'."
221
+ end
222
+
223
+ def test_type_errors
224
+ m = TestMessage.new
225
+ assert_raise TypeError do
226
+ m.optional_int32 = "hello"
227
+ end
228
+ assert_raise TypeError do
229
+ m.optional_string = 42
230
+ end
231
+ assert_raise TypeError do
232
+ m.optional_string = nil
233
+ end
234
+ assert_raise TypeError do
235
+ m.optional_bool = 42
236
+ end
237
+ assert_raise TypeError do
238
+ m.optional_msg = TestMessage.new # expects TestMessage2
239
+ end
240
+
241
+ assert_raise TypeError do
242
+ m.repeated_int32 = [] # needs RepeatedField
243
+ end
244
+
245
+ assert_raise TypeError do
246
+ m.repeated_int32.push "hello"
247
+ end
248
+
249
+ assert_raise TypeError do
250
+ m.repeated_msg.push TestMessage.new
251
+ end
252
+ end
253
+
254
+ def test_string_encoding
255
+ m = TestMessage.new
256
+
257
+ # Assigning a normal (ASCII or UTF8) string to a bytes field, or
258
+ # ASCII-8BIT to a string field, raises an error.
259
+ assert_raise TypeError do
260
+ m.optional_bytes = "Test string ASCII".encode!('ASCII')
261
+ end
262
+ assert_raise TypeError do
263
+ m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
264
+ end
265
+ assert_raise TypeError do
266
+ m.optional_string = ["FFFF"].pack('H*')
267
+ end
268
+
269
+ # "Ordinary" use case.
270
+ m.optional_bytes = ["FFFF"].pack('H*')
271
+ m.optional_string = "\u0100"
272
+
273
+ # strings are mutable so we can do this, but serialize should catch it.
274
+ m.optional_string = "asdf".encode!('UTF-8')
275
+ m.optional_string.encode!('ASCII-8BIT')
276
+ assert_raise TypeError do
277
+ data = TestMessage.encode(m)
278
+ end
279
+ end
280
+
281
+ def test_rptfield_int32
282
+ l = Google::Protobuf::RepeatedField.new(:int32)
283
+ assert l.count == 0
284
+ l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
285
+ assert l.count == 3
286
+ assert_equal [1, 2, 3], l
287
+ assert_equal l, [1, 2, 3]
288
+ l.push 4
289
+ assert l == [1, 2, 3, 4]
290
+ dst_list = []
291
+ l.each { |val| dst_list.push val }
292
+ assert dst_list == [1, 2, 3, 4]
293
+ assert l.to_a == [1, 2, 3, 4]
294
+ assert l[0] == 1
295
+ assert l[3] == 4
296
+ l[0] = 5
297
+ assert l == [5, 2, 3, 4]
298
+
299
+ l2 = l.dup
300
+ assert l == l2
301
+ assert l.object_id != l2.object_id
302
+ l2.push 6
303
+ assert l.count == 4
304
+ assert l2.count == 5
305
+
306
+ assert l.inspect == '[5, 2, 3, 4]'
307
+
308
+ l.concat([7, 8, 9])
309
+ assert l == [5, 2, 3, 4, 7, 8, 9]
310
+ assert l.pop == 9
311
+ assert l == [5, 2, 3, 4, 7, 8]
312
+
313
+ assert_raise TypeError do
314
+ m = TestMessage.new
315
+ l.push m
316
+ end
317
+
318
+ m = TestMessage.new
319
+ m.repeated_int32 = l
320
+ assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
321
+ assert m.repeated_int32.object_id == l.object_id
322
+ l.push 42
323
+ assert m.repeated_int32.pop == 42
324
+
325
+ l3 = l + l.dup
326
+ assert l3.count == l.count * 2
327
+ l.count.times do |i|
328
+ assert l3[i] == l[i]
329
+ assert l3[l.count + i] == l[i]
330
+ end
331
+
332
+ l.clear
333
+ assert l.count == 0
334
+ l += [1, 2, 3, 4]
335
+ l.replace([5, 6, 7, 8])
336
+ assert l == [5, 6, 7, 8]
337
+
338
+ l4 = Google::Protobuf::RepeatedField.new(:int32)
339
+ l4[5] = 42
340
+ assert l4 == [0, 0, 0, 0, 0, 42]
341
+
342
+ l4 << 100
343
+ assert l4 == [0, 0, 0, 0, 0, 42, 100]
344
+ l4 << 101 << 102
345
+ assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
346
+ end
347
+
348
+ def test_parent_rptfield
349
+ #make sure we set the RepeatedField and can add to it
350
+ m = TestMessage.new
351
+ assert m.repeated_string == []
352
+ m.repeated_string << 'ok'
353
+ m.repeated_string.push('ok2')
354
+ assert m.repeated_string == ['ok', 'ok2']
355
+ m.repeated_string += ['ok3']
356
+ assert m.repeated_string == ['ok', 'ok2', 'ok3']
357
+ end
358
+
359
+ def test_rptfield_msg
360
+ l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
361
+ l.push TestMessage.new
362
+ assert l.count == 1
363
+ assert_raise TypeError do
364
+ l.push TestMessage2.new
365
+ end
366
+ assert_raise TypeError do
367
+ l.push 42
368
+ end
369
+
370
+ l2 = l.dup
371
+ assert l2[0] == l[0]
372
+ assert l2[0].object_id == l[0].object_id
373
+
374
+ l2 = Google::Protobuf.deep_copy(l)
375
+ assert l2[0] == l[0]
376
+ assert l2[0].object_id != l[0].object_id
377
+
378
+ l3 = l + l2
379
+ assert l3.count == 2
380
+ assert l3[0] == l[0]
381
+ assert l3[1] == l2[0]
382
+ l3[0].optional_int32 = 1000
383
+ assert l[0].optional_int32 == 1000
384
+
385
+ new_msg = TestMessage.new(:optional_int32 => 200)
386
+ l4 = l + [new_msg]
387
+ assert l4.count == 2
388
+ new_msg.optional_int32 = 1000
389
+ assert l4[1].optional_int32 == 1000
390
+ end
391
+
392
+ def test_rptfield_enum
393
+ l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
394
+ l.push :A
395
+ l.push :B
396
+ l.push :C
397
+ assert l.count == 3
398
+ assert_raise RangeError do
399
+ l.push :D
400
+ end
401
+ assert l[0] == :A
402
+
403
+ l.push 4
404
+ assert l[3] == 4
405
+ end
406
+
407
+ def test_rptfield_initialize
408
+ assert_raise ArgumentError do
409
+ l = Google::Protobuf::RepeatedField.new
410
+ end
411
+ assert_raise ArgumentError do
412
+ l = Google::Protobuf::RepeatedField.new(:message)
413
+ end
414
+ assert_raise ArgumentError do
415
+ l = Google::Protobuf::RepeatedField.new([1, 2, 3])
416
+ end
417
+ assert_raise ArgumentError do
418
+ l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
419
+ end
420
+ end
421
+
422
+ def test_rptfield_array_ducktyping
423
+ l = Google::Protobuf::RepeatedField.new(:int32)
424
+ length_methods = %w(count length size)
425
+ length_methods.each do |lm|
426
+ assert l.send(lm) == 0
427
+ end
428
+ # out of bounds returns a nil
429
+ assert l[0] == nil
430
+ assert l[1] == nil
431
+ assert l[-1] == nil
432
+ l.push 4
433
+ length_methods.each do |lm|
434
+ assert l.send(lm) == 1
435
+ end
436
+ assert l[0] == 4
437
+ assert l[1] == nil
438
+ assert l[-1] == 4
439
+ assert l[-2] == nil
440
+
441
+ l.push 2
442
+ length_methods.each do |lm|
443
+ assert l.send(lm) == 2
444
+ end
445
+ assert l[0] == 4
446
+ assert l[1] == 2
447
+ assert l[2] == nil
448
+ assert l[-1] == 2
449
+ assert l[-2] == 4
450
+ assert l[-3] == nil
451
+
452
+ #adding out of scope will backfill with empty objects
453
+ end
454
+
455
+ def test_map_basic
456
+ # allowed key types:
457
+ # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
458
+
459
+ m = Google::Protobuf::Map.new(:string, :int32)
460
+ m["asdf"] = 1
461
+ assert m["asdf"] == 1
462
+ m["jkl;"] = 42
463
+ assert m == { "jkl;" => 42, "asdf" => 1 }
464
+ assert m.has_key?("asdf")
465
+ assert !m.has_key?("qwerty")
466
+ assert m.length == 2
467
+
468
+ m2 = m.dup
469
+ assert m == m2
470
+ assert m.hash != 0
471
+ assert m.hash == m2.hash
472
+
473
+ collected = {}
474
+ m.each { |k,v| collected[v] = k }
475
+ assert collected == { 42 => "jkl;", 1 => "asdf" }
476
+
477
+ assert m.delete("asdf") == 1
478
+ assert !m.has_key?("asdf")
479
+ assert m["asdf"] == nil
480
+ assert !m.has_key?("asdf")
481
+
482
+ # We only assert on inspect value when there is one map entry because the
483
+ # order in which elements appear is unspecified (depends on the internal
484
+ # hash function). We don't want a brittle test.
485
+ assert m.inspect == "{\"jkl;\"=>42}"
486
+
487
+ assert m.keys == ["jkl;"]
488
+ assert m.values == [42]
489
+
490
+ m.clear
491
+ assert m.length == 0
492
+ assert m == {}
493
+
494
+ assert_raise TypeError do
495
+ m[1] = 1
496
+ end
497
+ assert_raise RangeError do
498
+ m["asdf"] = 0x1_0000_0000
499
+ end
500
+ end
501
+
502
+ def test_map_ctor
503
+ m = Google::Protobuf::Map.new(:string, :int32,
504
+ {"a" => 1, "b" => 2, "c" => 3})
505
+ assert m == {"a" => 1, "c" => 3, "b" => 2}
506
+ end
507
+
508
+ def test_map_keytypes
509
+ m = Google::Protobuf::Map.new(:int32, :int32)
510
+ m[1] = 42
511
+ m[-1] = 42
512
+ assert_raise RangeError do
513
+ m[0x8000_0000] = 1
514
+ end
515
+ assert_raise TypeError do
516
+ m["asdf"] = 1
517
+ end
518
+
519
+ m = Google::Protobuf::Map.new(:int64, :int32)
520
+ m[0x1000_0000_0000_0000] = 1
521
+ assert_raise RangeError do
522
+ m[0x1_0000_0000_0000_0000] = 1
523
+ end
524
+ assert_raise TypeError do
525
+ m["asdf"] = 1
526
+ end
527
+
528
+ m = Google::Protobuf::Map.new(:uint32, :int32)
529
+ m[0x8000_0000] = 1
530
+ assert_raise RangeError do
531
+ m[0x1_0000_0000] = 1
532
+ end
533
+ assert_raise RangeError do
534
+ m[-1] = 1
535
+ end
536
+
537
+ m = Google::Protobuf::Map.new(:uint64, :int32)
538
+ m[0x8000_0000_0000_0000] = 1
539
+ assert_raise RangeError do
540
+ m[0x1_0000_0000_0000_0000] = 1
541
+ end
542
+ assert_raise RangeError do
543
+ m[-1] = 1
544
+ end
545
+
546
+ m = Google::Protobuf::Map.new(:bool, :int32)
547
+ m[true] = 1
548
+ m[false] = 2
549
+ assert_raise TypeError do
550
+ m[1] = 1
551
+ end
552
+ assert_raise TypeError do
553
+ m["asdf"] = 1
554
+ end
555
+
556
+ m = Google::Protobuf::Map.new(:string, :int32)
557
+ m["asdf"] = 1
558
+ assert_raise TypeError do
559
+ m[1] = 1
560
+ end
561
+ assert_raise TypeError do
562
+ bytestring = ["FFFF"].pack("H*")
563
+ m[bytestring] = 1
564
+ end
565
+
566
+ m = Google::Protobuf::Map.new(:bytes, :int32)
567
+ bytestring = ["FFFF"].pack("H*")
568
+ m[bytestring] = 1
569
+ assert_raise TypeError do
570
+ m["asdf"] = 1
571
+ end
572
+ assert_raise TypeError do
573
+ m[1] = 1
574
+ end
575
+ end
576
+
577
+ def test_map_msg_enum_valuetypes
578
+ m = Google::Protobuf::Map.new(:string, :message, TestMessage)
579
+ m["asdf"] = TestMessage.new
580
+ assert_raise TypeError do
581
+ m["jkl;"] = TestMessage2.new
582
+ end
583
+
584
+ m = Google::Protobuf::Map.new(
585
+ :string, :message, TestMessage,
586
+ { "a" => TestMessage.new(:optional_int32 => 42),
587
+ "b" => TestMessage.new(:optional_int32 => 84) })
588
+ assert m.length == 2
589
+ assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84]
590
+
591
+ m = Google::Protobuf::Map.new(:string, :enum, TestEnum,
592
+ { "x" => :A, "y" => :B, "z" => :C })
593
+ assert m.length == 3
594
+ assert m["z"] == :C
595
+ m["z"] = 2
596
+ assert m["z"] == :B
597
+ m["z"] = 4
598
+ assert m["z"] == 4
599
+ assert_raise RangeError do
600
+ m["z"] = :Z
601
+ end
602
+ assert_raise TypeError do
603
+ m["z"] = "z"
604
+ end
605
+ end
606
+
607
+ def test_map_dup_deep_copy
608
+ m = Google::Protobuf::Map.new(
609
+ :string, :message, TestMessage,
610
+ { "a" => TestMessage.new(:optional_int32 => 42),
611
+ "b" => TestMessage.new(:optional_int32 => 84) })
612
+
613
+ m2 = m.dup
614
+ assert m == m2
615
+ assert m.object_id != m2.object_id
616
+ assert m["a"].object_id == m2["a"].object_id
617
+ assert m["b"].object_id == m2["b"].object_id
618
+
619
+ m2 = Google::Protobuf.deep_copy(m)
620
+ assert m == m2
621
+ assert m.object_id != m2.object_id
622
+ assert m["a"].object_id != m2["a"].object_id
623
+ assert m["b"].object_id != m2["b"].object_id
624
+ end
625
+
626
+ def test_map_field
627
+ m = MapMessage.new
628
+ assert m.map_string_int32 == {}
629
+ assert m.map_string_msg == {}
630
+
631
+ m = MapMessage.new(
632
+ :map_string_int32 => {"a" => 1, "b" => 2},
633
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
634
+ "b" => TestMessage2.new(:foo => 2)})
635
+ assert m.map_string_int32.keys.sort == ["a", "b"]
636
+ assert m.map_string_int32["a"] == 1
637
+ assert m.map_string_msg["b"].foo == 2
638
+
639
+ m.map_string_int32["c"] = 3
640
+ assert m.map_string_int32["c"] == 3
641
+ m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
642
+ assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
643
+ m.map_string_msg.delete("b")
644
+ m.map_string_msg.delete("c")
645
+ assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
646
+
647
+ assert_raise TypeError do
648
+ m.map_string_msg["e"] = TestMessage.new # wrong value type
649
+ end
650
+ # ensure nothing was added by the above
651
+ assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
652
+
653
+ m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
654
+ assert_raise TypeError do
655
+ m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
656
+ end
657
+ assert_raise TypeError do
658
+ m.map_string_int32 = {}
659
+ end
660
+
661
+ assert_raise TypeError do
662
+ m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
663
+ end
664
+ end
665
+
666
+ def test_map_encode_decode
667
+ m = MapMessage.new(
668
+ :map_string_int32 => {"a" => 1, "b" => 2},
669
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
670
+ "b" => TestMessage2.new(:foo => 2)})
671
+ m2 = MapMessage.decode(MapMessage.encode(m))
672
+ assert m == m2
673
+
674
+ m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
675
+ assert m3.map_string_int32.length == 2
676
+
677
+ kv = {}
678
+ m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
679
+ assert kv == {"a" => 1, "b" => 2}
680
+
681
+ kv = {}
682
+ m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
683
+ assert kv == {"a" => TestMessage2.new(:foo => 1),
684
+ "b" => TestMessage2.new(:foo => 2)}
685
+ end
686
+
687
+ def test_oneof_descriptors
688
+ d = OneofMessage.descriptor
689
+ o = d.lookup_oneof("my_oneof")
690
+ assert o != nil
691
+ assert o.class == Google::Protobuf::OneofDescriptor
692
+ assert o.name == "my_oneof"
693
+ oneof_count = 0
694
+ d.each_oneof{ |oneof|
695
+ oneof_count += 1
696
+ assert oneof == o
697
+ }
698
+ assert oneof_count == 1
699
+ assert o.count == 4
700
+ field_names = o.map{|f| f.name}.sort
701
+ assert field_names == ["a", "b", "c", "d"]
702
+ end
703
+
704
+ def test_oneof
705
+ d = OneofMessage.new
706
+ assert d.a == ""
707
+ assert d.b == 0
708
+ assert d.c == nil
709
+ assert d.d == :Default
710
+ assert d.my_oneof == nil
711
+
712
+ d.a = "hi"
713
+ assert d.a == "hi"
714
+ assert d.b == 0
715
+ assert d.c == nil
716
+ assert d.d == :Default
717
+ assert d.my_oneof == :a
718
+
719
+ d.b = 42
720
+ assert d.a == ""
721
+ assert d.b == 42
722
+ assert d.c == nil
723
+ assert d.d == :Default
724
+ assert d.my_oneof == :b
725
+
726
+ d.c = TestMessage2.new(:foo => 100)
727
+ assert d.a == ""
728
+ assert d.b == 0
729
+ assert d.c.foo == 100
730
+ assert d.d == :Default
731
+ assert d.my_oneof == :c
732
+
733
+ d.d = :C
734
+ assert d.a == ""
735
+ assert d.b == 0
736
+ assert d.c == nil
737
+ assert d.d == :C
738
+ assert d.my_oneof == :d
739
+
740
+ d2 = OneofMessage.decode(OneofMessage.encode(d))
741
+ assert d2 == d
742
+
743
+ encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
744
+ encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
745
+ encoded_field_c = OneofMessage.encode(
746
+ OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
747
+ encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
748
+
749
+ d3 = OneofMessage.decode(
750
+ encoded_field_c + encoded_field_a + encoded_field_d)
751
+ assert d3.a == ""
752
+ assert d3.b == 0
753
+ assert d3.c == nil
754
+ assert d3.d == :B
755
+
756
+ d4 = OneofMessage.decode(
757
+ encoded_field_c + encoded_field_a + encoded_field_d +
758
+ encoded_field_c)
759
+ assert d4.a == ""
760
+ assert d4.b == 0
761
+ assert d4.c.foo == 1
762
+ assert d4.d == :Default
763
+
764
+ d5 = OneofMessage.new(:a => "hello")
765
+ assert d5.a == "hello"
766
+ d5.a = nil
767
+ assert d5.a == ""
768
+ assert OneofMessage.encode(d5) == ''
769
+ assert d5.my_oneof == nil
770
+ end
771
+
772
+ def test_enum_field
773
+ m = TestMessage.new
774
+ assert m.optional_enum == :Default
775
+ m.optional_enum = :A
776
+ assert m.optional_enum == :A
777
+ assert_raise RangeError do
778
+ m.optional_enum = :ASDF
779
+ end
780
+ m.optional_enum = 1
781
+ assert m.optional_enum == :A
782
+ m.optional_enum = 100
783
+ assert m.optional_enum == 100
784
+ end
785
+
786
+ def test_dup
787
+ m = TestMessage.new
788
+ m.optional_string = "hello"
789
+ m.optional_int32 = 42
790
+ tm1 = TestMessage2.new(:foo => 100)
791
+ tm2 = TestMessage2.new(:foo => 200)
792
+ m.repeated_msg.push tm1
793
+ assert m.repeated_msg[-1] == tm1
794
+ m.repeated_msg.push tm2
795
+ assert m.repeated_msg[-1] == tm2
796
+ m2 = m.dup
797
+ assert m == m2
798
+ m.optional_int32 += 1
799
+ assert m != m2
800
+ assert m.repeated_msg[0] == m2.repeated_msg[0]
801
+ assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
802
+ end
803
+
804
+ def test_deep_copy
805
+ m = TestMessage.new(:optional_int32 => 42,
806
+ :repeated_msg => [TestMessage2.new(:foo => 100)])
807
+ m2 = Google::Protobuf.deep_copy(m)
808
+ assert m == m2
809
+ assert m.repeated_msg == m2.repeated_msg
810
+ assert m.repeated_msg.object_id != m2.repeated_msg.object_id
811
+ assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
812
+ end
813
+
814
+ def test_eq
815
+ m = TestMessage.new(:optional_int32 => 42,
816
+ :repeated_int32 => [1, 2, 3])
817
+ m2 = TestMessage.new(:optional_int32 => 43,
818
+ :repeated_int32 => [1, 2, 3])
819
+ assert m != m2
820
+ end
821
+
822
+ def test_enum_lookup
823
+ assert TestEnum::A == 1
824
+ assert TestEnum::B == 2
825
+ assert TestEnum::C == 3
826
+
827
+ assert TestEnum::lookup(1) == :A
828
+ assert TestEnum::lookup(2) == :B
829
+ assert TestEnum::lookup(3) == :C
830
+
831
+ assert TestEnum::resolve(:A) == 1
832
+ assert TestEnum::resolve(:B) == 2
833
+ assert TestEnum::resolve(:C) == 3
834
+ end
835
+
836
+ def test_parse_serialize
837
+ m = TestMessage.new(:optional_int32 => 42,
838
+ :optional_string => "hello world",
839
+ :optional_enum => :B,
840
+ :repeated_string => ["a", "b", "c"],
841
+ :repeated_int32 => [42, 43, 44],
842
+ :repeated_enum => [:A, :B, :C, 100],
843
+ :repeated_msg => [TestMessage2.new(:foo => 1),
844
+ TestMessage2.new(:foo => 2)])
845
+ data = TestMessage.encode m
846
+ m2 = TestMessage.decode data
847
+ assert m == m2
848
+
849
+ data = Google::Protobuf.encode m
850
+ m2 = Google::Protobuf.decode(TestMessage, data)
851
+ assert m == m2
852
+ end
853
+
854
+ def test_encode_decode_helpers
855
+ m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
856
+ json = m.to_json
857
+ m2 = TestMessage.decode_json(json)
858
+ assert m2.optional_string == 'foo'
859
+ assert m2.repeated_string == ['bar1', 'bar2']
860
+
861
+ proto = m.to_proto
862
+ m2 = TestMessage.decode(proto)
863
+ assert m2.optional_string == 'foo'
864
+ assert m2.repeated_string == ['bar1', 'bar2']
865
+ end
866
+
867
+ def test_protobuf_encode_decode_helpers
868
+ m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
869
+ encoded_msg = Google::Protobuf.encode(m)
870
+ assert_equal m.to_proto, encoded_msg
871
+
872
+ decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg)
873
+ assert_equal TestMessage.decode(m.to_proto), decoded_msg
874
+ end
875
+
876
+ def test_protobuf_encode_decode_json_helpers
877
+ m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
878
+ encoded_msg = Google::Protobuf.encode_json(m)
879
+ assert_equal m.to_json, encoded_msg
880
+
881
+ decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg)
882
+ assert_equal TestMessage.decode_json(m.to_json), decoded_msg
883
+ end
884
+
885
+ def test_to_h
886
+ m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
887
+ expected_result = {
888
+ :optional_bool=>true,
889
+ :optional_bytes=>"",
890
+ :optional_double=>-10.100001,
891
+ :optional_enum=>:Default,
892
+ :optional_float=>0.0,
893
+ :optional_int32=>0,
894
+ :optional_int64=>0,
895
+ :optional_msg=>nil,
896
+ :optional_string=>"foo",
897
+ :optional_uint32=>0,
898
+ :optional_uint64=>0,
899
+ :repeated_bool=>[],
900
+ :repeated_bytes=>[],
901
+ :repeated_double=>[],
902
+ :repeated_enum=>[],
903
+ :repeated_float=>[],
904
+ :repeated_int32=>[],
905
+ :repeated_int64=>[],
906
+ :repeated_msg=>[],
907
+ :repeated_string=>["bar1", "bar2"],
908
+ :repeated_uint32=>[],
909
+ :repeated_uint64=>[]
910
+ }
911
+ assert_equal expected_result, m.to_h
912
+ end
913
+
914
+
915
+ def test_def_errors
916
+ s = Google::Protobuf::DescriptorPool.new
917
+ assert_raise TypeError do
918
+ s.build do
919
+ # enum with no default (integer value 0)
920
+ add_enum "MyEnum" do
921
+ value :A, 1
922
+ end
923
+ end
924
+ end
925
+ assert_raise TypeError do
926
+ s.build do
927
+ # message with required field (unsupported in proto3)
928
+ add_message "MyMessage" do
929
+ required :foo, :int32, 1
930
+ end
931
+ end
932
+ end
933
+ end
934
+
935
+ def test_corecursive
936
+ # just be sure that we can instantiate types with corecursive field-type
937
+ # references.
938
+ m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
939
+ assert Recursive1.descriptor.lookup("foo").subtype ==
940
+ Recursive2.descriptor
941
+ assert Recursive2.descriptor.lookup("foo").subtype ==
942
+ Recursive1.descriptor
943
+
944
+ serialized = Recursive1.encode(m)
945
+ m2 = Recursive1.decode(serialized)
946
+ assert m == m2
947
+ end
948
+
949
+ def test_serialize_cycle
950
+ m = Recursive1.new(:foo => Recursive2.new)
951
+ m.foo.foo = m
952
+ assert_raise RuntimeError do
953
+ serialized = Recursive1.encode(m)
954
+ end
955
+ end
956
+
957
+ def test_bad_field_names
958
+ m = BadFieldNames.new(:dup => 1, :class => 2)
959
+ m2 = m.dup
960
+ assert m == m2
961
+ assert m['dup'] == 1
962
+ assert m['class'] == 2
963
+ m['dup'] = 3
964
+ assert m['dup'] == 3
965
+ m['a.b'] = 4
966
+ assert m['a.b'] == 4
967
+ end
968
+
969
+ def test_int_ranges
970
+ m = TestMessage.new
971
+
972
+ m.optional_int32 = 0
973
+ m.optional_int32 = -0x8000_0000
974
+ m.optional_int32 = +0x7fff_ffff
975
+ m.optional_int32 = 1.0
976
+ m.optional_int32 = -1.0
977
+ m.optional_int32 = 2e9
978
+ assert_raise RangeError do
979
+ m.optional_int32 = -0x8000_0001
980
+ end
981
+ assert_raise RangeError do
982
+ m.optional_int32 = +0x8000_0000
983
+ end
984
+ assert_raise RangeError do
985
+ m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
986
+ end
987
+ assert_raise RangeError do
988
+ m.optional_int32 = 1e12
989
+ end
990
+ assert_raise RangeError do
991
+ m.optional_int32 = 1.5
992
+ end
993
+
994
+ m.optional_uint32 = 0
995
+ m.optional_uint32 = +0xffff_ffff
996
+ m.optional_uint32 = 1.0
997
+ m.optional_uint32 = 4e9
998
+ assert_raise RangeError do
999
+ m.optional_uint32 = -1
1000
+ end
1001
+ assert_raise RangeError do
1002
+ m.optional_uint32 = -1.5
1003
+ end
1004
+ assert_raise RangeError do
1005
+ m.optional_uint32 = -1.5e12
1006
+ end
1007
+ assert_raise RangeError do
1008
+ m.optional_uint32 = -0x1000_0000_0000_0000
1009
+ end
1010
+ assert_raise RangeError do
1011
+ m.optional_uint32 = +0x1_0000_0000
1012
+ end
1013
+ assert_raise RangeError do
1014
+ m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1015
+ end
1016
+ assert_raise RangeError do
1017
+ m.optional_uint32 = 1e12
1018
+ end
1019
+ assert_raise RangeError do
1020
+ m.optional_uint32 = 1.5
1021
+ end
1022
+
1023
+ m.optional_int64 = 0
1024
+ m.optional_int64 = -0x8000_0000_0000_0000
1025
+ m.optional_int64 = +0x7fff_ffff_ffff_ffff
1026
+ m.optional_int64 = 1.0
1027
+ m.optional_int64 = -1.0
1028
+ m.optional_int64 = 8e18
1029
+ m.optional_int64 = -8e18
1030
+ assert_raise RangeError do
1031
+ m.optional_int64 = -0x8000_0000_0000_0001
1032
+ end
1033
+ assert_raise RangeError do
1034
+ m.optional_int64 = +0x8000_0000_0000_0000
1035
+ end
1036
+ assert_raise RangeError do
1037
+ m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1038
+ end
1039
+ assert_raise RangeError do
1040
+ m.optional_int64 = 1e50
1041
+ end
1042
+ assert_raise RangeError do
1043
+ m.optional_int64 = 1.5
1044
+ end
1045
+
1046
+ m.optional_uint64 = 0
1047
+ m.optional_uint64 = +0xffff_ffff_ffff_ffff
1048
+ m.optional_uint64 = 1.0
1049
+ m.optional_uint64 = 16e18
1050
+ assert_raise RangeError do
1051
+ m.optional_uint64 = -1
1052
+ end
1053
+ assert_raise RangeError do
1054
+ m.optional_uint64 = -1.5
1055
+ end
1056
+ assert_raise RangeError do
1057
+ m.optional_uint64 = -1.5e12
1058
+ end
1059
+ assert_raise RangeError do
1060
+ m.optional_uint64 = -0x1_0000_0000_0000_0000
1061
+ end
1062
+ assert_raise RangeError do
1063
+ m.optional_uint64 = +0x1_0000_0000_0000_0000
1064
+ end
1065
+ assert_raise RangeError do
1066
+ m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1067
+ end
1068
+ assert_raise RangeError do
1069
+ m.optional_uint64 = 1e50
1070
+ end
1071
+ assert_raise RangeError do
1072
+ m.optional_uint64 = 1.5
1073
+ end
1074
+ end
1075
+
1076
+ def test_stress_test
1077
+ m = TestMessage.new
1078
+ m.optional_int32 = 42
1079
+ m.optional_int64 = 0x100000000
1080
+ m.optional_string = "hello world"
1081
+ 10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
1082
+ 10.times do m.repeated_string.push "hello world" end
1083
+
1084
+ data = TestMessage.encode(m)
1085
+
1086
+ l = 0
1087
+ 10_000.times do
1088
+ m = TestMessage.decode(data)
1089
+ data_new = TestMessage.encode(m)
1090
+ assert data_new == data
1091
+ data = data_new
1092
+ end
1093
+ end
1094
+
1095
+ def test_reflection
1096
+ m = TestMessage.new(:optional_int32 => 1234)
1097
+ msgdef = m.class.descriptor
1098
+ assert msgdef.class == Google::Protobuf::Descriptor
1099
+ assert msgdef.any? {|field| field.name == "optional_int32"}
1100
+ optional_int32 = msgdef.lookup "optional_int32"
1101
+ assert optional_int32.class == Google::Protobuf::FieldDescriptor
1102
+ assert optional_int32 != nil
1103
+ assert optional_int32.name == "optional_int32"
1104
+ assert optional_int32.type == :int32
1105
+ optional_int32.set(m, 5678)
1106
+ assert m.optional_int32 == 5678
1107
+ m.optional_int32 = 1000
1108
+ assert optional_int32.get(m) == 1000
1109
+
1110
+ optional_msg = msgdef.lookup "optional_msg"
1111
+ assert optional_msg.subtype == TestMessage2.descriptor
1112
+
1113
+ optional_msg.set(m, optional_msg.subtype.msgclass.new)
1114
+
1115
+ assert msgdef.msgclass == TestMessage
1116
+
1117
+ optional_enum = msgdef.lookup "optional_enum"
1118
+ assert optional_enum.subtype == TestEnum.descriptor
1119
+ assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
1120
+ optional_enum.subtype.each do |k, v|
1121
+ # set with integer, check resolution to symbolic name
1122
+ optional_enum.set(m, v)
1123
+ assert optional_enum.get(m) == k
1124
+ end
1125
+ end
1126
+
1127
+ def test_json
1128
+ # TODO: Fix JSON in JRuby version.
1129
+ return if RUBY_PLATFORM == "java"
1130
+ m = TestMessage.new(:optional_int32 => 1234,
1131
+ :optional_int64 => -0x1_0000_0000,
1132
+ :optional_uint32 => 0x8000_0000,
1133
+ :optional_uint64 => 0xffff_ffff_ffff_ffff,
1134
+ :optional_bool => true,
1135
+ :optional_float => 1.0,
1136
+ :optional_double => -1e100,
1137
+ :optional_string => "Test string",
1138
+ :optional_bytes => ["FFFFFFFF"].pack('H*'),
1139
+ :optional_msg => TestMessage2.new(:foo => 42),
1140
+ :repeated_int32 => [1, 2, 3, 4],
1141
+ :repeated_string => ["a", "b", "c"],
1142
+ :repeated_bool => [true, false, true, false],
1143
+ :repeated_msg => [TestMessage2.new(:foo => 1),
1144
+ TestMessage2.new(:foo => 2)])
1145
+
1146
+ json_text = TestMessage.encode_json(m)
1147
+ m2 = TestMessage.decode_json(json_text)
1148
+ assert m == m2
1149
+
1150
+ # Crash case from GitHub issue 283.
1151
+ bar = Bar.new(msg: "bar")
1152
+ baz1 = Baz.new(msg: "baz")
1153
+ baz2 = Baz.new(msg: "quux")
1154
+ Foo.encode_json(Foo.new)
1155
+ Foo.encode_json(Foo.new(bar: bar))
1156
+ Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2]))
1157
+ end
1158
+
1159
+ def test_json_maps
1160
+ # TODO: Fix JSON in JRuby version.
1161
+ return if RUBY_PLATFORM == "java"
1162
+ m = MapMessage.new(:map_string_int32 => {"a" => 1})
1163
+ expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}'
1164
+ expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
1165
+ assert MapMessage.encode_json(m) == expected
1166
+
1167
+ json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
1168
+ assert json == expected_preserve
1169
+
1170
+ m2 = MapMessage.decode_json(MapMessage.encode_json(m))
1171
+ assert m == m2
1172
+ end
1173
+ end
1174
+ end