OLD | NEW |
| (Empty) |
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_ms
g: <BasicTest::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], rep
eated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], re
peated_float: [], repeated_double: [], repeated_string: ["hello", "there", "worl
d"], 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 | |
OLD | NEW |