google-gax 0.10.2 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 042b5b8369bf9dd8599b15f142f6608fbd7d2eb2
4
- data.tar.gz: 1982637288109d3c84bd27d531f0736a8060ce27
3
+ metadata.gz: 87b2e27818073928a99f7edc7a49ab31a1ff05a6
4
+ data.tar.gz: bbe86ff3f6584127ace5d22509c59bb1be0b7e60
5
5
  SHA512:
6
- metadata.gz: f0cd057e35054c328494dab34bad86eeb47b90cbe762489be0e3f37598a52bed9097572d9b77a46ccc587fbdf35148a9e4e66e7a671571754a360063e55c5b6f
7
- data.tar.gz: 619f3cea1620d36159a1cc51f15899f4b7c608a6cb4a20044c8472ef9ccb84d0cc4c352d4b6b5e69e187907d9dcdc52720f6c4c8ddd6523b8bd48fc5909456b8
6
+ metadata.gz: 108eb512cbf772cb7b0fd1196b9676ef594bb7ecbdab2038f4e307e9e1d20289b7a108d4031a28545c8110468adc23c2ffbccdafa57e311a00f152a6afe32db6
7
+ data.tar.gz: 37fb30807ae24551812160303d18ead970587dacb30c53e1a01708eee42ac77e6b4ff5c68b322470c34f0e8a0f04ac98505c4ecb1aab00632bdd31a274cbdd08
@@ -168,7 +168,7 @@ module Google
168
168
  # @yield [Page] Gives the pages in the stream.
169
169
  # @raise [GaxError] if it's not started yet.
170
170
  def each_page
171
- raise GaxError, 'not started!' unless started?
171
+ raise GaxError.new('not started!') unless started?
172
172
  yield @page
173
173
  loop do
174
174
  break unless next_page?
@@ -254,8 +254,9 @@ module Google
254
254
  end
255
255
  begin
256
256
  api_caller.call(api_call, request, this_settings)
257
- rescue *settings.errors
258
- raise GaxError, 'RPC failed'
257
+ rescue *settings.errors => e
258
+ error_class = Google::Gax.from_error e
259
+ raise error_class.new('RPC failed')
259
260
  end
260
261
  end
261
262
  end
@@ -348,15 +349,15 @@ module Google
348
349
  rescue => exception
349
350
  unless exception.respond_to?(:code) &&
350
351
  retry_options.retry_codes.include?(exception.code)
351
- raise RetryError, 'Exception occurred in retry method that ' \
352
- 'was not classified as transient'
352
+ raise RetryError.new('Exception occurred in retry method that ' \
353
+ 'was not classified as transient')
353
354
  end
354
355
  sleep(rand(delay) / MILLIS_PER_SECOND)
355
356
  now = Time.now
356
357
  delay = [delay * delay_mult, max_delay].min
357
358
  timeout = [timeout * timeout_mult, max_timeout, deadline - now].min
358
359
  if now >= deadline
359
- raise RetryError, 'Retry total timeout exceeded with exception'
360
+ raise RetryError.new('Retry total timeout exceeded with exception')
360
361
  end
361
362
  retry
362
363
  end
@@ -71,8 +71,81 @@ module Google
71
71
  end
72
72
  end
73
73
 
74
+ def from_error(error)
75
+ if error.respond_to? :code
76
+ grpc_error_class_for error.code
77
+ else
78
+ GaxError
79
+ end
80
+ end
81
+
74
82
  # Indicates an error during automatic GAX retrying.
75
83
  class RetryError < GaxError
76
84
  end
85
+
86
+ # Errors corresponding to standard HTTP/gRPC statuses.
87
+ class CanceledError < GaxError
88
+ end
89
+
90
+ class UnknownError < GaxError
91
+ end
92
+
93
+ class InvalidArgumentError < GaxError
94
+ end
95
+
96
+ class DeadlineExceededError < GaxError
97
+ end
98
+
99
+ class NotFoundError < GaxError
100
+ end
101
+
102
+ class AlreadyExistsError < GaxError
103
+ end
104
+
105
+ class PermissionDeniedError < GaxError
106
+ end
107
+
108
+ class ResourceExhaustedError < GaxError
109
+ end
110
+
111
+ class FailedPreconditionError < GaxError
112
+ end
113
+
114
+ class AbortedError < GaxError
115
+ end
116
+
117
+ class OutOfRangeError < GaxError
118
+ end
119
+
120
+ class UnimplementedError < GaxError
121
+ end
122
+
123
+ class InternalError < GaxError
124
+ end
125
+
126
+ class UnavailableError < GaxError
127
+ end
128
+
129
+ class DataLossError < GaxError
130
+ end
131
+
132
+ class UnauthenticatedError < GaxError
133
+ end
134
+
135
+ # @private Identify the subclass for a gRPC error
136
+ # Note: ported from
137
+ # https:/g/github.com/GoogleCloudPlatform/google-cloud-ruby/blob/master/google-cloud-core/lib/google/cloud/errors.rb
138
+ def self.grpc_error_class_for(grpc_error_code)
139
+ # The gRPC status code 0 is for a successful response.
140
+ # So there is no error subclass for a 0 status code, use current class.
141
+ [GaxError, CanceledError, UnknownError, InvalidArgumentError,
142
+ DeadlineExceededError, NotFoundError, AlreadyExistsError,
143
+ PermissionDeniedError, ResourceExhaustedError, FailedPreconditionError,
144
+ AbortedError, OutOfRangeError, UnimplementedError, InternalError,
145
+ UnavailableError, DataLossError,
146
+ UnauthenticatedError][grpc_error_code] || GaxError
147
+ end
148
+
149
+ module_function :from_error
77
150
  end
78
151
  end
@@ -136,9 +136,9 @@ module Google
136
136
  if (channel && chan_creds) ||
137
137
  (channel && updater_proc) ||
138
138
  (chan_creds && updater_proc)
139
- raise ArgumentError, 'Only one of channel, chan_creds, and ' \
139
+ raise ArgumentError.new('Only one of channel, chan_creds, and ' \
140
140
  'updater_proc should be passed into ' \
141
- 'Google::Gax::Grpc#create_stub.'
141
+ 'Google::Gax::Grpc#create_stub.')
142
142
  end
143
143
  end
144
144
 
@@ -254,7 +254,7 @@ module Google
254
254
  until done?
255
255
  sleep(delay)
256
256
  if Time.now >= deadline
257
- raise RetryError, 'Retry total timeout exceeded with exception'
257
+ raise RetryError.new('Retry total timeout exceeded with exception')
258
258
  end
259
259
  delay = [delay * delay_multiplier, max_delay].min
260
260
  reload!
@@ -175,7 +175,7 @@ module Google
175
175
  literal_sym = segment.literal.to_sym
176
176
  unless bindings.key?(literal_sym)
177
177
  msg = "Value for key #{segment.literal} is not provided"
178
- raise(ArgumentError, msg)
178
+ raise ArgumentError.new(msg)
179
179
  end
180
180
  out.concat(PathTemplate.new(bindings[literal_sym]).segments)
181
181
  binding = true
@@ -27,6 +27,8 @@
27
27
  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
28
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
 
30
+ require 'google/protobuf/timestamp_pb'
31
+
30
32
  module Google
31
33
  # Gax defines Google API extensions
32
34
  module Gax
@@ -54,8 +56,9 @@ module Google
54
56
 
55
57
  # Sanity check: input must be a Hash
56
58
  unless hash.is_a? Hash
57
- raise ArgumentError,
58
- "Value #{hash} must be a Hash or a #{message_class.name}"
59
+ raise ArgumentError.new(
60
+ "Value #{hash} must be a Hash or a #{message_class.name}"
61
+ )
59
62
  end
60
63
  hash = coerce_submessages(hash, message_class)
61
64
  message_class.new(hash)
@@ -79,6 +82,9 @@ module Google
79
82
  field_descriptor = message_descriptor.lookup(key.to_s)
80
83
  if field_descriptor && field_descriptor.type == :message
81
84
  coerced[key] = coerce_submessage(val, field_descriptor)
85
+ elsif field_descriptor && field_descriptor.type == :bytes &&
86
+ (val.is_a?(IO) || val.is_a?(StringIO))
87
+ coerced[key] = val.binmode.read
82
88
  else
83
89
  # `google/protobuf` should throw an error if no field descriptor is
84
90
  # found. Simply pass through.
@@ -101,6 +107,9 @@ module Google
101
107
  def coerce_submessage(val, field_descriptor)
102
108
  if (field_descriptor.label == :repeated) && !(map_field? field_descriptor)
103
109
  coerce_array(val, field_descriptor)
110
+ elsif field_descriptor.subtype.msgclass == Google::Protobuf::Timestamp &&
111
+ val.is_a?(Time)
112
+ time_to_timestamp(val)
104
113
  else
105
114
  coerce(val, field_descriptor)
106
115
  end
@@ -118,7 +127,7 @@ module Google
118
127
  # @return [Array<Object>] The coerced version of the given values.
119
128
  def coerce_array(array, field_descriptor)
120
129
  unless array.is_a? Array
121
- raise ArgumentError, 'Value ' + array.to_s + ' must be an array'
130
+ raise ArgumentError.new('Value ' + array.to_s + ' must be an array')
122
131
  end
123
132
  array.map do |val|
124
133
  coerce(val, field_descriptor)
@@ -150,8 +159,31 @@ module Google
150
159
  to_proto(val, field_descriptor.subtype.msgclass)
151
160
  end
152
161
 
162
+ # Utility for converting a Google::Protobuf::Timestamp instance to a Ruby
163
+ # time.
164
+ #
165
+ # @param timestamp [Google::Protobuf::Timestamp] The timestamp to be
166
+ # converted.
167
+ #
168
+ # @return [Time] The converted Time.
169
+ def timestamp_to_time(timestamp)
170
+ Time.at(timestamp.nanos * 10**-9 + timestamp.seconds)
171
+ end
172
+
173
+ # Utility for converting a Ruby Time instance to a
174
+ # Google::Protobuf::Timestamp.
175
+ #
176
+ # @param time [Time] The Time to be converted.
177
+ #
178
+ # @return [Google::Protobuf::Timestamp] The converted
179
+ # Google::Protobuf::Timestamp.
180
+ def time_to_timestamp(time)
181
+ Google::Protobuf::Timestamp.new(seconds: time.to_i, nanos: time.nsec)
182
+ end
183
+
153
184
  module_function :to_proto, :coerce_submessages, :coerce_submessage,
154
- :coerce_array, :coerce, :map_field?
185
+ :coerce_array, :coerce, :map_field?, :timestamp_to_time,
186
+ :time_to_timestamp
155
187
  private_class_method :coerce_submessages, :coerce_submessage, :coerce_array,
156
188
  :coerce, :map_field?
157
189
  end
@@ -29,6 +29,6 @@
29
29
 
30
30
  module Google
31
31
  module Gax
32
- VERSION = '0.10.2'.freeze
32
+ VERSION = '1.0.0'.freeze
33
33
  end
34
34
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2017, Google Inc. All rights reserved.
1
+ # Copyright 2017, Google LLC All rights reserved.
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
4
  # modification, are permitted provided that the following conditions are
@@ -10,7 +10,7 @@
10
10
  # copyright notice, this list of conditions and the following disclaimer
11
11
  # in the documentation and/or other materials provided with the
12
12
  # distribution.
13
- # * Neither the name of Google Inc. nor the names of its
13
+ # * Neither the name of Google LLC nor the names of its
14
14
  # contributors may be used to endorse or promote products derived from
15
15
  # this software without specific prior written permission.
16
16
  #
@@ -83,6 +83,7 @@ module Google
83
83
  ALL_SCOPES = [
84
84
  ].freeze
85
85
 
86
+
86
87
  # @param credentials [Google::Auth::Credentials, String, Hash, GRPC::Core::Channel, GRPC::Core::ChannelCredentials, Proc]
87
88
  # Provides the means for authenticating requests made by the client. This parameter can
88
89
  # be many types.
@@ -108,11 +109,6 @@ module Google
108
109
  # @param timeout [Numeric]
109
110
  # The default timeout, in seconds, for calls made through this client.
110
111
  def initialize \
111
- service_path: self.class::SERVICE_ADDRESS,
112
- port: self.class::DEFAULT_SERVICE_PORT,
113
- channel: nil,
114
- chan_creds: nil,
115
- updater_proc: nil,
116
112
  credentials: nil,
117
113
  scopes: ALL_SCOPES,
118
114
  client_config: {},
@@ -125,17 +121,6 @@ module Google
125
121
  require "google/gax/grpc"
126
122
  require "google/longrunning/operations_services_pb"
127
123
 
128
- if channel || chan_creds || updater_proc
129
- warn "The `channel`, `chan_creds`, and `updater_proc` parameters will be removed " \
130
- "on 2017/09/08"
131
- credentials ||= channel
132
- credentials ||= chan_creds
133
- credentials ||= updater_proc
134
- end
135
- if port != DEFAULT_SERVICE_PORT
136
- warn "the `port` parameter is deprecated and will be removed"
137
- end
138
-
139
124
  credentials ||= Google::Auth::Credentials.default(scopes: scopes)
140
125
 
141
126
  if credentials.is_a?(String) || credentials.is_a?(Hash)
@@ -154,9 +139,11 @@ module Google
154
139
  updater_proc = credentials.updater_proc
155
140
  end
156
141
 
142
+ package_version = Gem.loaded_specs['google-gax'].version.version
143
+
157
144
  google_api_client = "gl-ruby/#{RUBY_VERSION}"
158
145
  google_api_client << " #{lib_name}/#{lib_version}" if lib_name
159
- google_api_client << " gapic/0.6.8 gax/#{Google::Gax::VERSION}"
146
+ google_api_client << " gapic/#{package_version} gax/#{Google::Gax::VERSION}"
160
147
  google_api_client << " grpc/#{GRPC::VERSION}"
161
148
  google_api_client.freeze
162
149
 
@@ -176,6 +163,10 @@ module Google
176
163
  kwargs: headers
177
164
  )
178
165
  end
166
+
167
+ # Allow overriding the service path/port in subclasses.
168
+ service_path = self.class::SERVICE_ADDRESS
169
+ port = self.class::DEFAULT_SERVICE_PORT
179
170
  @operations_stub = Google::Gax::Grpc.create_stub(
180
171
  service_path,
181
172
  port,
@@ -15,6 +15,8 @@ syntax = "proto3";
15
15
 
16
16
  package google.protobuf;
17
17
 
18
+ import "google/protobuf/timestamp.proto";
19
+
18
20
  message Request {
19
21
  string name = 1;
20
22
  User user = 2;
@@ -29,6 +31,8 @@ message User {
29
31
  UserType type = 2;
30
32
  repeated Post posts = 3;
31
33
  map<string, string> map_field = 4;
34
+ bytes bytes_field = 5;
35
+ google.protobuf.Timestamp timestamp = 6;
32
36
  }
33
37
 
34
38
  message Post {
@@ -0,0 +1 @@
1
+ This is a text file.
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'google/protobuf'
5
5
 
6
+ require 'google/protobuf/timestamp_pb'
6
7
  Google::Protobuf::DescriptorPool.generated_pool.build do
7
8
  add_message "google.protobuf.Request" do
8
9
  optional :name, :string, 1
@@ -13,6 +14,8 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
13
14
  optional :type, :enum, 2, "google.protobuf.User.UserType"
14
15
  repeated :posts, :message, 3, "google.protobuf.Post"
15
16
  map :map_field, :string, :string, 4
17
+ optional :bytes_field, :bytes, 5
18
+ optional :timestamp, :message, 6, "google.protobuf.Timestamp"
16
19
  end
17
20
  add_enum "google.protobuf.User.UserType" do
18
21
  value :UNSPECIFIED, 0
@@ -39,8 +39,8 @@ class CustomException < StandardError
39
39
  end
40
40
  end
41
41
 
42
- FAKE_STATUS_CODE_1 = :FAKE_STATUS_CODE_1
43
- FAKE_STATUS_CODE_2 = :FAKE_STATUS_CODE_2
42
+ FAKE_STATUS_CODE_1 = 1
43
+ FAKE_STATUS_CODE_2 = 2
44
44
 
45
45
  # Google::Gax::CallSettings is private, only accessible in the module context.
46
46
  # For testing purpose, this makes a toplevel ::CallSettings point to the same
@@ -158,7 +158,7 @@ describe Google::Gax do
158
158
  # A dummy api call that raises an exception
159
159
  def raise_exc
160
160
  proc do |_|
161
- raise Google::Gax::GaxError, 'Raised in a test'
161
+ raise Google::Gax::GaxError.new('Raised in a test')
162
162
  end
163
163
  end
164
164
 
@@ -67,7 +67,7 @@ describe Google::Gax::GaxError do
67
67
  it 'presents GRPC::BadStatus values' do
68
68
  error = wrapped_badstatus(3, 'invalid')
69
69
 
70
- expect(error).to be_an_instance_of(Google::Gax::GaxError)
70
+ expect(error).to be_a_kind_of(Google::Gax::GaxError)
71
71
  expect(error.message).to eq('GaxError 3:invalid, caused by 3:invalid')
72
72
  expect(error.code).to eq(3)
73
73
  expect(error.details).to eq('invalid')
@@ -93,7 +93,7 @@ describe Google::Gax::GaxError do
93
93
  'grpc-status-details-bin' => encoded_status_detail }
94
94
  error = wrapped_badstatus(1, 'cancelled', metadata)
95
95
 
96
- expect(error).to be_an_instance_of(Google::Gax::GaxError)
96
+ expect(error).to be_a_kind_of(Google::Gax::GaxError)
97
97
  expect(error.message).to eq('GaxError 1:cancelled, caused by 1:cancelled')
98
98
  expect(error.code).to eq(1)
99
99
  expect(error.details).to eq('cancelled')
@@ -108,10 +108,107 @@ describe Google::Gax::GaxError do
108
108
  end
109
109
  end
110
110
 
111
+ describe '#from_error' do
112
+ it 'identifies CanceledError' do
113
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(1, 'cancelled')
114
+ expect(mapped_error).to eq Google::Gax::CanceledError
115
+ end
116
+
117
+ it 'identifies UnknownError' do
118
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(2, 'unknown')
119
+ expect(mapped_error).to eq Google::Gax::UnknownError
120
+ end
121
+
122
+ it 'identifies InvalidArgumentError' do
123
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(3, 'invalid')
124
+ expect(mapped_error).to eq Google::Gax::InvalidArgumentError
125
+ end
126
+
127
+ it 'identifies DeadlineExceededError' do
128
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(4, 'exceeded')
129
+ expect(mapped_error).to eq Google::Gax::DeadlineExceededError
130
+ end
131
+
132
+ it 'identifies NotFoundError' do
133
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(5, 'not found')
134
+ expect(mapped_error).to eq Google::Gax::NotFoundError
135
+ end
136
+
137
+ it 'identifies AlreadyExistsError' do
138
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(6, 'exists')
139
+ expect(mapped_error).to eq Google::Gax::AlreadyExistsError
140
+ end
141
+
142
+ it 'identifies PermissionDeniedError' do
143
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(7, 'denied')
144
+ expect(mapped_error).to eq Google::Gax::PermissionDeniedError
145
+ end
146
+
147
+ it 'identifies ResourceExhaustedError' do
148
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(8, 'exhausted')
149
+ expect(mapped_error).to eq Google::Gax::ResourceExhaustedError
150
+ end
151
+
152
+ it 'identifies FailedPreconditionError' do
153
+ mapped_error =
154
+ Google::Gax.from_error GRPC::BadStatus.new(9, 'precondition')
155
+ expect(mapped_error).to eq Google::Gax::FailedPreconditionError
156
+ end
157
+
158
+ it 'identifies AbortedError' do
159
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(10, 'aborted')
160
+ expect(mapped_error).to eq Google::Gax::AbortedError
161
+ end
162
+
163
+ it 'identifies OutOfRangeError' do
164
+ mapped_error =
165
+ Google::Gax.from_error GRPC::BadStatus.new(11, 'out of range')
166
+ expect(mapped_error).to eq Google::Gax::OutOfRangeError
167
+ end
168
+
169
+ it 'identifies UnimplementedError' do
170
+ mapped_error =
171
+ Google::Gax.from_error GRPC::BadStatus.new(12, 'unimplemented')
172
+ expect(mapped_error).to eq Google::Gax::UnimplementedError
173
+ end
174
+
175
+ it 'identifies InternalError' do
176
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(13, 'internal')
177
+ expect(mapped_error).to eq Google::Gax::InternalError
178
+ end
179
+
180
+ it 'identifies UnavailableError' do
181
+ mapped_error =
182
+ Google::Gax.from_error GRPC::BadStatus.new(14, 'unavailable')
183
+ expect(mapped_error).to eq Google::Gax::UnavailableError
184
+ end
185
+
186
+ it 'identifies DataLossError' do
187
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(15, 'data loss')
188
+ expect(mapped_error).to eq Google::Gax::DataLossError
189
+ end
190
+
191
+ it 'identifies UnauthenticatedError' do
192
+ mapped_error =
193
+ Google::Gax.from_error GRPC::BadStatus.new(16, 'unauthenticated')
194
+ expect(mapped_error).to eq Google::Gax::UnauthenticatedError
195
+ end
196
+
197
+ it 'identifies unknown error' do
198
+ # We don't know what to map this error case to
199
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(0, 'unknown')
200
+ expect(mapped_error).to eq Google::Gax::GaxError
201
+
202
+ mapped_error = Google::Gax.from_error GRPC::BadStatus.new(17, 'unknown')
203
+ expect(mapped_error).to eq Google::Gax::GaxError
204
+ end
205
+ end
206
+
111
207
  def wrap_with_gax_error(err)
112
208
  raise err
113
209
  rescue => e
114
- raise Google::Gax::GaxError, e.message
210
+ klass = Google::Gax.from_error(e)
211
+ raise klass.new(e.message)
115
212
  end
116
213
 
117
214
  def wrapped_error(msg)
@@ -29,7 +29,9 @@
29
29
 
30
30
  require 'google/gax'
31
31
  require 'google/protobuf/any_pb'
32
+ require 'google/protobuf/timestamp_pb'
32
33
  require 'spec/fixtures/fixture_pb'
34
+ require 'stringio'
33
35
 
34
36
  describe Google::Gax do
35
37
  describe '#to_proto' do
@@ -110,6 +112,38 @@ describe Google::Gax do
110
112
  end
111
113
  end
112
114
 
115
+ it 'handles IO instances' do
116
+ file = File.new('spec/fixtures/fixture_file.txt')
117
+ request_hash = {
118
+ bytes_field: file
119
+ }
120
+ user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
121
+ expect(user.bytes_field).to eq("This is a text file.\n")
122
+ end
123
+
124
+ it 'handles StringIO instances' do
125
+ expected = 'This is a StringIO.'
126
+ string_io = StringIO.new(expected)
127
+ request_hash = {
128
+ bytes_field: string_io
129
+ }
130
+ user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
131
+ expect(user.bytes_field).to eq(expected)
132
+ end
133
+
134
+ it 'auto-coerces Time' do
135
+ seconds = 271_828_182
136
+ nanos = 845_904_523
137
+ # Fixnum, not float, for precision
138
+ sometime = seconds + nanos * 10**-9
139
+ request_hash = {
140
+ timestamp: Time.at(sometime)
141
+ }
142
+ user = Google::Gax.to_proto(request_hash, Google::Protobuf::User)
143
+ expected = Google::Protobuf::Timestamp.new(seconds: seconds, nanos: nanos)
144
+ expect(user.timestamp).to eq(expected)
145
+ end
146
+
113
147
  it 'fails if a key does not exist in the target message type' do
114
148
  user_hash = {
115
149
  name: USER_NAME,
@@ -135,4 +169,31 @@ describe Google::Gax do
135
169
  end.to raise_error(ArgumentError)
136
170
  end
137
171
  end
172
+
173
+ describe 'time-timestamp conversion' do
174
+ SECONDS = 271_828_182
175
+ NANOS = 845_904_523
176
+ A_TIME = Time.at(SECONDS + NANOS * 10**-9)
177
+ A_TIMESTAMP =
178
+ Google::Protobuf::Timestamp.new(seconds: SECONDS, nanos: NANOS)
179
+
180
+ it 'converts time to timestamp' do
181
+ expect(Google::Gax.time_to_timestamp(A_TIME)).to eq A_TIMESTAMP
182
+ end
183
+
184
+ it 'converts timestamp to time' do
185
+ expect(Google::Gax.timestamp_to_time(A_TIMESTAMP)).to eq A_TIME
186
+ end
187
+
188
+ it 'is an identity when conversion is a round trip' do
189
+ expect(
190
+ Google::Gax.timestamp_to_time(Google::Gax.time_to_timestamp(A_TIME))
191
+ ).to eq A_TIME
192
+ expect(
193
+ Google::Gax.time_to_timestamp(
194
+ Google::Gax.timestamp_to_time(A_TIMESTAMP)
195
+ )
196
+ ).to eq A_TIMESTAMP
197
+ end
198
+ end
138
199
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-gax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google API Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-01 00:00:00.000000000 Z
11
+ date: 2017-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: googleauth
@@ -184,6 +184,7 @@ files:
184
184
  - lib/google/longrunning/operations_client.rb
185
185
  - lib/google/longrunning/operations_client_config.json
186
186
  - spec/fixtures/fixture.proto
187
+ - spec/fixtures/fixture_file.txt
187
188
  - spec/fixtures/fixture_pb.rb
188
189
  - spec/google/gax/api_callable_spec.rb
189
190
  - spec/google/gax/bundling_spec.rb
@@ -214,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
215
  version: '0'
215
216
  requirements: []
216
217
  rubyforge_project:
217
- rubygems_version: 2.4.8
218
+ rubygems_version: 2.6.12
218
219
  signing_key:
219
220
  specification_version: 4
220
221
  summary: Aids the development of APIs for clients and servers based on GRPC and Google