protobuf 3.5.5 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGES.md +16 -0
  4. data/lib/protobuf/cli.rb +3 -1
  5. data/lib/protobuf/enum.rb +1 -0
  6. data/lib/protobuf/field/base_field.rb +1 -0
  7. data/lib/protobuf/field/varint_field.rb +16 -1
  8. data/lib/protobuf/message.rb +6 -7
  9. data/lib/protobuf/message/serialization.rb +0 -4
  10. data/lib/protobuf/rpc/connectors/ping.rb +87 -0
  11. data/lib/protobuf/rpc/connectors/zmq.rb +5 -16
  12. data/lib/protobuf/version.rb +1 -1
  13. data/spec/benchmark/tasks.rb +2 -1
  14. data/spec/encoding/all_types_spec.rb +28 -27
  15. data/spec/encoding/extreme_values_spec.rb +0 -0
  16. data/spec/functional/class_inheritance_spec.rb +1 -1
  17. data/spec/functional/socket_server_spec.rb +1 -1
  18. data/spec/functional/zmq_server_spec.rb +1 -1
  19. data/spec/lib/protobuf/field_spec.rb +1 -1
  20. data/spec/lib/protobuf/generators/base_spec.rb +2 -0
  21. data/spec/lib/protobuf/message_spec.rb +6 -4
  22. data/spec/lib/protobuf/rpc/client_spec.rb +1 -1
  23. data/spec/lib/protobuf/rpc/connectors/ping_spec.rb +69 -0
  24. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +6 -13
  25. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +1 -1
  26. data/spec/lib/protobuf/rpc/service_spec.rb +1 -1
  27. data/spec/lib/protobuf_spec.rb +1 -1
  28. data/spec/spec_helper.rb +5 -7
  29. data/spec/support/{test → protos}/all_types.data.bin +0 -0
  30. data/spec/support/{test → protos}/all_types.data.txt +0 -0
  31. data/spec/support/{test → protos}/enum.pb.rb +1 -1
  32. data/spec/support/{test → protos}/enum.proto +3 -1
  33. data/spec/support/{test → protos}/extreme_values.data.bin +0 -0
  34. data/spec/support/protos/google_unittest.bin +0 -0
  35. data/spec/support/{test → protos}/google_unittest.pb.rb +318 -77
  36. data/spec/support/{test → protos}/google_unittest.proto +230 -66
  37. data/spec/support/{test → protos}/google_unittest_import.pb.rb +13 -6
  38. data/spec/support/{test → protos}/google_unittest_import.proto +19 -10
  39. data/spec/support/protos/google_unittest_import_public.pb.rb +24 -0
  40. data/spec/support/{test → protos}/google_unittest_import_public.proto +8 -5
  41. data/spec/support/{test → protos}/multi_field_extensions.pb.rb +0 -0
  42. data/spec/support/{test → protos}/multi_field_extensions.proto +2 -0
  43. data/spec/support/{test → protos}/resource.pb.rb +0 -0
  44. data/spec/support/{test → protos}/resource.proto +2 -0
  45. data/spec/support/{test/resource_service.rb → resource_service.rb} +1 -1
  46. data/spec/support/server.rb +2 -1
  47. metadata +111 -160
  48. data/spec/data/data.bin +0 -3
  49. data/spec/data/types.bin +0 -0
  50. data/spec/support/test/defaults.pb.rb +0 -27
  51. data/spec/support/test/defaults.proto +0 -9
  52. data/spec/support/test/extended.pb.rb +0 -24
  53. data/spec/support/test/extended.proto +0 -10
  54. data/spec/support/test/google_unittest_import_public.pb.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37b8ae0a1e0e242f6e59627e2237e34e046e1ddc
4
- data.tar.gz: 64fd74dede3374c1ca631e05f3cc9c2261e9f81d
3
+ metadata.gz: 465d9557f2fe2a77ba7cffce41ecd05e4b051dc0
4
+ data.tar.gz: ad19416fb9d66c5282e892d9a8f4da9f1a6df4c1
5
5
  SHA512:
6
- metadata.gz: 83f929f8fd8a65cfd6e2e5c77218b96df98220335063847b2c1bb7cd1c0cd2207ddc4b0a06781f3a5f915fbe882e352961e04b6244cc7228b3947557a7230316
7
- data.tar.gz: 4cbc7cc6f211c1290aa9b7ff3a7477f8d503e79cf8a4b6530eeb48a1390538897ee22390a9b0adcbe8b81fdcc652789795d2694a4a3675e063c7001dfbeca07d
6
+ metadata.gz: 929245c25d77547a57ad94ab417d2cc9f3d249574b1fd0187159f6a23604b3c73b5fb495baaf13fae798c570293d09612013f98ce1971da62e790d2ad4b897f7
7
+ data.tar.gz: 11dada3beee45ba720383766fffe623b1c5c910c0a688771d2d23840c51239d1c26cebb3af502a84cc568684444fad9c3c05679e9e743b0d84ed8577682e18b9
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ before_install:
2
2
  - sudo apt-get update -qq
3
3
  - sudo apt-get install -y libzmq3-dev
4
4
  - sudo -E ./install-protobuf.sh
5
+ - gem update bundler
5
6
  language: ruby
6
7
  rvm:
7
8
  - 1.9.3
data/CHANGES.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Stable (3.x)
2
2
 
3
+ 3.5.5
4
+ --------
5
+ - Add native Varint for MRI.
6
+
7
+ 3.5.4
8
+ --------
9
+ - Ensures ActiveSupport::Deprecation does not get a stack trace when deprecations are disabled.
10
+
11
+ 3.5.3
12
+ --------
13
+ - Optimized get_extension_field and get_field calls.
14
+
15
+ 3.5.2
16
+ --------
17
+ - Optimized valid_tag?, enums_for_tag and enums_for_tags
18
+
3
19
  3.5.1
4
20
  --------
5
21
  - Adds compatibility for Rails 4.2+ as CLI options were broken
data/lib/protobuf/cli.rb CHANGED
@@ -39,7 +39,7 @@ module Protobuf
39
39
  option :broadcast_beacons, :type => :boolean, :desc => 'Broadcast beacons for dynamic discovery (Currently only available with ZeroMQ).'
40
40
  option :broadcast_busy, :type => :boolean, :default => false, :desc => 'Remove busy nodes from cluster when all workers are busy (Currently only available with ZeroMQ).'
41
41
  option :debug, :type => :boolean, :default => false, :aliases => %w(-d), :desc => 'Debug Mode. Override log level to DEBUG.'
42
- option :gc_pause_request, :type => :boolean, :default => false, :desc => 'Enable/Disable GC pause during request.'
42
+ option :gc_pause_request, :type => :boolean, :default => false, :desc => 'DEPRECATED: Enable/Disable GC pause during request.'
43
43
  option :print_deprecation_warnings, :type => :boolean, :default => nil, :desc => 'Cause use of deprecated fields to be printed or ignored.'
44
44
  option :workers_only, :type => :boolean, :default => false, :desc => "Starts process with only workers (no broker/frontend is started) only relevant for Zmq Server"
45
45
  option :worker_port, :type => :numeric, :default => nil, :desc => "Port for 'backend' where workers connect (defaults to port + 1)"
@@ -80,6 +80,8 @@ module Protobuf
80
80
 
81
81
  # If we pause during request we don't need to pause in serialization
82
82
  def configure_gc
83
+ say "DEPRECATED: The gc_pause_request option is deprecated and will be removed in 4.0." if options.gc_pause_request?
84
+
83
85
  debug_say('Configuring gc')
84
86
 
85
87
  if defined?(JRUBY_VERSION)
data/lib/protobuf/enum.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'delegate'
2
+ require 'protobuf/deprecation'
2
3
  require 'protobuf/optionable'
3
4
 
4
5
  ##
@@ -1,3 +1,4 @@
1
+ require 'protobuf/deprecation'
1
2
  require 'protobuf/field/field_array'
2
3
  require 'protobuf/logging'
3
4
  require 'protobuf/wire_type'
@@ -8,6 +8,7 @@ module Protobuf
8
8
  # Constants
9
9
  #
10
10
 
11
+ CACHE_LIMIT = 1024
11
12
  INT32_MAX = 2**31 - 1
12
13
  INT32_MIN = -2**31
13
14
  INT64_MAX = 2**63 - 1
@@ -23,7 +24,16 @@ module Protobuf
23
24
  0
24
25
  end
25
26
 
26
- def self.encode(value)
27
+ # Because all tags and enums are calculated as VarInt it is "most common" to have
28
+ # values < CACHE_LIMIT (low numbers) which is defaulting to 1024
29
+ def self.cached_varint(value)
30
+ @_varint_cache ||= {}
31
+ (@_varint_cache[value] ||= encode(value, false)).dup
32
+ end
33
+
34
+ def self.encode(value, use_cache = true)
35
+ return cached_varint(value) if use_cache && value >= 0 && value <= CACHE_LIMIT
36
+
27
37
  bytes = []
28
38
  until value < 128
29
39
  bytes << (0x80 | (value & 0x7f))
@@ -32,6 +42,11 @@ module Protobuf
32
42
  (bytes << value).pack('C*')
33
43
  end
34
44
 
45
+ # Load the cache of VarInts on load of file
46
+ (0..CACHE_LIMIT).to_a.each do |cached_value|
47
+ cached_varint(cached_value)
48
+ end
49
+
35
50
  ##
36
51
  # Public Instance Methods
37
52
  #
@@ -1,4 +1,5 @@
1
1
  require 'protobuf/field'
2
+ require 'protobuf/deprecation'
2
3
  require 'protobuf/enum'
3
4
  require 'protobuf/exceptions'
4
5
  require 'protobuf/message/fields'
@@ -73,6 +74,8 @@ module Protobuf
73
74
  # Iterate over every field, invoking the given block
74
75
  #
75
76
  def each_field
77
+ return to_enum(:each_field) unless block_given?
78
+
76
79
  self.class.all_fields.each do |field|
77
80
  value = __send__(field.getter)
78
81
  yield(field, value)
@@ -81,15 +84,11 @@ module Protobuf
81
84
 
82
85
  def each_field_for_serialization
83
86
  self.class.all_fields.each do |field|
84
- next unless field_must_be_serialized?(field)
85
-
86
87
  value = @values[field.getter]
88
+ fail ::Protobuf::SerializationError, "Required field #{self.class.name}##{field.name} does not have a value." if value.nil? && field.required?
89
+ next if value.nil?
87
90
 
88
- if value.nil?
89
- fail ::Protobuf::SerializationError, "Required field #{self.class.name}##{field.name} does not have a value."
90
- else
91
- yield(field, value)
92
- end
91
+ yield(field, value)
93
92
  end
94
93
  end
95
94
 
@@ -75,10 +75,6 @@ module Protobuf
75
75
 
76
76
  private
77
77
 
78
- def field_must_be_serialized?(field)
79
- field.required? || ! @values[field.name].nil?
80
- end
81
-
82
78
  def set_field_bytes(tag, bytes)
83
79
  field = self.class.get_field(tag, true)
84
80
  field.set(self, bytes) if field
@@ -0,0 +1,87 @@
1
+ require "socket"
2
+
3
+ module Protobuf
4
+ module Rpc
5
+ module Connectors
6
+ class Ping
7
+ attr_reader :host, :port
8
+
9
+ def initialize(host, port)
10
+ @host = host
11
+ @port = port
12
+ end
13
+
14
+ def online?
15
+ socket = tcp_socket
16
+ socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_LINGER, [1, 0].pack('ii'))
17
+
18
+ true
19
+ rescue
20
+ false
21
+ ensure
22
+ begin
23
+ socket && socket.close
24
+ rescue IOError
25
+ nil
26
+ end
27
+ end
28
+
29
+ def timeout
30
+ @timeout ||= begin
31
+ if ::ENV.key?("PB_RPC_PING_PORT_TIMEOUT")
32
+ ::ENV["PB_RPC_PING_PORT_TIMEOUT"].to_i
33
+ else
34
+ 5 # 5 seconds
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+
41
+ def tcp_socket
42
+ # Reference: http://stackoverflow.com/a/21014439/1457934
43
+ socket = ::Socket.new(family, ::Socket::SOCK_STREAM, 0)
44
+ socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
45
+ socket.connect_nonblock(sockaddr)
46
+ rescue ::IO::WaitWritable
47
+ # IO.select will block until the socket is writable or the timeout
48
+ # is exceeded - whichever comes first.
49
+ if ::IO.select(nil, [socket], nil, timeout)
50
+ begin
51
+ # Verify there is now a good connection
52
+ socket.connect_nonblock(sockaddr)
53
+ rescue ::Errno::EISCONN
54
+ # Socket is connected.
55
+ socket
56
+ rescue
57
+ # An unexpected exception was raised - the connection is no good.
58
+ socket.close
59
+ raise
60
+ end
61
+ else
62
+ # IO.select returns nil when the socket is not ready before timeout
63
+ # seconds have elapsed
64
+ socket.close
65
+ raise "Connection Timeout"
66
+ end
67
+ end
68
+
69
+ def family
70
+ @family ||= ::Socket.const_get(addrinfo[0][0])
71
+ end
72
+
73
+ def addrinfo
74
+ @addrinfo ||= ::Socket.getaddrinfo(host, nil)
75
+ end
76
+
77
+ def ip
78
+ @ip ||= addrinfo[0][3]
79
+ end
80
+
81
+ def sockaddr
82
+ @sockaddr ||= ::Socket.pack_sockaddr_in(port, ip)
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -1,6 +1,7 @@
1
- require 'thread_safe'
2
- require 'protobuf/rpc/connectors/base'
3
- require 'protobuf/rpc/service_directory'
1
+ require "thread_safe"
2
+ require "protobuf/rpc/connectors/base"
3
+ require "protobuf/rpc/connectors/ping"
4
+ require "protobuf/rpc/service_directory"
4
5
 
5
6
  module Protobuf
6
7
  module Rpc
@@ -161,19 +162,7 @@ module Protobuf
161
162
  end
162
163
 
163
164
  def ping_port_open?(host)
164
- socket = TCPSocket.new(host, ping_port.to_i)
165
- socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
166
- socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_LINGER, [1, 0].pack('ii'))
167
-
168
- true
169
- rescue
170
- false
171
- ensure
172
- begin
173
- socket && socket.close
174
- rescue IOError
175
- nil
176
- end
165
+ Ping.new(host, ping_port.to_i).online?
177
166
  end
178
167
 
179
168
  def rcv_timeout
@@ -1,3 +1,3 @@
1
1
  module Protobuf
2
- VERSION = '3.5.5'
2
+ VERSION = '3.6.0'
3
3
  end
@@ -1,7 +1,8 @@
1
1
  require 'benchmark'
2
2
  require 'protobuf/socket'
3
3
  require 'support/all'
4
- require 'support/test/resource_service'
4
+ require 'spec_helper'
5
+ require SUPPORT_PATH.join('resource_service')
5
6
 
6
7
  case RUBY_ENGINE.to_sym
7
8
  when :ruby
@@ -1,8 +1,9 @@
1
1
  require 'spec_helper'
2
+ require PROTOS_PATH.join('google_unittest.pb')
2
3
 
3
4
  RSpec.describe ::Protobuf do
4
5
  it "correctly encodes all types" do
5
- message = GoogleUnittest::TestAllTypes.new(
6
+ message = Protobuf_unittest::TestAllTypes.new(
6
7
  :optional_int32 => 101,
7
8
  :optional_int64 => 102,
8
9
  :optional_uint32 => 103,
@@ -18,16 +19,16 @@ RSpec.describe ::Protobuf do
18
19
  :optional_bool => true,
19
20
  :optional_string => "115",
20
21
  :optional_bytes => "116",
21
- :optional_nested_message => GoogleUnittest::TestAllTypes::NestedMessage.new(:bb => 118),
22
- :optional_foreign_message => GoogleUnittest::ForeignMessage.new(:c => 119),
23
- :optional_import_message => GoogleUnittestImport::ImportMessage.new(:d => 120),
24
- :optional_nested_enum => GoogleUnittest::TestAllTypes::NestedEnum::BAZ,
25
- :optional_foreign_enum => GoogleUnittest::ForeignEnum::FOREIGN_BAZ,
26
- :optional_import_enum => GoogleUnittestImport::ImportEnum::IMPORT_BAZ,
22
+ :optional_nested_message => Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 118),
23
+ :optional_foreign_message => Protobuf_unittest::ForeignMessage.new(:c => 119),
24
+ :optional_import_message => Protobuf_unittest_import::ImportMessage.new(:d => 120),
25
+ :optional_nested_enum => Protobuf_unittest::TestAllTypes::NestedEnum::BAZ,
26
+ :optional_foreign_enum => Protobuf_unittest::ForeignEnum::FOREIGN_BAZ,
27
+ :optional_import_enum => Protobuf_unittest_import::ImportEnum::IMPORT_BAZ,
27
28
  :optional_string_piece => "124",
28
29
  :optional_cord => "125",
29
- :optional_public_import_message => GoogleUnittestImport::PublicImportMessage.new(:e => 126),
30
- :optional_lazy_message => GoogleUnittest::TestAllTypes::NestedMessage.new(:bb => 127),
30
+ :optional_public_import_message => Protobuf_unittest_import::PublicImportMessage.new(:e => 126),
31
+ :optional_lazy_message => Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 127),
31
32
  :repeated_int32 => [201, 301],
32
33
  :repeated_int64 => [202, 302],
33
34
  :repeated_uint32 => [203, 303],
@@ -44,34 +45,34 @@ RSpec.describe ::Protobuf do
44
45
  :repeated_string => ["215", "315"],
45
46
  :repeated_bytes => ["216", "316"],
46
47
  :repeated_nested_message => [
47
- ::GoogleUnittest::TestAllTypes::NestedMessage.new(:bb => 218),
48
- ::GoogleUnittest::TestAllTypes::NestedMessage.new(:bb => 318),
48
+ ::Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 218),
49
+ ::Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 318),
49
50
  ],
50
51
  :repeated_foreign_message => [
51
- ::GoogleUnittest::ForeignMessage.new(:c => 219),
52
- ::GoogleUnittest::ForeignMessage.new(:c => 319),
52
+ ::Protobuf_unittest::ForeignMessage.new(:c => 219),
53
+ ::Protobuf_unittest::ForeignMessage.new(:c => 319),
53
54
  ],
54
55
  :repeated_import_message => [
55
- ::GoogleUnittestImport::ImportMessage.new(:d => 220),
56
- ::GoogleUnittestImport::ImportMessage.new(:d => 320),
56
+ ::Protobuf_unittest_import::ImportMessage.new(:d => 220),
57
+ ::Protobuf_unittest_import::ImportMessage.new(:d => 320),
57
58
  ],
58
59
  :repeated_nested_enum => [
59
- ::GoogleUnittest::TestAllTypes::NestedEnum::BAR,
60
- ::GoogleUnittest::TestAllTypes::NestedEnum::BAZ,
60
+ ::Protobuf_unittest::TestAllTypes::NestedEnum::BAR,
61
+ ::Protobuf_unittest::TestAllTypes::NestedEnum::BAZ,
61
62
  ],
62
63
  :repeated_foreign_enum => [
63
- ::GoogleUnittest::ForeignEnum::FOREIGN_BAR,
64
- ::GoogleUnittest::ForeignEnum::FOREIGN_BAZ,
64
+ ::Protobuf_unittest::ForeignEnum::FOREIGN_BAR,
65
+ ::Protobuf_unittest::ForeignEnum::FOREIGN_BAZ,
65
66
  ],
66
67
  :repeated_import_enum => [
67
- ::GoogleUnittestImport::ImportEnum::IMPORT_BAR,
68
- ::GoogleUnittestImport::ImportEnum::IMPORT_BAZ,
68
+ ::Protobuf_unittest_import::ImportEnum::IMPORT_BAR,
69
+ ::Protobuf_unittest_import::ImportEnum::IMPORT_BAZ,
69
70
  ],
70
71
  :repeated_string_piece => ["224", "324"],
71
72
  :repeated_cord => ["225", "325"],
72
73
  :repeated_lazy_message => [
73
- ::GoogleUnittest::TestAllTypes::NestedMessage.new(:bb => 227),
74
- ::GoogleUnittest::TestAllTypes::NestedMessage.new(:bb => 327),
74
+ ::Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 227),
75
+ ::Protobuf_unittest::TestAllTypes::NestedMessage.new(:bb => 327),
75
76
  ],
76
77
  :default_int32 => 401,
77
78
  :default_int64 => 402,
@@ -88,14 +89,14 @@ RSpec.describe ::Protobuf do
88
89
  :default_bool => false,
89
90
  :default_string => "415",
90
91
  :default_bytes => "416",
91
- :default_nested_enum => ::GoogleUnittest::TestAllTypes::NestedEnum::FOO,
92
- :default_foreign_enum => ::GoogleUnittest::ForeignEnum::FOREIGN_FOO,
93
- :default_import_enum => ::GoogleUnittestImport::ImportEnum::IMPORT_FOO,
92
+ :default_nested_enum => ::Protobuf_unittest::TestAllTypes::NestedEnum::FOO,
93
+ :default_foreign_enum => ::Protobuf_unittest::ForeignEnum::FOREIGN_FOO,
94
+ :default_import_enum => ::Protobuf_unittest_import::ImportEnum::IMPORT_FOO,
94
95
  :default_string_piece => "424",
95
96
  :default_cord => "425",
96
97
  )
97
98
 
98
- data_file_path = File.expand_path('../../support/test/all_types.data.bin', __FILE__)
99
+ data_file_path = PROTOS_PATH.join('all_types.data.bin')
99
100
  data = File.open(data_file_path, 'rb', &:read)
100
101
  expect(data).to eq(message.serialize_to_string)
101
102
  end
Binary file
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'spec/support/test/resource_service'
2
+ require SUPPORT_PATH.join('resource_service')
3
3
 
4
4
  RSpec.describe 'works through class inheritance' do
5
5
  module Corp
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'spec/support/test/resource_service'
2
+ require SUPPORT_PATH.join('resource_service')
3
3
 
4
4
  RSpec.describe 'Functional Socket Client' do
5
5
  before(:all) do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'spec/support/test/resource_service'
4
3
  require 'protobuf/rpc/service_directory'
4
+ require SUPPORT_PATH.join('resource_service')
5
5
 
6
6
  RSpec.describe 'Functional ZMQ Client' do
7
7
  before(:all) do
@@ -182,7 +182,7 @@ RSpec.describe ::Protobuf::Field do
182
182
  it 'raises an ArgumentError' do
183
183
  expect do
184
184
  subject.field_class("boom")
185
- end.to raise_error
185
+ end.to raise_error(ArgumentError)
186
186
  end
187
187
  end
188
188
 
@@ -74,6 +74,8 @@ RSpec.describe ::Protobuf::Generators::Base do
74
74
 
75
75
  context 'when tags are missing in the range' do
76
76
  it 'prints a warning' do
77
+ allow(ENV).to receive(:key?).and_call_original
78
+ allow(ENV).to receive(:key?).with("PB_NO_TAG_WARNINGS").and_return(false)
77
79
  expect(::Protobuf::CodeGenerator).to receive(:print_tag_warning_suppress)
78
80
  expect(::Protobuf::CodeGenerator).to receive(:warn).with(/FooBar object should have 5 tags \(1\.\.5\), but found 4 tags/)
79
81
  described_class.validate_tags("FooBar", [1, 2, 4, 5])