google-protobuf 3.0.0.alpha.5.0.3-universal-darwin

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.

Potentially problematic release.


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

@@ -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
@@ -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