protobuf 3.6.12 → 3.7.0.pre0
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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +4 -4
- data/CHANGES.md +14 -3
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +39 -2
- data/lib/protobuf/field.rb +2 -2
- data/lib/protobuf/field/base_field.rb +27 -84
- data/lib/protobuf/field/bool_field.rb +3 -13
- data/lib/protobuf/field/bytes_field.rb +10 -26
- data/lib/protobuf/field/enum_field.rb +10 -20
- data/lib/protobuf/field/message_field.rb +13 -23
- data/lib/protobuf/generators/enum_generator.rb +1 -0
- data/lib/protobuf/generators/field_generator.rb +8 -2
- data/lib/protobuf/generators/file_generator.rb +8 -0
- data/lib/protobuf/generators/service_generator.rb +2 -2
- data/lib/protobuf/message.rb +47 -12
- data/lib/protobuf/message/fields.rb +80 -8
- data/lib/protobuf/rpc/connectors/common.rb +1 -1
- data/lib/protobuf/rpc/connectors/ping.rb +2 -2
- data/lib/protobuf/rpc/connectors/zmq.rb +1 -1
- data/lib/protobuf/rpc/middleware/exception_handler.rb +0 -4
- data/lib/protobuf/rpc/middleware/logger.rb +0 -4
- data/lib/protobuf/rpc/middleware/request_decoder.rb +16 -11
- data/lib/protobuf/rpc/middleware/response_encoder.rb +20 -15
- data/lib/protobuf/rpc/service.rb +10 -2
- data/lib/protobuf/rpc/service_directory.rb +0 -8
- data/lib/protobuf/rpc/service_dispatcher.rb +6 -5
- data/lib/protobuf/rpc/service_filters.rb +30 -8
- data/lib/protobuf/version.rb +1 -1
- data/proto/google/protobuf/descriptor.proto +190 -31
- data/spec/lib/protobuf/field/bool_field_spec.rb +33 -7
- data/spec/lib/protobuf/field/enum_field_spec.rb +26 -0
- data/spec/lib/protobuf/field/float_field_spec.rb +32 -1
- data/spec/lib/protobuf/field/int32_field_spec.rb +32 -1
- data/spec/lib/protobuf/field/message_field_spec.rb +79 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +34 -0
- data/spec/lib/protobuf/field_spec.rb +1 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +9 -0
- data/spec/lib/protobuf/generators/service_generator_spec.rb +9 -0
- data/spec/lib/protobuf/message_spec.rb +328 -63
- data/spec/lib/protobuf/rpc/connectors/ping_spec.rb +3 -3
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +18 -1
- data/spec/support/protos/enum.pb.rb +1 -1
- data/spec/support/protos/google_unittest.pb.rb +113 -111
- data/spec/support/protos/google_unittest.proto +7 -0
- data/spec/support/protos/multi_field_extensions.pb.rb +1 -1
- data/spec/support/protos/resource.pb.rb +9 -9
- metadata +79 -5
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            RSpec.describe Protobuf::Field:: | 
| 3 | 
            +
            RSpec.describe Protobuf::Field::BoolField do
         | 
| 4 4 |  | 
| 5 5 | 
             
              class SomeBoolMessage < ::Protobuf::Message
         | 
| 6 6 | 
             
                optional :bool, :some_bool, 1
         | 
| @@ -9,7 +9,7 @@ RSpec.describe Protobuf::Field::Int32Field do | |
| 9 9 |  | 
| 10 10 | 
             
              let(:instance) { SomeBoolMessage.new }
         | 
| 11 11 |  | 
| 12 | 
            -
              describe ' | 
| 12 | 
            +
              describe 'setting and getting field' do
         | 
| 13 13 | 
             
                subject { instance.some_bool = value; instance.some_bool }
         | 
| 14 14 |  | 
| 15 15 | 
             
                [true, false].each do |val|
         | 
| @@ -49,12 +49,38 @@ RSpec.describe Protobuf::Field::Int32Field do | |
| 49 49 | 
             
                end
         | 
| 50 50 | 
             
              end
         | 
| 51 51 |  | 
| 52 | 
            -
               | 
| 53 | 
            -
                 | 
| 54 | 
            -
             | 
| 52 | 
            +
              it 'defines ? method' do
         | 
| 53 | 
            +
                instance.required_bool = false
         | 
| 54 | 
            +
                expect(instance.required_bool?).to be(false)
         | 
| 55 | 
            +
              end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              describe '#default_value' do
         | 
| 58 | 
            +
                context 'optional and required fields' do
         | 
| 59 | 
            +
                  it 'returns the class default' do
         | 
| 60 | 
            +
                    expect(SomeBoolMessage.get_field('some_bool').default).to be nil
         | 
| 61 | 
            +
                    expect(::Protobuf::Field::BoolField.default).to be false
         | 
| 62 | 
            +
                    expect(instance.some_bool).to be false
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  context 'with field default' do
         | 
| 66 | 
            +
                    class AnotherBoolMessage < ::Protobuf::Message
         | 
| 67 | 
            +
                      optional :bool, :set_bool, 1, :default => true
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                    it 'returns the set default' do
         | 
| 71 | 
            +
                      expect(AnotherBoolMessage.get_field('set_bool').default).to be true
         | 
| 72 | 
            +
                      expect(AnotherBoolMessage.new.set_bool).to be true
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                context 'repeated field' do
         | 
| 78 | 
            +
                  class RepeatedBoolMessage < ::Protobuf::Message
         | 
| 79 | 
            +
                    repeated :bool, :repeated_bool, 1
         | 
| 80 | 
            +
                  end
         | 
| 55 81 |  | 
| 56 | 
            -
                  it 'returns  | 
| 57 | 
            -
                    expect( | 
| 82 | 
            +
                  it 'returns the set default' do
         | 
| 83 | 
            +
                    expect(RepeatedBoolMessage.new.repeated_bool).to eq []
         | 
| 58 84 | 
             
                  end
         | 
| 59 85 | 
             
                end
         | 
| 60 86 | 
             
              end
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Protobuf::Field::EnumField do
         | 
| 4 | 
            +
              let(:message) do
         | 
| 5 | 
            +
                Class.new(::Protobuf::Message) do
         | 
| 6 | 
            +
                  enum_class = Class.new(::Protobuf::Enum) do
         | 
| 7 | 
            +
                    define :POSITIVE, 22
         | 
| 8 | 
            +
                    define :NEGATIVE, -33
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  optional enum_class, :enum, 1
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe '.{encode, decode}' do
         | 
| 16 | 
            +
                it 'handles positive enum constants' do
         | 
| 17 | 
            +
                  instance = message.new(:enum => :POSITIVE)
         | 
| 18 | 
            +
                  expect(message.decode(instance.encode).enum).to eq(22)
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                it 'handles negative enum constants' do
         | 
| 22 | 
            +
                  instance = message.new(:enum => :NEGATIVE)
         | 
| 23 | 
            +
                  expect(message.decode(instance.encode).enum).to eq(-33)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| @@ -8,7 +8,7 @@ RSpec.describe Protobuf::Field::FloatField do | |
| 8 8 |  | 
| 9 9 | 
             
              let(:instance) { SomeFloatMessage.new }
         | 
| 10 10 |  | 
| 11 | 
            -
              describe ' | 
| 11 | 
            +
              describe 'setting and getting field' do
         | 
| 12 12 | 
             
                subject { instance.some_float = value; instance.some_float }
         | 
| 13 13 |  | 
| 14 14 | 
             
                context 'when set with an int' do
         | 
| @@ -52,4 +52,35 @@ RSpec.describe Protobuf::Field::FloatField do | |
| 52 52 | 
             
                end
         | 
| 53 53 | 
             
              end
         | 
| 54 54 |  | 
| 55 | 
            +
              describe '#default_value' do
         | 
| 56 | 
            +
                context 'optional and required fields' do
         | 
| 57 | 
            +
                  it 'returns the class default' do
         | 
| 58 | 
            +
                    expect(SomeFloatMessage.get_field('some_float').default).to be nil
         | 
| 59 | 
            +
                    expect(::Protobuf::Field::FloatField.default).to eq 0.0
         | 
| 60 | 
            +
                    expect(instance.some_float).to eq 0.0
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  context 'with field default' do
         | 
| 64 | 
            +
                    class AnotherFloatMessage < ::Protobuf::Message
         | 
| 65 | 
            +
                      optional :float, :set_float, 1, :default => 3.6
         | 
| 66 | 
            +
                    end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    it 'returns the set default' do
         | 
| 69 | 
            +
                      expect(AnotherFloatMessage.get_field('set_float').default).to eq 3.6
         | 
| 70 | 
            +
                      expect(AnotherFloatMessage.new.set_float).to eq 3.6
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                context 'repeated field' do
         | 
| 76 | 
            +
                  class RepeatedFloatMessage < ::Protobuf::Message
         | 
| 77 | 
            +
                    repeated :float, :repeated_float, 1
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  it 'returns the set default' do
         | 
| 81 | 
            +
                    expect(RepeatedFloatMessage.new.repeated_float).to eq []
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
              end
         | 
| 85 | 
            +
             | 
| 55 86 | 
             
            end
         | 
| @@ -10,7 +10,7 @@ RSpec.describe Protobuf::Field::Int32Field do | |
| 10 10 |  | 
| 11 11 | 
             
              let(:instance) { SomeInt32Message.new }
         | 
| 12 12 |  | 
| 13 | 
            -
              describe ' | 
| 13 | 
            +
              describe 'setting and getting a field' do
         | 
| 14 14 | 
             
                subject { instance.some_int = value; instance.some_int }
         | 
| 15 15 |  | 
| 16 16 | 
             
                context 'when set with an int' do
         | 
| @@ -86,4 +86,35 @@ RSpec.describe Protobuf::Field::Int32Field do | |
| 86 86 | 
             
                end
         | 
| 87 87 | 
             
              end
         | 
| 88 88 |  | 
| 89 | 
            +
              describe '#default_value' do
         | 
| 90 | 
            +
                context 'optional and required fields' do
         | 
| 91 | 
            +
                  it 'returns the class default' do
         | 
| 92 | 
            +
                    expect(SomeInt32Message.get_field('some_int').default).to be nil
         | 
| 93 | 
            +
                    expect(::Protobuf::Field::Int32Field.default).to eq 0
         | 
| 94 | 
            +
                    expect(instance.some_int).to eq 0
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  context 'with field default' do
         | 
| 98 | 
            +
                    class AnotherIntMessage < ::Protobuf::Message
         | 
| 99 | 
            +
                      optional :int32, :set_int, 1, :default => 3
         | 
| 100 | 
            +
                    end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                    it 'returns the set default' do
         | 
| 103 | 
            +
                      expect(AnotherIntMessage.get_field('set_int').default).to eq 3
         | 
| 104 | 
            +
                      expect(AnotherIntMessage.new.set_int).to eq 3
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                context 'repeated field' do
         | 
| 110 | 
            +
                  class RepeatedIntMessage < ::Protobuf::Message
         | 
| 111 | 
            +
                    repeated :int32, :repeated_int, 1
         | 
| 112 | 
            +
                  end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                  it 'returns the set default' do
         | 
| 115 | 
            +
                    expect(RepeatedIntMessage.new.repeated_int).to eq []
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
             | 
| 89 120 | 
             
            end
         | 
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe Protobuf::Field::MessageField do
         | 
| 4 | 
            +
              let(:field_message) do
         | 
| 5 | 
            +
                Class.new(::Protobuf::Message) do
         | 
| 6 | 
            +
                  optional :int32, :field, 1
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              let(:message) do
         | 
| 11 | 
            +
                Class.new(::Protobuf::Message) do
         | 
| 12 | 
            +
                  optional FieldMessage, :message_field, 1
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              before do
         | 
| 17 | 
            +
                stub_const('FieldMessage', field_message)
         | 
| 18 | 
            +
                stub_const('Message', message)
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              let(:instance) { message.new }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              describe 'setting and getting field' do
         | 
| 24 | 
            +
                context "when set with the message type" do
         | 
| 25 | 
            +
                  it 'is readable as a message' do
         | 
| 26 | 
            +
                    value = field_message.new(:field => 34)
         | 
| 27 | 
            +
                    instance.message_field = value
         | 
| 28 | 
            +
                    expect(instance.message_field).to eq(value)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                context "when set with #to_proto" do
         | 
| 33 | 
            +
                  let(:to_proto_message) do
         | 
| 34 | 
            +
                    Class.new do
         | 
| 35 | 
            +
                      def to_proto
         | 
| 36 | 
            +
                        FieldMessage.new(:field => 42)
         | 
| 37 | 
            +
                      end
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  it 'is readable as a message' do
         | 
| 42 | 
            +
                    value = to_proto_message.new
         | 
| 43 | 
            +
                    instance.message_field = value
         | 
| 44 | 
            +
                    expect(instance.message_field).to eq(value.to_proto)
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                context "when set with #to_proto that returns the wrong message type" do
         | 
| 49 | 
            +
                  let(:to_proto_is_wrong_message) do
         | 
| 50 | 
            +
                    Class.new do
         | 
| 51 | 
            +
                      def to_proto
         | 
| 52 | 
            +
                        Message.new
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  it 'fails' do
         | 
| 58 | 
            +
                    value = to_proto_is_wrong_message.new
         | 
| 59 | 
            +
                    expect { instance.message_field = value }.to raise_error TypeError
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                context "when set with #to_hash" do
         | 
| 64 | 
            +
                  let(:to_hash_message) do
         | 
| 65 | 
            +
                    Class.new do
         | 
| 66 | 
            +
                      def to_hash
         | 
| 67 | 
            +
                        { :field => 989 }
         | 
| 68 | 
            +
                      end
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  it 'is readable as a message' do
         | 
| 73 | 
            +
                    value = to_hash_message.new
         | 
| 74 | 
            +
                    instance.message_field = value
         | 
| 75 | 
            +
                    expect(instance.message_field).to eq(field_message.new(value.to_hash))
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         | 
| @@ -42,4 +42,38 @@ RSpec.describe ::Protobuf::Field::StringField do | |
| 42 42 | 
             
                end
         | 
| 43 43 | 
             
              end
         | 
| 44 44 |  | 
| 45 | 
            +
              describe '#default_value' do
         | 
| 46 | 
            +
                context 'optional and required fields' do
         | 
| 47 | 
            +
                  it 'returns the class default' do
         | 
| 48 | 
            +
                    class SomeStringMessage < ::Protobuf::Message
         | 
| 49 | 
            +
                      optional :string, :some_string, 1
         | 
| 50 | 
            +
                    end
         | 
| 51 | 
            +
                    expect(SomeStringMessage.get_field('some_string').default).to be nil
         | 
| 52 | 
            +
                    expect(::Protobuf::Field::StringField.default).to eq ""
         | 
| 53 | 
            +
                    expect(SomeStringMessage.new.some_string).to eq ""
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  context 'with field default' do
         | 
| 57 | 
            +
                    class AnotherStringMessage < ::Protobuf::Message
         | 
| 58 | 
            +
                      optional :string, :set_string, 1, :default => "default value this is"
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    it 'returns the set default' do
         | 
| 62 | 
            +
                      expect(AnotherStringMessage.get_field('set_string').default).to eq "default value this is"
         | 
| 63 | 
            +
                      expect(AnotherStringMessage.new.set_string).to eq "default value this is"
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                context 'repeated field' do
         | 
| 69 | 
            +
                  class RepeatedStringMessage < ::Protobuf::Message
         | 
| 70 | 
            +
                    repeated :string, :repeated_string, 1
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  it 'returns the set default' do
         | 
| 74 | 
            +
                    expect(RepeatedStringMessage.new.repeated_string).to eq []
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 45 79 | 
             
            end
         | 
| @@ -68,6 +68,15 @@ end | |
| 68 68 | 
             
                it 'returns a string identifying the given enum value' do
         | 
| 69 69 | 
             
                  expect(subject.build_value(enum.value.first)).to eq("define :FOO, 1")
         | 
| 70 70 | 
             
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                context 'with PB_UPCASE_ENUMS set' do
         | 
| 73 | 
            +
                  before { allow(ENV).to receive(:key?).with('PB_UPCASE_ENUMS').and_return(true) }
         | 
| 74 | 
            +
                  let(:values) { [{ :name => 'boom', :number => 1 }] }
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  it 'returns a string with the given enum name in ALL CAPS' do
         | 
| 77 | 
            +
                    expect(subject.build_value(enum.value.first)).to eq("define :BOOM, 1")
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
                end
         | 
| 71 80 | 
             
              end
         | 
| 72 81 |  | 
| 73 82 | 
             
            end
         | 
| @@ -41,6 +41,15 @@ end | |
| 41 41 | 
             
                it 'returns a string identifying the given method descriptor' do
         | 
| 42 42 | 
             
                  expect(subject.build_method(service.method.first)).to eq("rpc :search, FooRequest, FooResponse")
         | 
| 43 43 | 
             
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                context 'with PB_USE_RAW_RPC_NAMES in the environemnt' do
         | 
| 46 | 
            +
                  before { allow(ENV).to receive(:key?).with('PB_USE_RAW_RPC_NAMES').and_return(true) }
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  it 'uses the raw RPC name and does not underscore it' do
         | 
| 49 | 
            +
                    expect(subject.build_method(service.method.first)).to eq("rpc :Search, FooRequest, FooResponse")
         | 
| 50 | 
            +
                    expect(subject.build_method(service.method.last)).to eq("rpc :FooBar, ::Foo::Request, ::Bar::Response")
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 44 53 | 
             
              end
         | 
| 45 54 |  | 
| 46 55 | 
             
            end
         | 
| @@ -181,64 +181,6 @@ RSpec.describe Protobuf::Message do | |
| 181 181 | 
             
                  test_enum = Test::EnumTestMessage.new { |p| p.non_default_enum = 2 }
         | 
| 182 182 | 
             
                  expect(test_enum.non_default_enum).to eq(2)
         | 
| 183 183 | 
             
                end
         | 
| 184 | 
            -
             | 
| 185 | 
            -
                context 'ignoring unknown fields' do
         | 
| 186 | 
            -
                  around do |example|
         | 
| 187 | 
            -
                    orig = ::Protobuf.ignore_unknown_fields?
         | 
| 188 | 
            -
                    ::Protobuf.ignore_unknown_fields = true
         | 
| 189 | 
            -
                    example.call
         | 
| 190 | 
            -
                    ::Protobuf.ignore_unknown_fields = orig
         | 
| 191 | 
            -
                  end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
                  context 'with valid fields' do
         | 
| 194 | 
            -
                    let(:values) { { :name => "Jim" } }
         | 
| 195 | 
            -
             | 
| 196 | 
            -
                    it "does not raise an error" do
         | 
| 197 | 
            -
                      expect { ::Test::Resource.new(values) }.to_not raise_error
         | 
| 198 | 
            -
                    end
         | 
| 199 | 
            -
                  end
         | 
| 200 | 
            -
             | 
| 201 | 
            -
                  context 'with non-existent field' do
         | 
| 202 | 
            -
                    let(:values) { { :name => "Jim", :othername => "invalid" } }
         | 
| 203 | 
            -
             | 
| 204 | 
            -
                    it "does not raise an error" do
         | 
| 205 | 
            -
                      expect { ::Test::Resource.new(values) }.to_not raise_error
         | 
| 206 | 
            -
                    end
         | 
| 207 | 
            -
                  end
         | 
| 208 | 
            -
                end
         | 
| 209 | 
            -
             | 
| 210 | 
            -
                context 'not ignoring unknown fields' do
         | 
| 211 | 
            -
                  around do |example|
         | 
| 212 | 
            -
                    orig = ::Protobuf.ignore_unknown_fields?
         | 
| 213 | 
            -
                    ::Protobuf.ignore_unknown_fields = false
         | 
| 214 | 
            -
                    example.call
         | 
| 215 | 
            -
                    ::Protobuf.ignore_unknown_fields = orig
         | 
| 216 | 
            -
                  end
         | 
| 217 | 
            -
             | 
| 218 | 
            -
                  context 'with valid fields' do
         | 
| 219 | 
            -
                    let(:values) { { :name => "Jim" } }
         | 
| 220 | 
            -
             | 
| 221 | 
            -
                    it "does not raise an error" do
         | 
| 222 | 
            -
                      expect { ::Test::Resource.new(values) }.to_not raise_error
         | 
| 223 | 
            -
                    end
         | 
| 224 | 
            -
                  end
         | 
| 225 | 
            -
             | 
| 226 | 
            -
                  context 'with non-existent field' do
         | 
| 227 | 
            -
                    let(:values) { { :name => "Jim", :othername => "invalid" } }
         | 
| 228 | 
            -
             | 
| 229 | 
            -
                    it "raises an error and mentions the erroneous field" do
         | 
| 230 | 
            -
                      expect { ::Test::Resource.new(values) }.to raise_error(::Protobuf::FieldNotDefinedError, /othername/)
         | 
| 231 | 
            -
                    end
         | 
| 232 | 
            -
             | 
| 233 | 
            -
                    context 'with a nil value' do
         | 
| 234 | 
            -
                      let(:values) { { :name => "Jim", :othername => nil } }
         | 
| 235 | 
            -
             | 
| 236 | 
            -
                      it "raises an error and mentions the erroneous field" do
         | 
| 237 | 
            -
                        expect { ::Test::Resource.new(values) }.to raise_error(::Protobuf::FieldNotDefinedError, /othername/)
         | 
| 238 | 
            -
                      end
         | 
| 239 | 
            -
                    end
         | 
| 240 | 
            -
                  end
         | 
| 241 | 
            -
                end
         | 
| 242 184 | 
             
              end
         | 
| 243 185 |  | 
| 244 186 | 
             
              describe '#encode' do
         | 
| @@ -448,6 +390,29 @@ RSpec.describe Protobuf::Message do | |
| 448 390 | 
             
                    )
         | 
| 449 391 | 
             
                  end
         | 
| 450 392 | 
             
                end
         | 
| 393 | 
            +
             | 
| 394 | 
            +
                it 'uses simple field names as keys when possible and fully qualified names otherwise' do
         | 
| 395 | 
            +
                  message = Class.new(::Protobuf::Message) do
         | 
| 396 | 
            +
                    optional :int32, :field, 1
         | 
| 397 | 
            +
                    optional :int32, :colliding_field, 2
         | 
| 398 | 
            +
                    extensions 100...200
         | 
| 399 | 
            +
                    optional :int32, :".ext.normal_ext_field", 100, :extension => true
         | 
| 400 | 
            +
                    optional :int32, :".ext.colliding_field", 101, :extension => true
         | 
| 401 | 
            +
                    optional :int32, :".ext.colliding_field2", 102, :extension => true
         | 
| 402 | 
            +
                    optional :int32, :".ext2.colliding_field2", 103, :extension => true
         | 
| 403 | 
            +
                  end
         | 
| 404 | 
            +
             | 
| 405 | 
            +
                  hash = {
         | 
| 406 | 
            +
                    :field => 1,
         | 
| 407 | 
            +
                    :colliding_field => 2,
         | 
| 408 | 
            +
                    :normal_ext_field => 3,
         | 
| 409 | 
            +
                    :".ext.colliding_field" => 4,
         | 
| 410 | 
            +
                    :".ext.colliding_field2" => 5,
         | 
| 411 | 
            +
                    :".ext2.colliding_field2" => 6,
         | 
| 412 | 
            +
                  }
         | 
| 413 | 
            +
                  instance = message.new(hash)
         | 
| 414 | 
            +
                  expect(instance.to_hash).to eq(hash)
         | 
| 415 | 
            +
                end
         | 
| 451 416 | 
             
              end
         | 
| 452 417 |  | 
| 453 418 | 
             
              describe '#to_json' do
         | 
| @@ -468,16 +433,40 @@ RSpec.describe Protobuf::Message do | |
| 468 433 | 
             
                end
         | 
| 469 434 | 
             
              end
         | 
| 470 435 |  | 
| 471 | 
            -
              describe "# | 
| 436 | 
            +
              describe "#define_accessor" do
         | 
| 472 437 | 
             
                subject { ::Test::Resource.new }
         | 
| 473 438 |  | 
| 474 | 
            -
                it  | 
| 439 | 
            +
                it 'allows string fields to be set to nil' do
         | 
| 475 440 | 
             
                  expect { subject.name = nil }.to_not raise_error
         | 
| 476 441 | 
             
                end
         | 
| 477 442 |  | 
| 478 | 
            -
                it  | 
| 443 | 
            +
                it 'does not allow string fields to be set to Numeric' do
         | 
| 479 444 | 
             
                  expect { subject.name = 1 }.to raise_error(/name/)
         | 
| 480 445 | 
             
                end
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                context '#{simple_field_name}!' do
         | 
| 448 | 
            +
                  it 'returns value of set field' do
         | 
| 449 | 
            +
                    expect(::Test::Resource.new(:name => "Joe").name!).to eq("Joe")
         | 
| 450 | 
            +
                  end
         | 
| 451 | 
            +
             | 
| 452 | 
            +
                  it 'returns value of set field with default' do
         | 
| 453 | 
            +
                    expect(::Test::Resource.new(:name => "").name!).to eq("")
         | 
| 454 | 
            +
                  end
         | 
| 455 | 
            +
             | 
| 456 | 
            +
                  it 'returns nil if extension field is unset' do
         | 
| 457 | 
            +
                    expect(subject.ext_is_searchable!).to be_nil
         | 
| 458 | 
            +
                  end
         | 
| 459 | 
            +
             | 
| 460 | 
            +
                  it 'returns value of set extension field' do
         | 
| 461 | 
            +
                    message = ::Test::Resource.new(:ext_is_searchable => true)
         | 
| 462 | 
            +
                    expect(message.ext_is_searchable!).to be(true)
         | 
| 463 | 
            +
                  end
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                  it 'returns value of set extension field with default' do
         | 
| 466 | 
            +
                    message = ::Test::Resource.new(:ext_is_searchable => false)
         | 
| 467 | 
            +
                    expect(message.ext_is_searchable!).to be(false)
         | 
| 468 | 
            +
                  end
         | 
| 469 | 
            +
                end
         | 
| 481 470 | 
             
              end
         | 
| 482 471 |  | 
| 483 472 | 
             
              describe '.get_extension_field' do
         | 
| @@ -486,12 +475,15 @@ RSpec.describe Protobuf::Message do | |
| 486 475 | 
             
                  expect(field).to be_a(::Protobuf::Field::BoolField)
         | 
| 487 476 | 
             
                  expect(field.tag).to eq(100)
         | 
| 488 477 | 
             
                  expect(field.name).to eq(:ext_is_searchable)
         | 
| 478 | 
            +
                  expect(field.fully_qualified_name).to eq(:'.test.Searchable.ext_is_searchable')
         | 
| 489 479 | 
             
                  expect(field).to be_extension
         | 
| 490 480 | 
             
                end
         | 
| 491 481 |  | 
| 492 482 | 
             
                it 'fetches an extension field by its symbolized name' do
         | 
| 493 483 | 
             
                  expect(::Test::Resource.get_extension_field(:ext_is_searchable)).to be_a(::Protobuf::Field::BoolField)
         | 
| 494 484 | 
             
                  expect(::Test::Resource.get_extension_field('ext_is_searchable')).to be_a(::Protobuf::Field::BoolField)
         | 
| 485 | 
            +
                  expect(::Test::Resource.get_extension_field(:'.test.Searchable.ext_is_searchable')).to be_a(::Protobuf::Field::BoolField)
         | 
| 486 | 
            +
                  expect(::Test::Resource.get_extension_field('.test.Searchable.ext_is_searchable')).to be_a(::Protobuf::Field::BoolField)
         | 
| 495 487 | 
             
                end
         | 
| 496 488 |  | 
| 497 489 | 
             
                it 'returns nil when attempting to get a non-extension field' do
         | 
| @@ -504,12 +496,71 @@ RSpec.describe Protobuf::Message do | |
| 504 496 | 
             
                end
         | 
| 505 497 | 
             
              end
         | 
| 506 498 |  | 
| 499 | 
            +
              describe '#field?' do
         | 
| 500 | 
            +
                it 'returns false for non-existent field' do
         | 
| 501 | 
            +
                  expect(::Test::Resource.get_field('doesnotexist')).to be_nil
         | 
| 502 | 
            +
                  expect(::Test::Resource.new.field?('doesnotexist')).to be(false)
         | 
| 503 | 
            +
                end
         | 
| 504 | 
            +
             | 
| 505 | 
            +
                it 'returns false for unset field' do
         | 
| 506 | 
            +
                  expect(::Test::Resource.get_field('name')).to be
         | 
| 507 | 
            +
                  expect(::Test::Resource.new.field?('name')).to be(false)
         | 
| 508 | 
            +
                end
         | 
| 509 | 
            +
             | 
| 510 | 
            +
                it 'returns false for unset field from tag' do
         | 
| 511 | 
            +
                  expect(::Test::Resource.get_field(1)).to be
         | 
| 512 | 
            +
                  expect(::Test::Resource.new.field?(1)).to be(false)
         | 
| 513 | 
            +
                end
         | 
| 514 | 
            +
             | 
| 515 | 
            +
                it 'returns true for set field' do
         | 
| 516 | 
            +
                  expect(::Test::Resource.new(:name => "Joe").field?('name')).to be(true)
         | 
| 517 | 
            +
                end
         | 
| 518 | 
            +
             | 
| 519 | 
            +
                it 'returns true for set field with default' do
         | 
| 520 | 
            +
                  expect(::Test::Resource.new(:name => "").field?('name')).to be(true)
         | 
| 521 | 
            +
                end
         | 
| 522 | 
            +
             | 
| 523 | 
            +
                it 'returns true from field tag value' do
         | 
| 524 | 
            +
                  expect(::Test::Resource.new(:name => "Joe").field?(1)).to be(true)
         | 
| 525 | 
            +
                end
         | 
| 526 | 
            +
             | 
| 527 | 
            +
                it 'returns false for unset extension field' do
         | 
| 528 | 
            +
                  ext_field = :".test.Searchable.ext_is_searchable"
         | 
| 529 | 
            +
                  expect(::Test::Resource.get_extension_field(ext_field)).to be
         | 
| 530 | 
            +
                  expect(::Test::Resource.new.field?(ext_field)).to be(false)
         | 
| 531 | 
            +
                end
         | 
| 532 | 
            +
             | 
| 533 | 
            +
                it 'returns false for unset extension field from tag' do
         | 
| 534 | 
            +
                  expect(::Test::Resource.get_extension_field(100)).to be
         | 
| 535 | 
            +
                  expect(::Test::Resource.new.field?(100)).to be(false)
         | 
| 536 | 
            +
                end
         | 
| 537 | 
            +
             | 
| 538 | 
            +
                it 'returns true for set extension field' do
         | 
| 539 | 
            +
                  ext_field = :".test.Searchable.ext_is_searchable"
         | 
| 540 | 
            +
                  message = ::Test::Resource.new(ext_field => true)
         | 
| 541 | 
            +
                  expect(message.field?(ext_field)).to be(true)
         | 
| 542 | 
            +
                end
         | 
| 543 | 
            +
             | 
| 544 | 
            +
                it 'returns true for set extension field with default' do
         | 
| 545 | 
            +
                  ext_field = :".test.Searchable.ext_is_searchable"
         | 
| 546 | 
            +
                  message = ::Test::Resource.new(ext_field => false)
         | 
| 547 | 
            +
                  expect(message.field?(ext_field)).to be(true)
         | 
| 548 | 
            +
                end
         | 
| 549 | 
            +
             | 
| 550 | 
            +
                it 'returns true for set extension field from tag' do
         | 
| 551 | 
            +
                  ext_field = :".test.Searchable.ext_is_searchable"
         | 
| 552 | 
            +
                  message = ::Test::Resource.new(ext_field => false)
         | 
| 553 | 
            +
                  expect(message.field?(100)).to be(true)
         | 
| 554 | 
            +
                end
         | 
| 555 | 
            +
              end
         | 
| 556 | 
            +
             | 
| 507 557 | 
             
              describe '.get_field' do
         | 
| 508 558 | 
             
                it 'fetches a non-extension field by its tag' do
         | 
| 509 559 | 
             
                  field = ::Test::Resource.get_field(1)
         | 
| 510 560 | 
             
                  expect(field).to be_a(::Protobuf::Field::StringField)
         | 
| 511 561 | 
             
                  expect(field.tag).to eq(1)
         | 
| 512 562 | 
             
                  expect(field.name).to eq(:name)
         | 
| 563 | 
            +
                  expect(field.fully_qualified_name).to eq(:name)
         | 
| 513 564 | 
             
                  expect(field).not_to be_extension
         | 
| 514 565 | 
             
                end
         | 
| 515 566 |  | 
| @@ -520,8 +571,8 @@ RSpec.describe Protobuf::Message do | |
| 520 571 |  | 
| 521 572 | 
             
                it 'fetches an extension field when forced' do
         | 
| 522 573 | 
             
                  expect(::Test::Resource.get_field(100, true)).to be_a(::Protobuf::Field::BoolField)
         | 
| 523 | 
            -
                  expect(::Test::Resource.get_field(:ext_is_searchable, true)).to be_a(::Protobuf::Field::BoolField)
         | 
| 524 | 
            -
                  expect(::Test::Resource.get_field('ext_is_searchable', true)).to be_a(::Protobuf::Field::BoolField)
         | 
| 574 | 
            +
                  expect(::Test::Resource.get_field(:'.test.Searchable.ext_is_searchable', true)).to be_a(::Protobuf::Field::BoolField)
         | 
| 575 | 
            +
                  expect(::Test::Resource.get_field('.test.Searchable.ext_is_searchable', true)).to be_a(::Protobuf::Field::BoolField)
         | 
| 525 576 | 
             
                end
         | 
| 526 577 |  | 
| 527 578 | 
             
                it 'returns nil when attempting to get an extension field' do
         | 
| @@ -534,4 +585,218 @@ RSpec.describe Protobuf::Message do | |
| 534 585 | 
             
                end
         | 
| 535 586 | 
             
              end
         | 
| 536 587 |  | 
| 588 | 
            +
              describe 'defining a field' do
         | 
| 589 | 
            +
                # Case 1
         | 
| 590 | 
            +
                context 'single base field' do
         | 
| 591 | 
            +
                  let(:klass) do
         | 
| 592 | 
            +
                    Class.new(Protobuf::Message) do
         | 
| 593 | 
            +
                      optional :string, :foo, 1
         | 
| 594 | 
            +
                    end
         | 
| 595 | 
            +
                  end
         | 
| 596 | 
            +
             | 
| 597 | 
            +
                  it 'has an accessor for foo' do
         | 
| 598 | 
            +
                    message = klass.new(:foo => 'bar')
         | 
| 599 | 
            +
                    expect(message.foo).to eq('bar')
         | 
| 600 | 
            +
                    expect(message[:foo]).to eq('bar')
         | 
| 601 | 
            +
                    expect(message['foo']).to eq('bar')
         | 
| 602 | 
            +
                  end
         | 
| 603 | 
            +
                end
         | 
| 604 | 
            +
             | 
| 605 | 
            +
                # Case 2
         | 
| 606 | 
            +
                context 'base field and extension field name collision' do
         | 
| 607 | 
            +
                  let(:klass) do
         | 
| 608 | 
            +
                    Class.new(Protobuf::Message) do
         | 
| 609 | 
            +
                      optional :string, :foo, 1
         | 
| 610 | 
            +
                      optional :string, :".boom.foo", 2, :extension => true
         | 
| 611 | 
            +
                    end
         | 
| 612 | 
            +
                  end
         | 
| 613 | 
            +
             | 
| 614 | 
            +
                  it 'has an accessor for foo that refers to the base field' do
         | 
| 615 | 
            +
                    message = klass.new(:foo => 'bar', '.boom.foo' => 'bam')
         | 
| 616 | 
            +
                    expect(message.foo).to eq('bar')
         | 
| 617 | 
            +
                    expect(message[:foo]).to eq('bar')
         | 
| 618 | 
            +
                    expect(message['foo']).to eq('bar')
         | 
| 619 | 
            +
                    expect(message[:'.boom.foo']).to eq('bam')
         | 
| 620 | 
            +
                    expect(message['.boom.foo']).to eq('bam')
         | 
| 621 | 
            +
                  end
         | 
| 622 | 
            +
                end
         | 
| 623 | 
            +
             | 
| 624 | 
            +
                # Case 3
         | 
| 625 | 
            +
                context 'no base field with extension fields with name collision' do
         | 
| 626 | 
            +
                  let(:klass) do
         | 
| 627 | 
            +
                    Class.new(Protobuf::Message) do
         | 
| 628 | 
            +
                      optional :string, :".boom.foo", 2, :extension => true
         | 
| 629 | 
            +
                      optional :string, :".goat.foo", 3, :extension => true
         | 
| 630 | 
            +
                    end
         | 
| 631 | 
            +
                  end
         | 
| 632 | 
            +
             | 
| 633 | 
            +
                  it 'has an accessor for foo that refers to the extension field' do
         | 
| 634 | 
            +
                    message = klass.new('.boom.foo' => 'bam', '.goat.foo' => 'red')
         | 
| 635 | 
            +
                    expect { message.foo }.to raise_error(NoMethodError)
         | 
| 636 | 
            +
                    expect { message[:foo] }.to raise_error(ArgumentError)
         | 
| 637 | 
            +
                    expect { message['foo'] }.to raise_error(ArgumentError)
         | 
| 638 | 
            +
                    expect(message[:'.boom.foo']).to eq('bam')
         | 
| 639 | 
            +
                    expect(message['.boom.foo']).to eq('bam')
         | 
| 640 | 
            +
                    expect(message[:'.goat.foo']).to eq('red')
         | 
| 641 | 
            +
                    expect(message['.goat.foo']).to eq('red')
         | 
| 642 | 
            +
                  end
         | 
| 643 | 
            +
                end
         | 
| 644 | 
            +
             | 
| 645 | 
            +
                # Case 4
         | 
| 646 | 
            +
                context 'no base field with an extension field' do
         | 
| 647 | 
            +
                  let(:klass) do
         | 
| 648 | 
            +
                    Class.new(Protobuf::Message) do
         | 
| 649 | 
            +
                      optional :string, :".boom.foo", 2, :extension => true
         | 
| 650 | 
            +
                    end
         | 
| 651 | 
            +
                  end
         | 
| 652 | 
            +
             | 
| 653 | 
            +
                  it 'has an accessor for foo that refers to the extension field' do
         | 
| 654 | 
            +
                    message = klass.new('.boom.foo' => 'bam')
         | 
| 655 | 
            +
                    expect(message.foo).to eq('bam')
         | 
| 656 | 
            +
                    expect(message[:foo]).to eq('bam')
         | 
| 657 | 
            +
                    expect(message['foo']).to eq('bam')
         | 
| 658 | 
            +
                    expect(message[:'.boom.foo']).to eq('bam')
         | 
| 659 | 
            +
                    expect(message['.boom.foo']).to eq('bam')
         | 
| 660 | 
            +
                  end
         | 
| 661 | 
            +
                end
         | 
| 662 | 
            +
              end
         | 
| 663 | 
            +
             | 
| 664 | 
            +
              describe '.[]=' do
         | 
| 665 | 
            +
                context 'clearing fields' do
         | 
| 666 | 
            +
                  it 'clears repeated fields with an empty array' do
         | 
| 667 | 
            +
                    instance = ::Test::Resource.new(:repeated_enum => [::Test::StatusType::ENABLED])
         | 
| 668 | 
            +
                    expect(instance.field?(:repeated_enum)).to be(true)
         | 
| 669 | 
            +
                    instance[:repeated_enum] = []
         | 
| 670 | 
            +
                    expect(instance.field?(:repeated_enum)).to be(false)
         | 
| 671 | 
            +
                  end
         | 
| 672 | 
            +
             | 
| 673 | 
            +
                  it 'clears optional fields with nil' do
         | 
| 674 | 
            +
                    instance = ::Test::Resource.new(:name => "Joe")
         | 
| 675 | 
            +
                    expect(instance.field?(:name)).to be(true)
         | 
| 676 | 
            +
                    instance[:name] = nil
         | 
| 677 | 
            +
                    expect(instance.field?(:name)).to be(false)
         | 
| 678 | 
            +
                  end
         | 
| 679 | 
            +
             | 
| 680 | 
            +
                  it 'clears optional extenstion fields with nil' do
         | 
| 681 | 
            +
                    instance = ::Test::Resource.new(:ext_is_searchable => true)
         | 
| 682 | 
            +
                    expect(instance.field?(:ext_is_searchable)).to be(true)
         | 
| 683 | 
            +
                    instance[:ext_is_searchable] = nil
         | 
| 684 | 
            +
                    expect(instance.field?(:ext_is_searchable)).to be(false)
         | 
| 685 | 
            +
                  end
         | 
| 686 | 
            +
                end
         | 
| 687 | 
            +
             | 
| 688 | 
            +
                context 'setting fields' do
         | 
| 689 | 
            +
                  let(:instance) { ::Test::Resource.new }
         | 
| 690 | 
            +
             | 
| 691 | 
            +
                  it 'sets and replaces repeated fields' do
         | 
| 692 | 
            +
                    initial = [::Test::StatusType::ENABLED, ::Test::StatusType::DISABLED]
         | 
| 693 | 
            +
                    instance[:repeated_enum] = initial
         | 
| 694 | 
            +
                    expect(instance[:repeated_enum]).to eq(initial)
         | 
| 695 | 
            +
                    replacement = [::Test::StatusType::DELETED]
         | 
| 696 | 
            +
                    instance[:repeated_enum] = replacement
         | 
| 697 | 
            +
                    expect(instance[:repeated_enum]).to eq(replacement)
         | 
| 698 | 
            +
                  end
         | 
| 699 | 
            +
             | 
| 700 | 
            +
                  it 'sets acceptable optional field values' do
         | 
| 701 | 
            +
                    instance[:name] = "Joe"
         | 
| 702 | 
            +
                    expect(instance[:name]).to eq("Joe")
         | 
| 703 | 
            +
                    instance[1] = "Tom"
         | 
| 704 | 
            +
                    expect(instance[:name]).to eq("Tom")
         | 
| 705 | 
            +
                  end
         | 
| 706 | 
            +
             | 
| 707 | 
            +
                  it 'sets acceptable empty string field values' do
         | 
| 708 | 
            +
                    instance[:name] = ""
         | 
| 709 | 
            +
                    expect(instance.name!).to eq("")
         | 
| 710 | 
            +
                  end
         | 
| 711 | 
            +
             | 
| 712 | 
            +
                  it 'sets acceptable empty message field values' do
         | 
| 713 | 
            +
                    instance = ::Test::Nested.new
         | 
| 714 | 
            +
                    instance[:resource] = {}
         | 
| 715 | 
            +
                    expect(instance.resource!).to eq(::Test::Resource.new)
         | 
| 716 | 
            +
                  end
         | 
| 717 | 
            +
             | 
| 718 | 
            +
                  it 'sets acceptable extension field values' do
         | 
| 719 | 
            +
                    instance[:ext_is_searchable] = true
         | 
| 720 | 
            +
                    expect(instance[:ext_is_searchable]).to eq(true)
         | 
| 721 | 
            +
                    instance[:".test.Searchable.ext_is_searchable"] = false
         | 
| 722 | 
            +
                    expect(instance[:ext_is_searchable]).to eq(false)
         | 
| 723 | 
            +
                    instance[100] = true
         | 
| 724 | 
            +
                    expect(instance[:ext_is_searchable]).to eq(true)
         | 
| 725 | 
            +
                  end
         | 
| 726 | 
            +
                end
         | 
| 727 | 
            +
             | 
| 728 | 
            +
                context 'throwing TypeError' do
         | 
| 729 | 
            +
                  let(:instance) { ::Test::Resource.new }
         | 
| 730 | 
            +
             | 
| 731 | 
            +
                  it 'throws when a repeated value is set with a non array' do
         | 
| 732 | 
            +
                    expect { instance[:repeated_enum] = "string" }.to raise_error(TypeError)
         | 
| 733 | 
            +
                  end
         | 
| 734 | 
            +
             | 
| 735 | 
            +
                  it 'throws when a repeated value is set with an array of the wrong type' do
         | 
| 736 | 
            +
                    expect { instance[:repeated_enum] = [true, false] }.to raise_error(TypeError)
         | 
| 737 | 
            +
                  end
         | 
| 738 | 
            +
             | 
| 739 | 
            +
                  it 'throws when an optional value is not #acceptable?' do
         | 
| 740 | 
            +
                    expect { instance[:name] = 1 }.to raise_error(TypeError)
         | 
| 741 | 
            +
                  end
         | 
| 742 | 
            +
                end
         | 
| 743 | 
            +
             | 
| 744 | 
            +
                context 'ignoring unknown fields' do
         | 
| 745 | 
            +
                  around do |example|
         | 
| 746 | 
            +
                    orig = ::Protobuf.ignore_unknown_fields?
         | 
| 747 | 
            +
                    ::Protobuf.ignore_unknown_fields = true
         | 
| 748 | 
            +
                    example.call
         | 
| 749 | 
            +
                    ::Protobuf.ignore_unknown_fields = orig
         | 
| 750 | 
            +
                  end
         | 
| 751 | 
            +
             | 
| 752 | 
            +
                  context 'with valid fields' do
         | 
| 753 | 
            +
                    let(:values) { { :name => "Jim" } }
         | 
| 754 | 
            +
             | 
| 755 | 
            +
                    it "does not raise an error" do
         | 
| 756 | 
            +
                      expect { ::Test::Resource.new(values) }.to_not raise_error
         | 
| 757 | 
            +
                    end
         | 
| 758 | 
            +
                  end
         | 
| 759 | 
            +
             | 
| 760 | 
            +
                  context 'with non-existent field' do
         | 
| 761 | 
            +
                    let(:values) { { :name => "Jim", :othername => "invalid" } }
         | 
| 762 | 
            +
             | 
| 763 | 
            +
                    it "does not raise an error" do
         | 
| 764 | 
            +
                      expect { ::Test::Resource.new(values) }.to_not raise_error
         | 
| 765 | 
            +
                    end
         | 
| 766 | 
            +
                  end
         | 
| 767 | 
            +
                end
         | 
| 768 | 
            +
             | 
| 769 | 
            +
                context 'not ignoring unknown fields' do
         | 
| 770 | 
            +
                  around do |example|
         | 
| 771 | 
            +
                    orig = ::Protobuf.ignore_unknown_fields?
         | 
| 772 | 
            +
                    ::Protobuf.ignore_unknown_fields = false
         | 
| 773 | 
            +
                    example.call
         | 
| 774 | 
            +
                    ::Protobuf.ignore_unknown_fields = orig
         | 
| 775 | 
            +
                  end
         | 
| 776 | 
            +
             | 
| 777 | 
            +
                  context 'with valid fields' do
         | 
| 778 | 
            +
                    let(:values) { { :name => "Jim" } }
         | 
| 779 | 
            +
             | 
| 780 | 
            +
                    it "does not raise an error" do
         | 
| 781 | 
            +
                      expect { ::Test::Resource.new(values) }.to_not raise_error
         | 
| 782 | 
            +
                    end
         | 
| 783 | 
            +
                  end
         | 
| 784 | 
            +
             | 
| 785 | 
            +
                  context 'with non-existent field' do
         | 
| 786 | 
            +
                    let(:values) { { :name => "Jim", :othername => "invalid" } }
         | 
| 787 | 
            +
             | 
| 788 | 
            +
                    it "raises an error and mentions the erroneous field" do
         | 
| 789 | 
            +
                      expect { ::Test::Resource.new(values) }.to raise_error(::Protobuf::FieldNotDefinedError, /othername/)
         | 
| 790 | 
            +
                    end
         | 
| 791 | 
            +
             | 
| 792 | 
            +
                    context 'with a nil value' do
         | 
| 793 | 
            +
                      let(:values) { { :name => "Jim", :othername => nil } }
         | 
| 794 | 
            +
             | 
| 795 | 
            +
                      it "raises an error and mentions the erroneous field" do
         | 
| 796 | 
            +
                        expect { ::Test::Resource.new(values) }.to raise_error(::Protobuf::FieldNotDefinedError, /othername/)
         | 
| 797 | 
            +
                      end
         | 
| 798 | 
            +
                    end
         | 
| 799 | 
            +
                  end
         | 
| 800 | 
            +
                end
         | 
| 801 | 
            +
              end
         | 
| 537 802 | 
             
            end
         |