google-protoc 3.0.0.alpha.6.0.0

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