protobuf 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +28 -0
  4. data/README.md +216 -0
  5. data/Rakefile +1 -0
  6. data/bin/rpc_server +117 -0
  7. data/bin/rprotoc +46 -0
  8. data/examples/addressbook.pb.rb +55 -0
  9. data/examples/addressbook.proto +24 -0
  10. data/examples/reading_a_message.rb +32 -0
  11. data/examples/writing_a_message.rb +46 -0
  12. data/lib/protobuf.rb +6 -0
  13. data/lib/protobuf/common/exceptions.rb +11 -0
  14. data/lib/protobuf/common/logger.rb +64 -0
  15. data/lib/protobuf/common/util.rb +59 -0
  16. data/lib/protobuf/common/wire_type.rb +10 -0
  17. data/lib/protobuf/compiler/compiler.rb +52 -0
  18. data/lib/protobuf/compiler/nodes.rb +323 -0
  19. data/lib/protobuf/compiler/proto.y +216 -0
  20. data/lib/protobuf/compiler/proto2.ebnf +79 -0
  21. data/lib/protobuf/compiler/proto_parser.rb +1425 -0
  22. data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
  23. data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
  24. data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
  25. data/lib/protobuf/compiler/template/rpc_service_implementation.erb +42 -0
  26. data/lib/protobuf/compiler/visitors.rb +302 -0
  27. data/lib/protobuf/descriptor/descriptor.proto +286 -0
  28. data/lib/protobuf/descriptor/descriptor.rb +55 -0
  29. data/lib/protobuf/descriptor/descriptor_builder.rb +143 -0
  30. data/lib/protobuf/descriptor/descriptor_proto.rb +138 -0
  31. data/lib/protobuf/descriptor/enum_descriptor.rb +33 -0
  32. data/lib/protobuf/descriptor/field_descriptor.rb +49 -0
  33. data/lib/protobuf/descriptor/file_descriptor.rb +37 -0
  34. data/lib/protobuf/message/decoder.rb +83 -0
  35. data/lib/protobuf/message/encoder.rb +46 -0
  36. data/lib/protobuf/message/enum.rb +62 -0
  37. data/lib/protobuf/message/extend.rb +8 -0
  38. data/lib/protobuf/message/field.rb +701 -0
  39. data/lib/protobuf/message/message.rb +402 -0
  40. data/lib/protobuf/message/protoable.rb +38 -0
  41. data/lib/protobuf/rpc/buffer.rb +74 -0
  42. data/lib/protobuf/rpc/client.rb +268 -0
  43. data/lib/protobuf/rpc/client_connection.rb +225 -0
  44. data/lib/protobuf/rpc/error.rb +34 -0
  45. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  46. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  47. data/lib/protobuf/rpc/rpc.pb.rb +107 -0
  48. data/lib/protobuf/rpc/server.rb +183 -0
  49. data/lib/protobuf/rpc/service.rb +244 -0
  50. data/lib/protobuf/rpc/stat.rb +70 -0
  51. data/lib/protobuf/version.rb +3 -0
  52. data/proto/rpc.proto +73 -0
  53. data/protobuf.gemspec +25 -0
  54. data/script/mk_parser +2 -0
  55. data/spec/functional/embedded_service_spec.rb +7 -0
  56. data/spec/proto/test.pb.rb +31 -0
  57. data/spec/proto/test.proto +31 -0
  58. data/spec/proto/test_service.rb +30 -0
  59. data/spec/proto/test_service_impl.rb +17 -0
  60. data/spec/spec_helper.rb +26 -0
  61. data/spec/unit/client_spec.rb +128 -0
  62. data/spec/unit/common/logger_spec.rb +121 -0
  63. data/spec/unit/enum_spec.rb +13 -0
  64. data/spec/unit/message_spec.rb +67 -0
  65. data/spec/unit/server_spec.rb +27 -0
  66. data/spec/unit/service_spec.rb +75 -0
  67. data/test/check_unbuild.rb +30 -0
  68. data/test/data/data.bin +3 -0
  69. data/test/data/data_source.py +14 -0
  70. data/test/data/types.bin +0 -0
  71. data/test/data/types_source.py +22 -0
  72. data/test/data/unk.png +0 -0
  73. data/test/proto/addressbook.pb.rb +66 -0
  74. data/test/proto/addressbook.proto +33 -0
  75. data/test/proto/addressbook_base.pb.rb +58 -0
  76. data/test/proto/addressbook_base.proto +26 -0
  77. data/test/proto/addressbook_ext.pb.rb +20 -0
  78. data/test/proto/addressbook_ext.proto +6 -0
  79. data/test/proto/collision.pb.rb +17 -0
  80. data/test/proto/collision.proto +5 -0
  81. data/test/proto/ext_collision.pb.rb +24 -0
  82. data/test/proto/ext_collision.proto +8 -0
  83. data/test/proto/ext_range.pb.rb +22 -0
  84. data/test/proto/ext_range.proto +7 -0
  85. data/test/proto/float_default.proto +10 -0
  86. data/test/proto/lowercase.pb.rb +30 -0
  87. data/test/proto/lowercase.proto +9 -0
  88. data/test/proto/merge.pb.rb +39 -0
  89. data/test/proto/merge.proto +15 -0
  90. data/test/proto/nested.pb.rb +30 -0
  91. data/test/proto/nested.proto +9 -0
  92. data/test/proto/optional_field.pb.rb +35 -0
  93. data/test/proto/optional_field.proto +12 -0
  94. data/test/proto/packed.pb.rb +22 -0
  95. data/test/proto/packed.proto +6 -0
  96. data/test/proto/rpc.proto +6 -0
  97. data/test/proto/types.pb.rb +84 -0
  98. data/test/proto/types.proto +37 -0
  99. data/test/test_addressbook.rb +56 -0
  100. data/test/test_compiler.rb +325 -0
  101. data/test/test_descriptor.rb +122 -0
  102. data/test/test_enum_value.rb +41 -0
  103. data/test/test_extension.rb +36 -0
  104. data/test/test_lowercase.rb +11 -0
  105. data/test/test_message.rb +128 -0
  106. data/test/test_optional_field.rb +103 -0
  107. data/test/test_packed_field.rb +40 -0
  108. data/test/test_parse.rb +15 -0
  109. data/test/test_repeated_types.rb +132 -0
  110. data/test/test_serialize.rb +61 -0
  111. data/test/test_standard_message.rb +96 -0
  112. data/test/test_types.rb +226 -0
  113. metadata +261 -0
@@ -0,0 +1,122 @@
1
+ require 'test/unit'
2
+ require 'test/proto/addressbook.pb'
3
+ require 'protobuf/descriptor/descriptor_builder'
4
+ require 'protobuf/descriptor/descriptor_proto'
5
+
6
+ class DescriptorTest < Test::Unit::TestCase
7
+ include Google::Protobuf
8
+ def test_build
9
+ tutorial_proto = FileDescriptorProto.new
10
+ tutorial_proto.package = 'Build::Tutorial'
11
+
12
+ person_proto = DescriptorProto.new
13
+ tutorial_proto.message_type << person_proto
14
+ person_proto.name = 'Person'
15
+
16
+ person_name_proto = FieldDescriptorProto.new
17
+ person_proto.field << person_name_proto
18
+ person_name_proto.label = FieldDescriptorProto::Label::LABEL_REQUIRED
19
+ person_name_proto.type = FieldDescriptorProto::Type::TYPE_STRING
20
+ person_name_proto.name = 'name'
21
+ person_name_proto.number = 1
22
+
23
+ person_id_proto = FieldDescriptorProto.new
24
+ person_proto.field << person_id_proto
25
+ person_id_proto.label = FieldDescriptorProto::Label::LABEL_REQUIRED
26
+ person_id_proto.type = FieldDescriptorProto::Type::TYPE_INT32
27
+ person_id_proto.name = 'id'
28
+ person_id_proto.number = 2
29
+
30
+ person_email_proto = FieldDescriptorProto.new
31
+ person_proto.field << person_email_proto
32
+ person_email_proto.label = FieldDescriptorProto::Label::LABEL_OPTIONAL
33
+ person_email_proto.type = FieldDescriptorProto::Type::TYPE_STRING
34
+ person_email_proto.name = 'email'
35
+ person_email_proto.number = 3
36
+
37
+ person_phone_type_proto = EnumDescriptorProto.new
38
+ person_proto.enum_type << person_phone_type_proto
39
+ person_phone_type_proto.name = 'PhoneType'
40
+
41
+ person_phone_type_mobile_proto = EnumValueDescriptorProto.new
42
+ person_phone_type_proto.value << person_phone_type_mobile_proto
43
+ person_phone_type_mobile_proto.name = 'MOBILE'
44
+ person_phone_type_mobile_proto.number = 0
45
+
46
+ person_phone_type_home_proto = EnumValueDescriptorProto.new
47
+ person_phone_type_proto.value << person_phone_type_home_proto
48
+ person_phone_type_home_proto.name = 'HOME'
49
+ person_phone_type_home_proto.number = 1
50
+
51
+ person_phone_type_work_proto = EnumValueDescriptorProto.new
52
+ person_phone_type_proto.value << person_phone_type_work_proto
53
+ person_phone_type_work_proto.name = 'WORK'
54
+ person_phone_type_work_proto.number = 2
55
+
56
+ person_phone_number_proto = DescriptorProto.new
57
+ person_proto.nested_type << person_phone_number_proto
58
+ person_phone_number_proto.name = 'PhoneNumber'
59
+
60
+ person_phone_number_number_proto = FieldDescriptorProto.new
61
+ person_phone_number_proto.field << person_phone_number_number_proto
62
+ person_phone_number_number_proto.label = FieldDescriptorProto::Label::LABEL_REQUIRED
63
+ person_phone_number_number_proto.type = FieldDescriptorProto::Type::TYPE_STRING
64
+ person_phone_number_number_proto.name = 'number'
65
+ person_phone_number_number_proto.number = 1
66
+
67
+ person_phone_number_type_proto = FieldDescriptorProto.new
68
+ person_phone_number_proto.field << person_phone_number_type_proto
69
+ person_phone_number_type_proto.label = FieldDescriptorProto::Label::LABEL_OPTIONAL
70
+ person_phone_number_type_proto.type = FieldDescriptorProto::Type::TYPE_ENUM
71
+ person_phone_number_type_proto.type_name = 'PhoneType'
72
+ person_phone_number_type_proto.name = 'type'
73
+ person_phone_number_type_proto.number = 2
74
+ person_phone_number_type_proto.default_value = 'HOME'
75
+
76
+ person_phone_phone_number_proto = FieldDescriptorProto.new
77
+ person_proto.field << person_phone_phone_number_proto
78
+ person_phone_phone_number_proto.label = FieldDescriptorProto::Label::LABEL_REPEATED
79
+ person_phone_phone_number_proto.type = FieldDescriptorProto::Type::TYPE_MESSAGE
80
+ person_phone_phone_number_proto.type_name = 'PhoneNumber'
81
+ person_phone_phone_number_proto.name = 'phone'
82
+ person_phone_phone_number_proto.number = 4
83
+
84
+ address_book_proto = DescriptorProto.new
85
+ tutorial_proto.message_type << address_book_proto
86
+ address_book_proto.name = 'AddressBook'
87
+
88
+ address_book_person_proto = FieldDescriptorProto.new
89
+ address_book_proto.field << address_book_person_proto
90
+ address_book_person_proto.label = FieldDescriptorProto::Label::LABEL_REPEATED
91
+ address_book_person_proto.type = FieldDescriptorProto::Type::TYPE_MESSAGE
92
+ address_book_person_proto.type_name = 'Person'
93
+ address_book_person_proto.name = 'person'
94
+ address_book_person_proto.number = 1
95
+
96
+ Protobuf::Descriptor::DescriptorBuilder.build(tutorial_proto)
97
+
98
+ assert_nothing_raised {Build::Tutorial::Person}
99
+ assert_nothing_raised {Build::Tutorial::Person.new}
100
+ assert_equal(['email', 'id', 'name', 'phone'],
101
+ Build::Tutorial::Person.fields.map{|tag, field| field.name}.sort)
102
+
103
+ assert_nothing_raised {Build::Tutorial::Person::PhoneNumber}
104
+ assert_nothing_raised {Build::Tutorial::Person::PhoneNumber.new}
105
+ assert_equal(['number', 'type'],
106
+ Build::Tutorial::Person::PhoneNumber.fields.map{|tag, field| field.name}.sort)
107
+
108
+ assert_nothing_raised {Build::Tutorial::Person::PhoneType}
109
+ assert_equal(0, Build::Tutorial::Person::PhoneType::MOBILE)
110
+ assert_equal(1, Build::Tutorial::Person::PhoneType::HOME)
111
+ assert_equal(2, Build::Tutorial::Person::PhoneType::WORK)
112
+
113
+ assert_nothing_raised {Build::Tutorial::AddressBook}
114
+ end
115
+
116
+ def test_unbuild
117
+ proto = Protobuf::Descriptor::FileDescriptor.unbuild(Tutorial::Person)
118
+ proto.serialize_to_file('person.bin')
119
+ puts
120
+ puts "run `test/check_unbuild.rb'"
121
+ end
122
+ end
@@ -0,0 +1,41 @@
1
+ require 'test/unit'
2
+ require 'protobuf/message/message'
3
+ require 'protobuf/message/enum'
4
+ require 'test/proto/addressbook.pb'
5
+ require 'test/proto/addressbook_base.pb'
6
+
7
+ class EnumValueTest < Test::Unit::TestCase
8
+ def test_enum_value
9
+ e = Protobuf::EnumValue.new(Object, :name, 100)
10
+ assert_kind_of(Protobuf::EnumValue, e)
11
+ assert_equal(:name, e.name)
12
+ assert_equal(100, e.value)
13
+ assert_equal('name', e.to_s)
14
+ assert_equal('name', "#{e}")
15
+ assert(e == 100)
16
+ assert(100 == e)
17
+ assert(101, e + 1)
18
+ assert(101, 1 + e)
19
+ end
20
+
21
+ def test_enum_field_and_enum_value
22
+ phone_number = Tutorial::Person::PhoneNumber.new
23
+
24
+ assert_kind_of(Protobuf::EnumValue, phone_number.type)
25
+ assert_equal(Tutorial::Person::PhoneType::HOME, phone_number.type)
26
+
27
+ phone_number.type = 1
28
+ assert_kind_of(Protobuf::EnumValue, phone_number.type)
29
+ assert_equal(Tutorial::Person::PhoneType::HOME, phone_number.type)
30
+ assert_equal(1, phone_number.type)
31
+
32
+ phone_number.type = :HOME
33
+ assert_kind_of(Protobuf::EnumValue, phone_number.type)
34
+ assert_equal(Tutorial::Person::PhoneType::HOME, phone_number.type)
35
+ assert_equal(1, phone_number.type)
36
+
37
+ assert_raise(TypeError) do
38
+ phone_number.type = TutorialExt::Person::PhoneType::HOME
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ require 'test/unit'
2
+ require 'test/proto/addressbook_ext.pb'
3
+
4
+ class ExtensionTest < Test::Unit::TestCase
5
+ def test_accessor
6
+ assert(TutorialExt::Person.extension_fields.to_a.map{|t, f| f.name}.include?(:age))
7
+ person = TutorialExt::Person.new
8
+ assert_nothing_raised {person.age = 100}
9
+ assert_equal(100, person.age)
10
+ end
11
+
12
+ def test_serialize
13
+ # serialize to string
14
+ person = TutorialExt::Person.new
15
+ person.id = 1234
16
+ person.age = 70
17
+ person.name = 'John Doe'
18
+ person.email = 'jdoe@example.com'
19
+ phone = TutorialExt::Person::PhoneNumber.new
20
+ phone.number = '555-4321'
21
+ phone.type = TutorialExt::Person::PhoneType::HOME
22
+ person.phone << phone
23
+ serialized_string = person.serialize_to_string
24
+
25
+ # parse the serialized string
26
+ person2 = TutorialExt::Person.new
27
+ person2.parse_from_string serialized_string
28
+ assert_equal(1234, person2.id)
29
+ assert_equal(70, person2.age)
30
+ assert_equal('John Doe', person2.name)
31
+ assert_equal('jdoe@example.com', person2.email)
32
+ assert_equal(1, person2.phone.size)
33
+ assert_equal('555-4321', person2.phone[0].number)
34
+ assert_equal(TutorialExt::Person::PhoneType::HOME, person2.phone[0].type)
35
+ end
36
+ end
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'test/proto/lowercase.pb'
3
+
4
+ class LowercaseTest < Test::Unit::TestCase
5
+ def test_lowercase
6
+ message = nil
7
+ assert_nothing_raised { message = Test::Lowercase::Baaz.new }
8
+ assert_nothing_raised { message.x = Test::Lowercase::Foo::Bar.new }
9
+ assert_equal(Test::Lowercase::Foo::Bar, message.get_field_by_name(:x).type)
10
+ end
11
+ end
@@ -0,0 +1,128 @@
1
+ require 'protobuf/message/message'
2
+ require 'test/proto/addressbook.pb'
3
+ require 'test/proto/merge.pb'
4
+ require 'test/unit'
5
+
6
+ # It should not conflict with Test::InnerMessage1 which is included in merge.proto
7
+ class InnerMessage1; end
8
+
9
+ class MessageTest < Test::Unit::TestCase
10
+ def test_equality
11
+ person1 = Tutorial::Person.new :name => 'ando'
12
+ person2 = Tutorial::Person.new :name => 'ando'
13
+ person3 = Tutorial::Person.new :name => 'Ando'
14
+ assert(person1 == person2)
15
+ assert(person1 != person3)
16
+ assert(person1 != 'ando')
17
+ end
18
+
19
+ def test_bracketed_access
20
+ person = Tutorial::Person.new
21
+ name_tag = 1
22
+ person[name_tag] = 'Ichiro'
23
+ assert_equal('Ichiro', person.name)
24
+ assert_equal('Ichiro', person[name_tag])
25
+
26
+ person[:id] = 100
27
+ assert_equal(100, person.id)
28
+ person['id'] = 200
29
+ assert_equal(200, person.id)
30
+ assert_equal(200, person[:id])
31
+ assert_equal(200, person['id'])
32
+ end
33
+
34
+ def test_initialize_with_hash
35
+ person = Tutorial::Person.new(:name => 'Jiro', :id => 300, :email => 'jiro@ema.il')
36
+ assert_equal('Jiro', person.name)
37
+ assert_equal(300, person.id)
38
+ assert_equal('jiro@ema.il', person.email)
39
+
40
+ # initialize with array of hash
41
+ person = Tutorial::Person.new(:phone => [{:number => 'phone1'}, {:number => 'phone2'}])
42
+ assert_equal('phone1', person.phone[0].number)
43
+ assert_equal('phone2', person.phone[1].number)
44
+
45
+ # initalize with hash in hash
46
+ message = Test::MergeMessage.new(:require_message => { :name => 'name1', :repeate_message => [{:name => 'name2'}] })
47
+ assert_equal('name1', message.require_message.name)
48
+ assert_equal('name2', message.require_message.repeate_message[0].name)
49
+
50
+ message.require_message = { :name => 'name21' }
51
+ message.require_message.repeate_message = [ {:name => 'name22'} ]
52
+ assert_equal('name21', message.require_message.name)
53
+ assert_equal('name22', message.require_message.repeate_message[0].name)
54
+ assert_equal(1, message.require_message.repeate_message.size)
55
+ end
56
+
57
+ def test_defined_filenames
58
+ assert(Tutorial::Person.defined_filenames)
59
+ assert_equal(1, Tutorial::Person.defined_filenames.size)
60
+ assert_match(%r{/.*/proto/addressbook\.pb\.rb}, Tutorial::Person.defined_filenames.first)
61
+ end
62
+
63
+ def test_proto_filenames
64
+ assert(Tutorial::Person.proto_filenames)
65
+ assert_equal(1, Tutorial::Person.proto_filenames.size)
66
+ assert_equal('test/proto/addressbook.proto', Tutorial::Person.proto_filenames.first)
67
+ end
68
+
69
+ def test_proto_contents
70
+ assert_equal(<<-EOS.strip, Tutorial::Person.proto_contents.values.first.strip)
71
+ package tutorial;
72
+
73
+ message Person {
74
+ required string name = 1;
75
+ required int32 id = 2;
76
+ optional string email = 3;
77
+
78
+ enum PhoneType {
79
+ MOBILE = 0;
80
+ HOME = 1;
81
+ WORK = 2;
82
+ }
83
+
84
+ message PhoneNumber {
85
+ required string number = 1;
86
+ optional PhoneType type = 2 [default = HOME];
87
+ }
88
+
89
+ repeated PhoneNumber phone = 4;
90
+ optional uint32 age = 5 [default = 20];
91
+
92
+ extensions 100 to 200;
93
+ }
94
+
95
+ /*
96
+ extend Person {
97
+ optional int32 age = 100;
98
+ }
99
+ */
100
+
101
+ message AddressBook {
102
+ repeated Person person = 1;
103
+ }
104
+ EOS
105
+ end
106
+
107
+ def test_merge_field
108
+ inner_message1_2 = Test::MergeMessage::InnerMessage2.new(:name => 'name12')
109
+ inner_message1_2.repeate_message << Test::MergeMessage::InnerMessage1.new(:name => 'name121')
110
+ message1 = Test::MergeMessage.new(:name => 'name1', :require_message => inner_message1_2)
111
+ message1.repeate_message << Test::MergeMessage::InnerMessage1.new(:name => 'name11')
112
+
113
+ inner_message2_2 = Test::MergeMessage::InnerMessage2.new(:name => 'name22')
114
+ inner_message2_2.repeate_message << Test::MergeMessage::InnerMessage1.new(:name => 'name221')
115
+ message2 = Test::MergeMessage.new(:name => 'name2', :require_message => inner_message2_2)
116
+ message2.repeate_message << Test::MergeMessage::InnerMessage1.new(:name => 'name21')
117
+
118
+ message1.merge_from(message2)
119
+ assert_equal('name2', message1.name)
120
+ assert_equal(2, message1.repeate_message.size)
121
+ assert_equal('name11', message1.repeate_message[0].name)
122
+ assert_equal('name21', message1.repeate_message[1].name)
123
+ assert_equal('name22', message1.require_message.name)
124
+ assert_equal(2, message1.require_message.repeate_message.size)
125
+ assert_equal('name121', message1.require_message.repeate_message[0].name)
126
+ assert_equal('name221', message1.require_message.repeate_message[1].name)
127
+ end
128
+ end
@@ -0,0 +1,103 @@
1
+ require 'test/unit'
2
+ require 'test/proto/optional_field.pb'
3
+
4
+ class OptionalFieldTest < Test::Unit::TestCase
5
+ def test_accessor
6
+ message = Test::OptionalField::Message.new
7
+
8
+ # default values
9
+ assert(!message.has_field?(:number))
10
+ assert_equal(20, message.number)
11
+
12
+ assert(!message.has_field?(:text))
13
+ assert_equal('default string', message.text)
14
+
15
+ assert(!message.has_field?(:enum))
16
+ assert_equal(2, message.enum)
17
+
18
+ assert(!message.has_field?(:signed))
19
+ assert_equal(-100, message.signed)
20
+
21
+ # assign values
22
+ assert_nothing_raised { message.number = 100 }
23
+ assert(message.has_field?(:number))
24
+ assert_equal(100, message.number)
25
+
26
+ assert_nothing_raised { message.text = 'abc' }
27
+ assert(message.has_field?(:text))
28
+ assert_equal('abc', message.text)
29
+
30
+ assert_nothing_raised { message.enum = Test::OptionalField::Message::Enum::A }
31
+ assert(message.has_field?(:enum))
32
+ assert_equal(1, message.enum)
33
+
34
+ assert_nothing_raised { message.signed = -20 }
35
+ assert(message.has_field?(:signed))
36
+ assert_equal(-20, message.signed)
37
+ end
38
+
39
+ def test_serialize
40
+ message1 = Test::OptionalField::Message.new
41
+ message2 = Test::OptionalField::Message.new
42
+
43
+ # all fields are empty
44
+ serialized_string = message1.to_s
45
+ assert(serialized_string.empty?)
46
+ message2.parse_from_string(serialized_string)
47
+ assert_equal(message1.number, message2.number)
48
+ assert_equal(message1.text, message2.text)
49
+ assert_equal(message1.enum, message2.enum)
50
+ assert_equal(message1.signed, message2.signed)
51
+ assert(!message2.has_field?(:number))
52
+ assert(!message2.has_field?(:text))
53
+ assert(!message2.has_field?(:enum))
54
+ assert(!message2.has_field?(:signed))
55
+
56
+ # assign the value whith is equal to default value
57
+ message1 = Test::OptionalField::Message.new
58
+ message1.number = message1.number
59
+ message1.text = message1.text
60
+ message1.enum = message1.enum
61
+ message1.signed = message1.signed
62
+ serialized_string = message1.to_s
63
+ assert !serialized_string.empty?
64
+
65
+ # set some fields
66
+ message1 = Test::OptionalField::Message.new
67
+ message1.number = 100
68
+ message1.text = 'new text'
69
+ serialized_string = message1.to_s
70
+ message2.parse_from_string(serialized_string)
71
+ assert_equal(message1.number, message2.number)
72
+ assert_equal(message1.text, message2.text)
73
+ assert_equal(message1.enum, message2.enum)
74
+ assert_equal(message1.signed, message2.signed)
75
+ assert( message2.has_field?(:number))
76
+ assert( message2.has_field?(:text))
77
+ assert(!message2.has_field?(:enum))
78
+ assert(!message2.has_field?(:signed))
79
+ end
80
+
81
+ def test_merge_optional_fields
82
+ src1 = Test::OptionalField::Message.new
83
+ src2 = Test::OptionalField::Message.new
84
+ dst = Test::OptionalField::Message.new
85
+
86
+ src1.number = 100
87
+ src1.text = 'old'
88
+ src2.text = 'new'
89
+ src2.signed = 20
90
+
91
+ serialized_string = src1.to_s + src2.to_s
92
+ dst.parse_from_string(serialized_string)
93
+
94
+ assert_equal(100, dst.number)
95
+ assert_equal('new', dst.text)
96
+ assert_equal(20, dst.signed)
97
+ assert dst.has_field?(:number)
98
+ assert dst.has_field?(:text)
99
+ assert !dst.has_field?(:enum)
100
+ assert dst.has_field?(:signed)
101
+ end
102
+
103
+ end