google-protobuf 3.0.0.alpha.5.0.3-x86-linux

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Binary file
Binary file
Binary file
Binary file
@@ -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, :combination, :compact, :count, :cycle,
73
+ :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
data/tests/basic.rb ADDED
@@ -0,0 +1,1140 @@
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_type_errors
195
+ m = TestMessage.new
196
+ assert_raise TypeError do
197
+ m.optional_int32 = "hello"
198
+ end
199
+ assert_raise TypeError do
200
+ m.optional_string = 42
201
+ end
202
+ assert_raise TypeError do
203
+ m.optional_string = nil
204
+ end
205
+ assert_raise TypeError do
206
+ m.optional_bool = 42
207
+ end
208
+ assert_raise TypeError do
209
+ m.optional_msg = TestMessage.new # expects TestMessage2
210
+ end
211
+
212
+ assert_raise TypeError do
213
+ m.repeated_int32 = [] # needs RepeatedField
214
+ end
215
+
216
+ assert_raise TypeError do
217
+ m.repeated_int32.push "hello"
218
+ end
219
+
220
+ assert_raise TypeError do
221
+ m.repeated_msg.push TestMessage.new
222
+ end
223
+ end
224
+
225
+ def test_string_encoding
226
+ m = TestMessage.new
227
+
228
+ # Assigning a normal (ASCII or UTF8) string to a bytes field, or
229
+ # ASCII-8BIT to a string field, raises an error.
230
+ assert_raise TypeError do
231
+ m.optional_bytes = "Test string ASCII".encode!('ASCII')
232
+ end
233
+ assert_raise TypeError do
234
+ m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
235
+ end
236
+ assert_raise TypeError do
237
+ m.optional_string = ["FFFF"].pack('H*')
238
+ end
239
+
240
+ # "Ordinary" use case.
241
+ m.optional_bytes = ["FFFF"].pack('H*')
242
+ m.optional_string = "\u0100"
243
+
244
+ # strings are mutable so we can do this, but serialize should catch it.
245
+ m.optional_string = "asdf".encode!('UTF-8')
246
+ m.optional_string.encode!('ASCII-8BIT')
247
+ assert_raise TypeError do
248
+ data = TestMessage.encode(m)
249
+ end
250
+ end
251
+
252
+ def test_rptfield_int32
253
+ l = Google::Protobuf::RepeatedField.new(:int32)
254
+ assert l.count == 0
255
+ l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
256
+ assert l.count == 3
257
+ assert_equal [1, 2, 3], l
258
+ assert_equal l, [1, 2, 3]
259
+ l.push 4
260
+ assert l == [1, 2, 3, 4]
261
+ dst_list = []
262
+ l.each { |val| dst_list.push val }
263
+ assert dst_list == [1, 2, 3, 4]
264
+ assert l.to_a == [1, 2, 3, 4]
265
+ assert l[0] == 1
266
+ assert l[3] == 4
267
+ l[0] = 5
268
+ assert l == [5, 2, 3, 4]
269
+
270
+ l2 = l.dup
271
+ assert l == l2
272
+ assert l.object_id != l2.object_id
273
+ l2.push 6
274
+ assert l.count == 4
275
+ assert l2.count == 5
276
+
277
+ assert l.inspect == '[5, 2, 3, 4]'
278
+
279
+ l.concat([7, 8, 9])
280
+ assert l == [5, 2, 3, 4, 7, 8, 9]
281
+ assert l.pop == 9
282
+ assert l == [5, 2, 3, 4, 7, 8]
283
+
284
+ assert_raise TypeError do
285
+ m = TestMessage.new
286
+ l.push m
287
+ end
288
+
289
+ m = TestMessage.new
290
+ m.repeated_int32 = l
291
+ assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
292
+ assert m.repeated_int32.object_id == l.object_id
293
+ l.push 42
294
+ assert m.repeated_int32.pop == 42
295
+
296
+ l3 = l + l.dup
297
+ assert l3.count == l.count * 2
298
+ l.count.times do |i|
299
+ assert l3[i] == l[i]
300
+ assert l3[l.count + i] == l[i]
301
+ end
302
+
303
+ l.clear
304
+ assert l.count == 0
305
+ l += [1, 2, 3, 4]
306
+ l.replace([5, 6, 7, 8])
307
+ assert l == [5, 6, 7, 8]
308
+
309
+ l4 = Google::Protobuf::RepeatedField.new(:int32)
310
+ l4[5] = 42
311
+ assert l4 == [0, 0, 0, 0, 0, 42]
312
+
313
+ l4 << 100
314
+ assert l4 == [0, 0, 0, 0, 0, 42, 100]
315
+ l4 << 101 << 102
316
+ assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
317
+ end
318
+
319
+ def test_parent_rptfield
320
+ #make sure we set the RepeatedField and can add to it
321
+ m = TestMessage.new
322
+ assert m.repeated_string == []
323
+ m.repeated_string << 'ok'
324
+ m.repeated_string.push('ok2')
325
+ assert m.repeated_string == ['ok', 'ok2']
326
+ m.repeated_string += ['ok3']
327
+ assert m.repeated_string == ['ok', 'ok2', 'ok3']
328
+ end
329
+
330
+ def test_rptfield_msg
331
+ l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
332
+ l.push TestMessage.new
333
+ assert l.count == 1
334
+ assert_raise TypeError do
335
+ l.push TestMessage2.new
336
+ end
337
+ assert_raise TypeError do
338
+ l.push 42
339
+ end
340
+
341
+ l2 = l.dup
342
+ assert l2[0] == l[0]
343
+ assert l2[0].object_id == l[0].object_id
344
+
345
+ l2 = Google::Protobuf.deep_copy(l)
346
+ assert l2[0] == l[0]
347
+ assert l2[0].object_id != l[0].object_id
348
+
349
+ l3 = l + l2
350
+ assert l3.count == 2
351
+ assert l3[0] == l[0]
352
+ assert l3[1] == l2[0]
353
+ l3[0].optional_int32 = 1000
354
+ assert l[0].optional_int32 == 1000
355
+
356
+ new_msg = TestMessage.new(:optional_int32 => 200)
357
+ l4 = l + [new_msg]
358
+ assert l4.count == 2
359
+ new_msg.optional_int32 = 1000
360
+ assert l4[1].optional_int32 == 1000
361
+ end
362
+
363
+ def test_rptfield_enum
364
+ l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
365
+ l.push :A
366
+ l.push :B
367
+ l.push :C
368
+ assert l.count == 3
369
+ assert_raise RangeError do
370
+ l.push :D
371
+ end
372
+ assert l[0] == :A
373
+
374
+ l.push 4
375
+ assert l[3] == 4
376
+ end
377
+
378
+ def test_rptfield_initialize
379
+ assert_raise ArgumentError do
380
+ l = Google::Protobuf::RepeatedField.new
381
+ end
382
+ assert_raise ArgumentError do
383
+ l = Google::Protobuf::RepeatedField.new(:message)
384
+ end
385
+ assert_raise ArgumentError do
386
+ l = Google::Protobuf::RepeatedField.new([1, 2, 3])
387
+ end
388
+ assert_raise ArgumentError do
389
+ l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
390
+ end
391
+ end
392
+
393
+ def test_rptfield_array_ducktyping
394
+ l = Google::Protobuf::RepeatedField.new(:int32)
395
+ length_methods = %w(count length size)
396
+ length_methods.each do |lm|
397
+ assert l.send(lm) == 0
398
+ end
399
+ # out of bounds returns a nil
400
+ assert l[0] == nil
401
+ assert l[1] == nil
402
+ assert l[-1] == nil
403
+ l.push 4
404
+ length_methods.each do |lm|
405
+ assert l.send(lm) == 1
406
+ end
407
+ assert l[0] == 4
408
+ assert l[1] == nil
409
+ assert l[-1] == 4
410
+ assert l[-2] == nil
411
+
412
+ l.push 2
413
+ length_methods.each do |lm|
414
+ assert l.send(lm) == 2
415
+ end
416
+ assert l[0] == 4
417
+ assert l[1] == 2
418
+ assert l[2] == nil
419
+ assert l[-1] == 2
420
+ assert l[-2] == 4
421
+ assert l[-3] == nil
422
+
423
+ #adding out of scope will backfill with empty objects
424
+ end
425
+
426
+ def test_map_basic
427
+ # allowed key types:
428
+ # :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
429
+
430
+ m = Google::Protobuf::Map.new(:string, :int32)
431
+ m["asdf"] = 1
432
+ assert m["asdf"] == 1
433
+ m["jkl;"] = 42
434
+ assert m == { "jkl;" => 42, "asdf" => 1 }
435
+ assert m.has_key?("asdf")
436
+ assert !m.has_key?("qwerty")
437
+ assert m.length == 2
438
+
439
+ m2 = m.dup
440
+ assert m == m2
441
+ assert m.hash != 0
442
+ assert m.hash == m2.hash
443
+
444
+ collected = {}
445
+ m.each { |k,v| collected[v] = k }
446
+ assert collected == { 42 => "jkl;", 1 => "asdf" }
447
+
448
+ assert m.delete("asdf") == 1
449
+ assert !m.has_key?("asdf")
450
+ assert m["asdf"] == nil
451
+ assert !m.has_key?("asdf")
452
+
453
+ # We only assert on inspect value when there is one map entry because the
454
+ # order in which elements appear is unspecified (depends on the internal
455
+ # hash function). We don't want a brittle test.
456
+ assert m.inspect == "{\"jkl;\"=>42}"
457
+
458
+ assert m.keys == ["jkl;"]
459
+ assert m.values == [42]
460
+
461
+ m.clear
462
+ assert m.length == 0
463
+ assert m == {}
464
+
465
+ assert_raise TypeError do
466
+ m[1] = 1
467
+ end
468
+ assert_raise RangeError do
469
+ m["asdf"] = 0x1_0000_0000
470
+ end
471
+ end
472
+
473
+ def test_map_ctor
474
+ m = Google::Protobuf::Map.new(:string, :int32,
475
+ {"a" => 1, "b" => 2, "c" => 3})
476
+ assert m == {"a" => 1, "c" => 3, "b" => 2}
477
+ end
478
+
479
+ def test_map_keytypes
480
+ m = Google::Protobuf::Map.new(:int32, :int32)
481
+ m[1] = 42
482
+ m[-1] = 42
483
+ assert_raise RangeError do
484
+ m[0x8000_0000] = 1
485
+ end
486
+ assert_raise TypeError do
487
+ m["asdf"] = 1
488
+ end
489
+
490
+ m = Google::Protobuf::Map.new(:int64, :int32)
491
+ m[0x1000_0000_0000_0000] = 1
492
+ assert_raise RangeError do
493
+ m[0x1_0000_0000_0000_0000] = 1
494
+ end
495
+ assert_raise TypeError do
496
+ m["asdf"] = 1
497
+ end
498
+
499
+ m = Google::Protobuf::Map.new(:uint32, :int32)
500
+ m[0x8000_0000] = 1
501
+ assert_raise RangeError do
502
+ m[0x1_0000_0000] = 1
503
+ end
504
+ assert_raise RangeError do
505
+ m[-1] = 1
506
+ end
507
+
508
+ m = Google::Protobuf::Map.new(:uint64, :int32)
509
+ m[0x8000_0000_0000_0000] = 1
510
+ assert_raise RangeError do
511
+ m[0x1_0000_0000_0000_0000] = 1
512
+ end
513
+ assert_raise RangeError do
514
+ m[-1] = 1
515
+ end
516
+
517
+ m = Google::Protobuf::Map.new(:bool, :int32)
518
+ m[true] = 1
519
+ m[false] = 2
520
+ assert_raise TypeError do
521
+ m[1] = 1
522
+ end
523
+ assert_raise TypeError do
524
+ m["asdf"] = 1
525
+ end
526
+
527
+ m = Google::Protobuf::Map.new(:string, :int32)
528
+ m["asdf"] = 1
529
+ assert_raise TypeError do
530
+ m[1] = 1
531
+ end
532
+ assert_raise TypeError do
533
+ bytestring = ["FFFF"].pack("H*")
534
+ m[bytestring] = 1
535
+ end
536
+
537
+ m = Google::Protobuf::Map.new(:bytes, :int32)
538
+ bytestring = ["FFFF"].pack("H*")
539
+ m[bytestring] = 1
540
+ assert_raise TypeError do
541
+ m["asdf"] = 1
542
+ end
543
+ assert_raise TypeError do
544
+ m[1] = 1
545
+ end
546
+ end
547
+
548
+ def test_map_msg_enum_valuetypes
549
+ m = Google::Protobuf::Map.new(:string, :message, TestMessage)
550
+ m["asdf"] = TestMessage.new
551
+ assert_raise TypeError do
552
+ m["jkl;"] = TestMessage2.new
553
+ end
554
+
555
+ m = Google::Protobuf::Map.new(
556
+ :string, :message, TestMessage,
557
+ { "a" => TestMessage.new(:optional_int32 => 42),
558
+ "b" => TestMessage.new(:optional_int32 => 84) })
559
+ assert m.length == 2
560
+ assert m.values.map{|msg| msg.optional_int32}.sort == [42, 84]
561
+
562
+ m = Google::Protobuf::Map.new(:string, :enum, TestEnum,
563
+ { "x" => :A, "y" => :B, "z" => :C })
564
+ assert m.length == 3
565
+ assert m["z"] == :C
566
+ m["z"] = 2
567
+ assert m["z"] == :B
568
+ m["z"] = 4
569
+ assert m["z"] == 4
570
+ assert_raise RangeError do
571
+ m["z"] = :Z
572
+ end
573
+ assert_raise TypeError do
574
+ m["z"] = "z"
575
+ end
576
+ end
577
+
578
+ def test_map_dup_deep_copy
579
+ m = Google::Protobuf::Map.new(
580
+ :string, :message, TestMessage,
581
+ { "a" => TestMessage.new(:optional_int32 => 42),
582
+ "b" => TestMessage.new(:optional_int32 => 84) })
583
+
584
+ m2 = m.dup
585
+ assert m == m2
586
+ assert m.object_id != m2.object_id
587
+ assert m["a"].object_id == m2["a"].object_id
588
+ assert m["b"].object_id == m2["b"].object_id
589
+
590
+ m2 = Google::Protobuf.deep_copy(m)
591
+ assert m == m2
592
+ assert m.object_id != m2.object_id
593
+ assert m["a"].object_id != m2["a"].object_id
594
+ assert m["b"].object_id != m2["b"].object_id
595
+ end
596
+
597
+ def test_map_field
598
+ m = MapMessage.new
599
+ assert m.map_string_int32 == {}
600
+ assert m.map_string_msg == {}
601
+
602
+ m = MapMessage.new(
603
+ :map_string_int32 => {"a" => 1, "b" => 2},
604
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
605
+ "b" => TestMessage2.new(:foo => 2)})
606
+ assert m.map_string_int32.keys.sort == ["a", "b"]
607
+ assert m.map_string_int32["a"] == 1
608
+ assert m.map_string_msg["b"].foo == 2
609
+
610
+ m.map_string_int32["c"] = 3
611
+ assert m.map_string_int32["c"] == 3
612
+ m.map_string_msg["c"] = TestMessage2.new(:foo => 3)
613
+ assert m.map_string_msg["c"] == TestMessage2.new(:foo => 3)
614
+ m.map_string_msg.delete("b")
615
+ m.map_string_msg.delete("c")
616
+ assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
617
+
618
+ assert_raise TypeError do
619
+ m.map_string_msg["e"] = TestMessage.new # wrong value type
620
+ end
621
+ # ensure nothing was added by the above
622
+ assert m.map_string_msg == { "a" => TestMessage2.new(:foo => 1) }
623
+
624
+ m.map_string_int32 = Google::Protobuf::Map.new(:string, :int32)
625
+ assert_raise TypeError do
626
+ m.map_string_int32 = Google::Protobuf::Map.new(:string, :int64)
627
+ end
628
+ assert_raise TypeError do
629
+ m.map_string_int32 = {}
630
+ end
631
+
632
+ assert_raise TypeError do
633
+ m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
634
+ end
635
+ end
636
+
637
+ def test_map_encode_decode
638
+ m = MapMessage.new(
639
+ :map_string_int32 => {"a" => 1, "b" => 2},
640
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
641
+ "b" => TestMessage2.new(:foo => 2)})
642
+ m2 = MapMessage.decode(MapMessage.encode(m))
643
+ assert m == m2
644
+
645
+ m3 = MapMessageWireEquiv.decode(MapMessage.encode(m))
646
+ assert m3.map_string_int32.length == 2
647
+
648
+ kv = {}
649
+ m3.map_string_int32.map { |msg| kv[msg.key] = msg.value }
650
+ assert kv == {"a" => 1, "b" => 2}
651
+
652
+ kv = {}
653
+ m3.map_string_msg.map { |msg| kv[msg.key] = msg.value }
654
+ assert kv == {"a" => TestMessage2.new(:foo => 1),
655
+ "b" => TestMessage2.new(:foo => 2)}
656
+ end
657
+
658
+ def test_oneof_descriptors
659
+ d = OneofMessage.descriptor
660
+ o = d.lookup_oneof("my_oneof")
661
+ assert o != nil
662
+ assert o.class == Google::Protobuf::OneofDescriptor
663
+ assert o.name == "my_oneof"
664
+ oneof_count = 0
665
+ d.each_oneof{ |oneof|
666
+ oneof_count += 1
667
+ assert oneof == o
668
+ }
669
+ assert oneof_count == 1
670
+ assert o.count == 4
671
+ field_names = o.map{|f| f.name}.sort
672
+ assert field_names == ["a", "b", "c", "d"]
673
+ end
674
+
675
+ def test_oneof
676
+ d = OneofMessage.new
677
+ assert d.a == nil
678
+ assert d.b == nil
679
+ assert d.c == nil
680
+ assert d.d == nil
681
+ assert d.my_oneof == nil
682
+
683
+ d.a = "hi"
684
+ assert d.a == "hi"
685
+ assert d.b == nil
686
+ assert d.c == nil
687
+ assert d.d == nil
688
+ assert d.my_oneof == :a
689
+
690
+ d.b = 42
691
+ assert d.a == nil
692
+ assert d.b == 42
693
+ assert d.c == nil
694
+ assert d.d == nil
695
+ assert d.my_oneof == :b
696
+
697
+ d.c = TestMessage2.new(:foo => 100)
698
+ assert d.a == nil
699
+ assert d.b == nil
700
+ assert d.c.foo == 100
701
+ assert d.d == nil
702
+ assert d.my_oneof == :c
703
+
704
+ d.d = :C
705
+ assert d.a == nil
706
+ assert d.b == nil
707
+ assert d.c == nil
708
+ assert d.d == :C
709
+ assert d.my_oneof == :d
710
+
711
+ d2 = OneofMessage.decode(OneofMessage.encode(d))
712
+ assert d2 == d
713
+
714
+ encoded_field_a = OneofMessage.encode(OneofMessage.new(:a => "string"))
715
+ encoded_field_b = OneofMessage.encode(OneofMessage.new(:b => 1000))
716
+ encoded_field_c = OneofMessage.encode(
717
+ OneofMessage.new(:c => TestMessage2.new(:foo => 1)))
718
+ encoded_field_d = OneofMessage.encode(OneofMessage.new(:d => :B))
719
+
720
+ d3 = OneofMessage.decode(
721
+ encoded_field_c + encoded_field_a + encoded_field_d)
722
+ assert d3.a == nil
723
+ assert d3.b == nil
724
+ assert d3.c == nil
725
+ assert d3.d == :B
726
+
727
+ d4 = OneofMessage.decode(
728
+ encoded_field_c + encoded_field_a + encoded_field_d +
729
+ encoded_field_c)
730
+ assert d4.a == nil
731
+ assert d4.b == nil
732
+ assert d4.c.foo == 1
733
+ assert d4.d == nil
734
+
735
+ d5 = OneofMessage.new(:a => "hello")
736
+ assert d5.a != nil
737
+ d5.a = nil
738
+ assert d5.a == nil
739
+ assert OneofMessage.encode(d5) == ''
740
+ assert d5.my_oneof == nil
741
+ end
742
+
743
+ def test_enum_field
744
+ m = TestMessage.new
745
+ assert m.optional_enum == :Default
746
+ m.optional_enum = :A
747
+ assert m.optional_enum == :A
748
+ assert_raise RangeError do
749
+ m.optional_enum = :ASDF
750
+ end
751
+ m.optional_enum = 1
752
+ assert m.optional_enum == :A
753
+ m.optional_enum = 100
754
+ assert m.optional_enum == 100
755
+ end
756
+
757
+ def test_dup
758
+ m = TestMessage.new
759
+ m.optional_string = "hello"
760
+ m.optional_int32 = 42
761
+ tm1 = TestMessage2.new(:foo => 100)
762
+ tm2 = TestMessage2.new(:foo => 200)
763
+ m.repeated_msg.push tm1
764
+ assert m.repeated_msg[-1] == tm1
765
+ m.repeated_msg.push tm2
766
+ assert m.repeated_msg[-1] == tm2
767
+ m2 = m.dup
768
+ assert m == m2
769
+ m.optional_int32 += 1
770
+ assert m != m2
771
+ assert m.repeated_msg[0] == m2.repeated_msg[0]
772
+ assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
773
+ end
774
+
775
+ def test_deep_copy
776
+ m = TestMessage.new(:optional_int32 => 42,
777
+ :repeated_msg => [TestMessage2.new(:foo => 100)])
778
+ m2 = Google::Protobuf.deep_copy(m)
779
+ assert m == m2
780
+ assert m.repeated_msg == m2.repeated_msg
781
+ assert m.repeated_msg.object_id != m2.repeated_msg.object_id
782
+ assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
783
+ end
784
+
785
+ def test_eq
786
+ m = TestMessage.new(:optional_int32 => 42,
787
+ :repeated_int32 => [1, 2, 3])
788
+ m2 = TestMessage.new(:optional_int32 => 43,
789
+ :repeated_int32 => [1, 2, 3])
790
+ assert m != m2
791
+ end
792
+
793
+ def test_enum_lookup
794
+ assert TestEnum::A == 1
795
+ assert TestEnum::B == 2
796
+ assert TestEnum::C == 3
797
+
798
+ assert TestEnum::lookup(1) == :A
799
+ assert TestEnum::lookup(2) == :B
800
+ assert TestEnum::lookup(3) == :C
801
+
802
+ assert TestEnum::resolve(:A) == 1
803
+ assert TestEnum::resolve(:B) == 2
804
+ assert TestEnum::resolve(:C) == 3
805
+ end
806
+
807
+ def test_parse_serialize
808
+ m = TestMessage.new(:optional_int32 => 42,
809
+ :optional_string => "hello world",
810
+ :optional_enum => :B,
811
+ :repeated_string => ["a", "b", "c"],
812
+ :repeated_int32 => [42, 43, 44],
813
+ :repeated_enum => [:A, :B, :C, 100],
814
+ :repeated_msg => [TestMessage2.new(:foo => 1),
815
+ TestMessage2.new(:foo => 2)])
816
+ data = TestMessage.encode m
817
+ m2 = TestMessage.decode data
818
+ assert m == m2
819
+
820
+ data = Google::Protobuf.encode m
821
+ m2 = Google::Protobuf.decode(TestMessage, data)
822
+ assert m == m2
823
+ end
824
+
825
+ def test_encode_decode_helpers
826
+ m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
827
+ json = m.to_json
828
+ m2 = TestMessage.decode_json(json)
829
+ assert m2.optional_string == 'foo'
830
+ assert m2.repeated_string == ['bar1', 'bar2']
831
+
832
+ proto = m.to_proto
833
+ m2 = TestMessage.decode(proto)
834
+ assert m2.optional_string == 'foo'
835
+ assert m2.repeated_string == ['bar1', 'bar2']
836
+ end
837
+
838
+ def test_protobuf_encode_decode_helpers
839
+ m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
840
+ encoded_msg = Google::Protobuf.encode(m)
841
+ assert_equal m.to_proto, encoded_msg
842
+
843
+ decoded_msg = Google::Protobuf.decode(TestMessage, encoded_msg)
844
+ assert_equal TestMessage.decode(m.to_proto), decoded_msg
845
+ end
846
+
847
+ def test_protobuf_encode_decode_json_helpers
848
+ m = TestMessage.new(:optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
849
+ encoded_msg = Google::Protobuf.encode_json(m)
850
+ assert_equal m.to_json, encoded_msg
851
+
852
+ decoded_msg = Google::Protobuf.decode_json(TestMessage, encoded_msg)
853
+ assert_equal TestMessage.decode_json(m.to_json), decoded_msg
854
+ end
855
+
856
+ def test_to_h
857
+ m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
858
+ expected_result = {
859
+ :optional_bool=>true,
860
+ :optional_bytes=>"",
861
+ :optional_double=>-10.100001,
862
+ :optional_enum=>:Default,
863
+ :optional_float=>0.0,
864
+ :optional_int32=>0,
865
+ :optional_int64=>0,
866
+ :optional_msg=>nil,
867
+ :optional_string=>"foo",
868
+ :optional_uint32=>0,
869
+ :optional_uint64=>0,
870
+ :repeated_bool=>[],
871
+ :repeated_bytes=>[],
872
+ :repeated_double=>[],
873
+ :repeated_enum=>[],
874
+ :repeated_float=>[],
875
+ :repeated_int32=>[],
876
+ :repeated_int64=>[],
877
+ :repeated_msg=>[],
878
+ :repeated_string=>["bar1", "bar2"],
879
+ :repeated_uint32=>[],
880
+ :repeated_uint64=>[]
881
+ }
882
+ assert_equal expected_result, m.to_h
883
+ end
884
+
885
+
886
+ def test_def_errors
887
+ s = Google::Protobuf::DescriptorPool.new
888
+ assert_raise TypeError do
889
+ s.build do
890
+ # enum with no default (integer value 0)
891
+ add_enum "MyEnum" do
892
+ value :A, 1
893
+ end
894
+ end
895
+ end
896
+ assert_raise TypeError do
897
+ s.build do
898
+ # message with required field (unsupported in proto3)
899
+ add_message "MyMessage" do
900
+ required :foo, :int32, 1
901
+ end
902
+ end
903
+ end
904
+ end
905
+
906
+ def test_corecursive
907
+ # just be sure that we can instantiate types with corecursive field-type
908
+ # references.
909
+ m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
910
+ assert Recursive1.descriptor.lookup("foo").subtype ==
911
+ Recursive2.descriptor
912
+ assert Recursive2.descriptor.lookup("foo").subtype ==
913
+ Recursive1.descriptor
914
+
915
+ serialized = Recursive1.encode(m)
916
+ m2 = Recursive1.decode(serialized)
917
+ assert m == m2
918
+ end
919
+
920
+ def test_serialize_cycle
921
+ m = Recursive1.new(:foo => Recursive2.new)
922
+ m.foo.foo = m
923
+ assert_raise RuntimeError do
924
+ serialized = Recursive1.encode(m)
925
+ end
926
+ end
927
+
928
+ def test_bad_field_names
929
+ m = BadFieldNames.new(:dup => 1, :class => 2)
930
+ m2 = m.dup
931
+ assert m == m2
932
+ assert m['dup'] == 1
933
+ assert m['class'] == 2
934
+ m['dup'] = 3
935
+ assert m['dup'] == 3
936
+ m['a.b'] = 4
937
+ assert m['a.b'] == 4
938
+ end
939
+
940
+ def test_int_ranges
941
+ m = TestMessage.new
942
+
943
+ m.optional_int32 = 0
944
+ m.optional_int32 = -0x8000_0000
945
+ m.optional_int32 = +0x7fff_ffff
946
+ m.optional_int32 = 1.0
947
+ m.optional_int32 = -1.0
948
+ m.optional_int32 = 2e9
949
+ assert_raise RangeError do
950
+ m.optional_int32 = -0x8000_0001
951
+ end
952
+ assert_raise RangeError do
953
+ m.optional_int32 = +0x8000_0000
954
+ end
955
+ assert_raise RangeError do
956
+ m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
957
+ end
958
+ assert_raise RangeError do
959
+ m.optional_int32 = 1e12
960
+ end
961
+ assert_raise RangeError do
962
+ m.optional_int32 = 1.5
963
+ end
964
+
965
+ m.optional_uint32 = 0
966
+ m.optional_uint32 = +0xffff_ffff
967
+ m.optional_uint32 = 1.0
968
+ m.optional_uint32 = 4e9
969
+ assert_raise RangeError do
970
+ m.optional_uint32 = -1
971
+ end
972
+ assert_raise RangeError do
973
+ m.optional_uint32 = -1.5
974
+ end
975
+ assert_raise RangeError do
976
+ m.optional_uint32 = -1.5e12
977
+ end
978
+ assert_raise RangeError do
979
+ m.optional_uint32 = -0x1000_0000_0000_0000
980
+ end
981
+ assert_raise RangeError do
982
+ m.optional_uint32 = +0x1_0000_0000
983
+ end
984
+ assert_raise RangeError do
985
+ m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
986
+ end
987
+ assert_raise RangeError do
988
+ m.optional_uint32 = 1e12
989
+ end
990
+ assert_raise RangeError do
991
+ m.optional_uint32 = 1.5
992
+ end
993
+
994
+ m.optional_int64 = 0
995
+ m.optional_int64 = -0x8000_0000_0000_0000
996
+ m.optional_int64 = +0x7fff_ffff_ffff_ffff
997
+ m.optional_int64 = 1.0
998
+ m.optional_int64 = -1.0
999
+ m.optional_int64 = 8e18
1000
+ m.optional_int64 = -8e18
1001
+ assert_raise RangeError do
1002
+ m.optional_int64 = -0x8000_0000_0000_0001
1003
+ end
1004
+ assert_raise RangeError do
1005
+ m.optional_int64 = +0x8000_0000_0000_0000
1006
+ end
1007
+ assert_raise RangeError do
1008
+ m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1009
+ end
1010
+ assert_raise RangeError do
1011
+ m.optional_int64 = 1e50
1012
+ end
1013
+ assert_raise RangeError do
1014
+ m.optional_int64 = 1.5
1015
+ end
1016
+
1017
+ m.optional_uint64 = 0
1018
+ m.optional_uint64 = +0xffff_ffff_ffff_ffff
1019
+ m.optional_uint64 = 1.0
1020
+ m.optional_uint64 = 16e18
1021
+ assert_raise RangeError do
1022
+ m.optional_uint64 = -1
1023
+ end
1024
+ assert_raise RangeError do
1025
+ m.optional_uint64 = -1.5
1026
+ end
1027
+ assert_raise RangeError do
1028
+ m.optional_uint64 = -1.5e12
1029
+ end
1030
+ assert_raise RangeError do
1031
+ m.optional_uint64 = -0x1_0000_0000_0000_0000
1032
+ end
1033
+ assert_raise RangeError do
1034
+ m.optional_uint64 = +0x1_0000_0000_0000_0000
1035
+ end
1036
+ assert_raise RangeError do
1037
+ m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
1038
+ end
1039
+ assert_raise RangeError do
1040
+ m.optional_uint64 = 1e50
1041
+ end
1042
+ assert_raise RangeError do
1043
+ m.optional_uint64 = 1.5
1044
+ end
1045
+ end
1046
+
1047
+ def test_stress_test
1048
+ m = TestMessage.new
1049
+ m.optional_int32 = 42
1050
+ m.optional_int64 = 0x100000000
1051
+ m.optional_string = "hello world"
1052
+ 10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
1053
+ 10.times do m.repeated_string.push "hello world" end
1054
+
1055
+ data = TestMessage.encode(m)
1056
+
1057
+ l = 0
1058
+ 10_000.times do
1059
+ m = TestMessage.decode(data)
1060
+ data_new = TestMessage.encode(m)
1061
+ assert data_new == data
1062
+ data = data_new
1063
+ end
1064
+ end
1065
+
1066
+ def test_reflection
1067
+ m = TestMessage.new(:optional_int32 => 1234)
1068
+ msgdef = m.class.descriptor
1069
+ assert msgdef.class == Google::Protobuf::Descriptor
1070
+ assert msgdef.any? {|field| field.name == "optional_int32"}
1071
+ optional_int32 = msgdef.lookup "optional_int32"
1072
+ assert optional_int32.class == Google::Protobuf::FieldDescriptor
1073
+ assert optional_int32 != nil
1074
+ assert optional_int32.name == "optional_int32"
1075
+ assert optional_int32.type == :int32
1076
+ optional_int32.set(m, 5678)
1077
+ assert m.optional_int32 == 5678
1078
+ m.optional_int32 = 1000
1079
+ assert optional_int32.get(m) == 1000
1080
+
1081
+ optional_msg = msgdef.lookup "optional_msg"
1082
+ assert optional_msg.subtype == TestMessage2.descriptor
1083
+
1084
+ optional_msg.set(m, optional_msg.subtype.msgclass.new)
1085
+
1086
+ assert msgdef.msgclass == TestMessage
1087
+
1088
+ optional_enum = msgdef.lookup "optional_enum"
1089
+ assert optional_enum.subtype == TestEnum.descriptor
1090
+ assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
1091
+ optional_enum.subtype.each do |k, v|
1092
+ # set with integer, check resolution to symbolic name
1093
+ optional_enum.set(m, v)
1094
+ assert optional_enum.get(m) == k
1095
+ end
1096
+ end
1097
+
1098
+ def test_json
1099
+ # TODO: Fix JSON in JRuby version.
1100
+ return if RUBY_PLATFORM == "java"
1101
+ m = TestMessage.new(:optional_int32 => 1234,
1102
+ :optional_int64 => -0x1_0000_0000,
1103
+ :optional_uint32 => 0x8000_0000,
1104
+ :optional_uint64 => 0xffff_ffff_ffff_ffff,
1105
+ :optional_bool => true,
1106
+ :optional_float => 1.0,
1107
+ :optional_double => -1e100,
1108
+ :optional_string => "Test string",
1109
+ :optional_bytes => ["FFFFFFFF"].pack('H*'),
1110
+ :optional_msg => TestMessage2.new(:foo => 42),
1111
+ :repeated_int32 => [1, 2, 3, 4],
1112
+ :repeated_string => ["a", "b", "c"],
1113
+ :repeated_bool => [true, false, true, false],
1114
+ :repeated_msg => [TestMessage2.new(:foo => 1),
1115
+ TestMessage2.new(:foo => 2)])
1116
+
1117
+ json_text = TestMessage.encode_json(m)
1118
+ m2 = TestMessage.decode_json(json_text)
1119
+ assert m == m2
1120
+
1121
+ # Crash case from GitHub issue 283.
1122
+ bar = Bar.new(msg: "bar")
1123
+ baz1 = Baz.new(msg: "baz")
1124
+ baz2 = Baz.new(msg: "quux")
1125
+ Foo.encode_json(Foo.new)
1126
+ Foo.encode_json(Foo.new(bar: bar))
1127
+ Foo.encode_json(Foo.new(bar: bar, baz: [baz1, baz2]))
1128
+ end
1129
+
1130
+ def test_json_maps
1131
+ # TODO: Fix JSON in JRuby version.
1132
+ return if RUBY_PLATFORM == "java"
1133
+ m = MapMessage.new(:map_string_int32 => {"a" => 1})
1134
+ expected = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
1135
+ assert MapMessage.encode_json(m) == expected
1136
+ m2 = MapMessage.decode_json(MapMessage.encode_json(m))
1137
+ assert m == m2
1138
+ end
1139
+ end
1140
+ end