stripe 5.1.1 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3317e27f361af5e5506ab608ccdc9c18b3746c76e6244a5db15b149135b7deee
4
- data.tar.gz: 65f8bd1faf0c64125bfd0badeb835e555cf3a23437bf8d62c3101058b153de76
3
+ metadata.gz: 0ec1d1414aafc87b63dca172263ecd4666467cda2ab39eaac1abdbd13e7cd90b
4
+ data.tar.gz: 3adde22d80c8f867e34d2735dd0aea142f0b69e6cd2a84e13fe7c6a53655ee85
5
5
  SHA512:
6
- metadata.gz: b5123ec85b0009c8ae4b3ae7c3532fc59f6501abaaf350f106cd0e64f9d2fec221bd54ca9384636edec370922391d48ceafdb044394a1367a45fdef4e372888e
7
- data.tar.gz: 5fa03e4c45c1b1e82b617fb50f79339740e3c431a0fefbda0c6af78ce4bb0e1e2539ae67b9494fc5fa694ccec1c8444772f179c6f283f6cc6ea20abe71eb850f
6
+ metadata.gz: e4086cfa6bc5281bf1e31e88a2435156d6928716d7022e319afe5845157571731ad260c3728c6bf021d593f11727fa6fdba06c26667d7d5774b6a29cfadf9829
7
+ data.tar.gz: 4b6477d988e90607c8ad8c1d8a4a11e3f0afb3494948403d2b6b9e23cde4a6be0dcb9779100306c28449e6d7d24876043edcc2239ab00cdb1dc7fd88942b57de
@@ -19,8 +19,17 @@ Layout/IndentFirstHashElement:
19
19
  Layout/IndentHeredoc:
20
20
  Enabled: false
21
21
 
22
+ Metrics/BlockLength:
23
+ Max: 40
24
+ Exclude:
25
+ # `context` in tests are blocks and get quite large, so exclude the test
26
+ # directory from having to adhere to this rule.
27
+ - "test/**/*.rb"
28
+
22
29
  Metrics/ClassLength:
23
30
  Exclude:
31
+ # Test classes get quite large, so exclude the test directory from having
32
+ # to adhere to this rule.
24
33
  - "test/**/*.rb"
25
34
 
26
35
  Metrics/LineLength:
@@ -10,12 +10,6 @@
10
10
  Metrics/AbcSize:
11
11
  Max: 51
12
12
 
13
- # Offense count: 33
14
- # Configuration parameters: CountComments, ExcludedMethods.
15
- # ExcludedMethods: refine
16
- Metrics/BlockLength:
17
- Max: 509
18
-
19
13
  # Offense count: 12
20
14
  # Configuration parameters: CountComments.
21
15
  Metrics/ClassLength:
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.2.0 - 2019-09-19
4
+ * [#851](https://github.com/stripe/stripe-ruby/pull/851) Introduce system for garbage collecting connection managers
5
+
3
6
  ## 5.1.1 - 2019-09-04
4
7
  * [#845](https://github.com/stripe/stripe-ruby/pull/845) Transfer the request_id from the http_headers to error.
5
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 5.1.1
1
+ 5.2.0
@@ -9,24 +9,35 @@ module Stripe
9
9
  #
10
10
  # Note that this class in itself is *not* thread safe. We expect it to be
11
11
  # instantiated once per thread.
12
- #
13
- # Note also that this class doesn't currently clean up after itself because
14
- # it expects to only ever have a few connections (unless `.clear` is called
15
- # manually). It'd be possible to tank memory by constantly changing the value
16
- # of `Stripe.api_base` or the like. A possible improvement might be to detect
17
- # and prune old connections whenever a request is executed.
18
12
  class ConnectionManager
13
+ # Timestamp indicating when the connection manager last made a request.
14
+ # This is used by `StripeClient` to determine whether a connection manager
15
+ # should be garbage collected or not.
16
+ attr_reader :last_used
17
+
19
18
  def initialize
20
19
  @active_connections = {}
20
+ @last_used = Time.now
21
+
22
+ # A connection manager may be accessed across threads as one thread makes
23
+ # requests on it while another is trying to clear it (either because it's
24
+ # trying to garbage collect the manager or trying to clear it because a
25
+ # configuration setting has changed). That's probably thread-safe already
26
+ # because of Ruby's GIL, but just in case the library's running on JRuby
27
+ # or the like, use a mutex to synchronize access in this connection
28
+ # manager.
29
+ @mutex = Mutex.new
21
30
  end
22
31
 
23
32
  # Finishes any active connections by closing their TCP connection and
24
33
  # clears them from internal tracking.
25
34
  def clear
26
- @active_connections.each do |_, connection|
27
- connection.finish
35
+ @mutex.synchronize do
36
+ @active_connections.each do |_, connection|
37
+ connection.finish
38
+ end
39
+ @active_connections = {}
28
40
  end
29
- @active_connections = {}
30
41
  end
31
42
 
32
43
  # Gets a connection for a given URI. This is for internal use only as it's
@@ -35,17 +46,19 @@ module Stripe
35
46
  #
36
47
  # `uri` is expected to be a string.
37
48
  def connection_for(uri)
38
- u = URI.parse(uri)
39
- connection = @active_connections[[u.host, u.port]]
49
+ @mutex.synchronize do
50
+ u = URI.parse(uri)
51
+ connection = @active_connections[[u.host, u.port]]
40
52
 
41
- if connection.nil?
42
- connection = create_connection(u)
43
- connection.start
53
+ if connection.nil?
54
+ connection = create_connection(u)
55
+ connection.start
44
56
 
45
- @active_connections[[u.host, u.port]] = connection
46
- end
57
+ @active_connections[[u.host, u.port]] = connection
58
+ end
47
59
 
48
- connection
60
+ connection
61
+ end
49
62
  end
50
63
 
51
64
  # Executes an HTTP request to the given URI with the given method. Also
@@ -65,6 +78,8 @@ module Stripe
65
78
  raise ArgumentError, "query should be a string" \
66
79
  if query && !query.is_a?(String)
67
80
 
81
+ @last_used = Time.now
82
+
68
83
  connection = connection_for(uri)
69
84
 
70
85
  u = URI.parse(uri)
@@ -74,7 +89,9 @@ module Stripe
74
89
  u.path
75
90
  end
76
91
 
77
- connection.send_request(method.to_s.upcase, path, body, headers)
92
+ @mutex.synchronize do
93
+ connection.send_request(method.to_s.upcase, path, body, headers)
94
+ end
78
95
  end
79
96
 
80
97
  #
@@ -5,18 +5,17 @@ module Stripe
5
5
  # recover both a resource a call returns as well as a response object that
6
6
  # contains information on the HTTP call.
7
7
  class StripeClient
8
- # A set of all known connection managers across all threads and a mutex to
8
+ # A set of all known thread contexts across all threads and a mutex to
9
9
  # synchronize global access to them.
10
- @all_connection_managers = []
11
- @all_connection_managers_mutex = Mutex.new
10
+ @thread_contexts_with_connection_managers = []
11
+ @thread_contexts_with_connection_managers_mutex = Mutex.new
12
+ @last_connection_manager_gc = Time.now
12
13
 
13
- attr_accessor :connection_manager
14
-
15
- # Initializes a new `StripeClient`. Expects a `ConnectionManager` object,
16
- # and uses a default connection manager unless one is passed.
17
- def initialize(connection_manager = nil)
18
- self.connection_manager = connection_manager ||
19
- self.class.default_connection_manager
14
+ # Initializes a new `StripeClient`.
15
+ #
16
+ # Takes a connection manager object for backwards compatibility only, and
17
+ # that use is DEPRECATED.
18
+ def initialize(_connection_manager = nil)
20
19
  @system_profiler = SystemProfiler.new
21
20
  @last_request_metrics = nil
22
21
  end
@@ -42,17 +41,24 @@ module Stripe
42
41
  # Just a quick path for when configuration is being set for the first
43
42
  # time before any connections have been opened. There is technically some
44
43
  # potential for thread raciness here, but not in a practical sense.
45
- return if @all_connection_managers.empty?
46
-
47
- @all_connection_managers_mutex.synchronize do
48
- @all_connection_managers.each(&:clear)
44
+ return if @thread_contexts_with_connection_managers.empty?
45
+
46
+ @thread_contexts_with_connection_managers_mutex.synchronize do
47
+ @thread_contexts_with_connection_managers.each do |thread_context|
48
+ # Note that the thread context itself is not destroyed, but we clear
49
+ # its connection manager and remove our reference to it. If it ever
50
+ # makes a new request we'll give it a new connection manager and
51
+ # it'll go back into `@thread_contexts_with_connection_managers`.
52
+ thread_context.default_connection_manager.clear
53
+ thread_context.default_connection_manager = nil
54
+ end
55
+ @thread_contexts_with_connection_managers.clear
49
56
  end
50
57
  end
51
58
 
52
59
  # A default client for the current thread.
53
60
  def self.default_client
54
- current_thread_context.default_client ||=
55
- StripeClient.new(default_connection_manager)
61
+ current_thread_context.default_client ||= StripeClient.new
56
62
  end
57
63
 
58
64
  # A default connection manager for the current thread.
@@ -60,8 +66,9 @@ module Stripe
60
66
  current_thread_context.default_connection_manager ||= begin
61
67
  connection_manager = ConnectionManager.new
62
68
 
63
- @all_connection_managers_mutex.synchronize do
64
- @all_connection_managers << connection_manager
69
+ @thread_contexts_with_connection_managers_mutex.synchronize do
70
+ maybe_gc_connection_managers
71
+ @thread_contexts_with_connection_managers << current_thread_context
65
72
  end
66
73
 
67
74
  connection_manager
@@ -131,6 +138,15 @@ module Stripe
131
138
  sleep_seconds
132
139
  end
133
140
 
141
+ # Gets the connection manager in use for the current `StripeClient`.
142
+ #
143
+ # This method is DEPRECATED and for backwards compatibility only.
144
+ def connection_manager
145
+ self.class.default_connection_manager
146
+ end
147
+ extend Gem::Deprecate
148
+ deprecate :connection_manager, :none, 2020, 9
149
+
134
150
  # Executes the API call within the given block. Usage looks like:
135
151
  #
136
152
  # client = StripeClient.new
@@ -207,10 +223,10 @@ module Stripe
207
223
  context.query = query
208
224
 
209
225
  http_resp = execute_request_with_rescues(method, api_base, context) do
210
- connection_manager.execute_request(method, url,
211
- body: body,
212
- headers: headers,
213
- query: query)
226
+ self.class.default_connection_manager.execute_request(method, url,
227
+ body: body,
228
+ headers: headers,
229
+ query: query)
214
230
  end
215
231
 
216
232
  begin
@@ -233,6 +249,14 @@ module Stripe
233
249
  # private
234
250
  #
235
251
 
252
+ # Time (in seconds) that a connection manager has not been used before it's
253
+ # eligible for garbage collection.
254
+ CONNECTION_MANAGER_GC_LAST_USED_EXPIRY = 120
255
+
256
+ # How often to check (in seconds) for connection managers that haven't been
257
+ # used in a long time and which should be garbage collected.
258
+ CONNECTION_MANAGER_GC_PERIOD = 60
259
+
236
260
  ERROR_MESSAGE_CONNECTION =
237
261
  "Unexpected error communicating when trying to connect to " \
238
262
  "Stripe (%s). You may be seeing this message because your DNS is not " \
@@ -320,6 +344,46 @@ module Stripe
320
344
  Thread.current[:stripe_client__internal_use_only] ||= ThreadContext.new
321
345
  end
322
346
 
347
+ # Garbage collects connection managers that haven't been used in some time,
348
+ # with the idea being that we want to remove old connection managers that
349
+ # belong to dead threads and the like.
350
+ #
351
+ # Prefixed with `maybe_` because garbage collection will only run
352
+ # periodically so that we're not constantly engaged in busy work. If
353
+ # connection managers live a little passed their useful age it's not
354
+ # harmful, so it's not necessary to get them right away.
355
+ #
356
+ # For testability, returns `nil` if it didn't run and the number of
357
+ # connection managers that were garbage collected otherwise.
358
+ #
359
+ # IMPORTANT: This method is not thread-safe and expects to be called inside
360
+ # a lock on `@thread_contexts_with_connection_managers_mutex`.
361
+ #
362
+ # For internal use only. Does not provide a stable API and may be broken
363
+ # with future non-major changes.
364
+ def self.maybe_gc_connection_managers
365
+ if @last_connection_manager_gc + CONNECTION_MANAGER_GC_PERIOD > Time.now
366
+ return nil
367
+ end
368
+
369
+ last_used_threshold = Time.now - CONNECTION_MANAGER_GC_LAST_USED_EXPIRY
370
+
371
+ pruned_thread_contexts = []
372
+ @thread_contexts_with_connection_managers.each do |thread_context|
373
+ connection_manager = thread_context.default_connection_manager
374
+ next if connection_manager.last_used > last_used_threshold
375
+
376
+ connection_manager.clear
377
+ thread_context.default_connection_manager = nil
378
+ pruned_thread_contexts << thread_context
379
+ end
380
+
381
+ @thread_contexts_with_connection_managers -= pruned_thread_contexts
382
+ @last_connection_manager_gc = Time.now
383
+
384
+ pruned_thread_contexts.count
385
+ end
386
+
323
387
  private def api_url(url = "", api_base = nil)
324
388
  (api_base || Stripe.api_base) + url
325
389
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Stripe
4
- VERSION = "5.1.1"
4
+ VERSION = "5.2.0"
5
5
  end
@@ -8,6 +8,15 @@ module Stripe
8
8
  @manager = Stripe::ConnectionManager.new
9
9
  end
10
10
 
11
+ context "#initialize" do
12
+ should "set #last_used to current time" do
13
+ t = Time.new(2019)
14
+ Timecop.freeze(t) do
15
+ assert_equal t, Stripe::ConnectionManager.new.last_used
16
+ end
17
+ end
18
+ end
19
+
11
20
  context "#clear" do
12
21
  should "clear any active connections" do
13
22
  stub_request(:post, "#{Stripe.api_base}/path")
@@ -133,6 +142,25 @@ module Stripe
133
142
  end
134
143
  assert_equal e.message, "query should be a string"
135
144
  end
145
+
146
+ should "set #last_used to current time" do
147
+ stub_request(:post, "#{Stripe.api_base}/path")
148
+ .to_return(body: JSON.generate(object: "account"))
149
+
150
+ t = Time.new(2019)
151
+
152
+ # Make sure the connection manager is initialized at a different time
153
+ # than the one we're going to measure at because `#last_used` is also
154
+ # set by the constructor.
155
+ manager = Timecop.freeze(t) do
156
+ Stripe::ConnectionManager.new
157
+ end
158
+
159
+ Timecop.freeze(t + 1) do
160
+ manager.execute_request(:post, "#{Stripe.api_base}/path")
161
+ assert_equal t + 1, manager.last_used
162
+ end
163
+ end
136
164
  end
137
165
  end
138
166
  end
@@ -17,6 +17,60 @@ module Stripe
17
17
  end
18
18
  end
19
19
 
20
+ context ".maybe_gc_connection_managers" do
21
+ should "garbage collect old connection managers when appropriate" do
22
+ stub_request(:post, "#{Stripe.api_base}/v1/path")
23
+ .to_return(body: JSON.generate(object: "account"))
24
+
25
+ # Make sure we start with a blank slate (state may have been left in
26
+ # place by other tests).
27
+ StripeClient.clear_all_connection_managers
28
+
29
+ # Establish a base time.
30
+ t = Time.new(2019)
31
+
32
+ # And pretend that `StripeClient` was just initialized for the first
33
+ # time. (Don't access instance variables like this, but it's tricky to
34
+ # test properly otherwise.)
35
+ StripeClient.instance_variable_set(:@last_connection_manager_gc, t)
36
+
37
+ Timecop.freeze(t) do
38
+ # Execute an initial request to ensure that a connection manager was
39
+ # created.
40
+ client = StripeClient.new
41
+ client.execute_request(:post, "/v1/path")
42
+
43
+ # The GC shouldn't run yet (a `nil` return indicates that GC didn't run).
44
+ assert_equal nil, StripeClient.maybe_gc_connection_managers
45
+ end
46
+
47
+ # Move time to just *before* garbage collection is eligible to run.
48
+ # Nothing should happen.
49
+ Timecop.freeze(t + StripeClient::CONNECTION_MANAGER_GC_PERIOD - 1) do
50
+ assert_equal nil, StripeClient.maybe_gc_connection_managers
51
+ end
52
+
53
+ # Move time to just *after* garbage collection is eligible to run.
54
+ # Garbage collection will run, but because the connection manager is
55
+ # not passed its expiry age, it will not be collected. Zero is returned
56
+ # to indicate so.
57
+ Timecop.freeze(t + StripeClient::CONNECTION_MANAGER_GC_PERIOD + 1) do
58
+ assert_equal 0, StripeClient.maybe_gc_connection_managers
59
+ end
60
+
61
+ # Move us far enough into the future that we're passed the horizons for
62
+ # both a GC run as well as well as the expiry age of a connection
63
+ # manager. That means the GC will run and collect the connection
64
+ # manager that we created above.
65
+ Timecop.freeze(t + StripeClient::CONNECTION_MANAGER_GC_LAST_USED_EXPIRY + 1) do
66
+ assert_equal 1, StripeClient.maybe_gc_connection_managers
67
+
68
+ # And as an additional check, the connection manager of the current thread context should have been set to `nil` as it was GCed.
69
+ assert_nil StripeClient.current_thread_context.default_connection_manager
70
+ end
71
+ end
72
+ end
73
+
20
74
  context ".clear_all_connection_managers" do
21
75
  should "clear connection managers across all threads" do
22
76
  stub_request(:post, "#{Stripe.api_base}/path")
@@ -199,20 +253,6 @@ module Stripe
199
253
  end
200
254
  end
201
255
 
202
- context "#initialize" do
203
- should "set Stripe.default_connection_manager" do
204
- client = StripeClient.new
205
- assert_equal StripeClient.default_connection_manager,
206
- client.connection_manager
207
- end
208
-
209
- should "set a different connection if one was specified" do
210
- connection_manager = ConnectionManager.new
211
- client = StripeClient.new(connection_manager)
212
- assert_equal connection_manager, client.connection_manager
213
- end
214
- end
215
-
216
256
  context "#execute_request" do
217
257
  context "headers" do
218
258
  should "support literal headers" do
@@ -470,10 +510,10 @@ module Stripe
470
510
  .to_return(body: "", status: 500)
471
511
 
472
512
  client = StripeClient.new
513
+
473
514
  e = assert_raises Stripe::APIError do
474
515
  client.execute_request(:post, "/v1/charges")
475
516
  end
476
-
477
517
  assert_equal 'Invalid response object from API: "" (HTTP response code was 500)', e.message
478
518
  end
479
519
 
@@ -482,22 +522,36 @@ module Stripe
482
522
  .to_return(body: "", status: 200)
483
523
 
484
524
  client = StripeClient.new
525
+
485
526
  e = assert_raises Stripe::APIError do
486
527
  client.execute_request(:post, "/v1/charges")
487
528
  end
488
-
489
529
  assert_equal 'Invalid response object from API: "" (HTTP response code was 200)', e.message
490
530
  end
491
531
 
532
+ should "feed a request ID through to the error object" do
533
+ stub_request(:post, "#{Stripe.api_base}/v1/charges")
534
+ .to_return(body: JSON.generate(make_missing_id_error),
535
+ headers: { "Request-ID": "req_123" },
536
+ status: 400)
537
+
538
+ client = StripeClient.new
539
+
540
+ e = assert_raises Stripe::InvalidRequestError do
541
+ client.execute_request(:post, "/v1/charges")
542
+ end
543
+ assert_equal("req_123", e.request_id)
544
+ end
545
+
492
546
  should "handle low level error" do
493
547
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
494
548
  .to_raise(Errno::ECONNREFUSED.new)
495
549
 
496
550
  client = StripeClient.new
551
+
497
552
  e = assert_raises Stripe::APIConnectionError do
498
553
  client.execute_request(:post, "/v1/charges")
499
554
  end
500
-
501
555
  assert_equal StripeClient::ERROR_MESSAGE_CONNECTION % Stripe.api_base +
502
556
  "\n\n(Network error: Connection refused)",
503
557
  e.message
@@ -508,10 +562,10 @@ module Stripe
508
562
  .to_return(body: JSON.generate(bar: "foo"), status: 500)
509
563
 
510
564
  client = StripeClient.new
565
+
511
566
  e = assert_raises Stripe::APIError do
512
567
  client.execute_request(:post, "/v1/charges")
513
568
  end
514
-
515
569
  assert_equal 'Invalid response object from API: "{\"bar\":\"foo\"}" (HTTP response code was 500)', e.message
516
570
  end
517
571
 
@@ -521,6 +575,7 @@ module Stripe
521
575
 
522
576
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
523
577
  .to_return(body: JSON.generate(data), status: 400)
578
+
524
579
  client = StripeClient.new
525
580
 
526
581
  e = assert_raises Stripe::IdempotencyError do
@@ -533,75 +588,81 @@ module Stripe
533
588
  should "raise InvalidRequestError on other 400s" do
534
589
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
535
590
  .to_return(body: JSON.generate(make_missing_id_error), status: 400)
591
+
536
592
  client = StripeClient.new
537
- begin
593
+
594
+ e = assert_raises Stripe::InvalidRequestError do
538
595
  client.execute_request(:post, "/v1/charges")
539
- rescue Stripe::InvalidRequestError => e
540
- assert_equal(400, e.http_status)
541
- assert_equal(true, e.json_body.is_a?(Hash))
542
596
  end
597
+ assert_equal(400, e.http_status)
598
+ assert_equal(true, e.json_body.is_a?(Hash))
543
599
  end
544
600
 
545
601
  should "raise AuthenticationError on 401" do
546
602
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
547
603
  .to_return(body: JSON.generate(make_missing_id_error), status: 401)
604
+
548
605
  client = StripeClient.new
549
- begin
606
+
607
+ e = assert_raises Stripe::AuthenticationError do
550
608
  client.execute_request(:post, "/v1/charges")
551
- rescue Stripe::AuthenticationError => e
552
- assert_equal(401, e.http_status)
553
- assert_equal(true, e.json_body.is_a?(Hash))
554
609
  end
610
+ assert_equal(401, e.http_status)
611
+ assert_equal(true, e.json_body.is_a?(Hash))
555
612
  end
556
613
 
557
614
  should "raise CardError on 402" do
558
615
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
559
616
  .to_return(body: JSON.generate(make_invalid_exp_year_error), status: 402)
617
+
560
618
  client = StripeClient.new
561
- begin
619
+
620
+ e = assert_raises Stripe::CardError do
562
621
  client.execute_request(:post, "/v1/charges")
563
- rescue Stripe::CardError => e
564
- assert_equal(402, e.http_status)
565
- assert_equal(true, e.json_body.is_a?(Hash))
566
- assert_equal("invalid_expiry_year", e.code)
567
- assert_equal("exp_year", e.param)
568
622
  end
623
+ assert_equal(402, e.http_status)
624
+ assert_equal(true, e.json_body.is_a?(Hash))
625
+ assert_equal("invalid_expiry_year", e.code)
626
+ assert_equal("exp_year", e.param)
569
627
  end
570
628
 
571
629
  should "raise PermissionError on 403" do
572
630
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
573
631
  .to_return(body: JSON.generate(make_missing_id_error), status: 403)
632
+
574
633
  client = StripeClient.new
575
- begin
634
+
635
+ e = assert_raises Stripe::PermissionError do
576
636
  client.execute_request(:post, "/v1/charges")
577
- rescue Stripe::PermissionError => e
578
- assert_equal(403, e.http_status)
579
- assert_equal(true, e.json_body.is_a?(Hash))
580
637
  end
638
+ assert_equal(403, e.http_status)
639
+ assert_equal(true, e.json_body.is_a?(Hash))
581
640
  end
582
641
 
583
642
  should "raise InvalidRequestError on 404" do
584
643
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
585
644
  .to_return(body: JSON.generate(make_missing_id_error), status: 404)
645
+
586
646
  client = StripeClient.new
587
- begin
647
+
648
+ e = assert_raises Stripe::InvalidRequestError do
588
649
  client.execute_request(:post, "/v1/charges")
589
- rescue Stripe::InvalidRequestError => e
590
- assert_equal(404, e.http_status)
591
- assert_equal(true, e.json_body.is_a?(Hash))
592
650
  end
651
+ assert_equal(404, e.http_status)
652
+ assert_equal(true, e.json_body.is_a?(Hash))
593
653
  end
594
654
 
595
655
  should "raise RateLimitError on 429" do
596
656
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
597
657
  .to_return(body: JSON.generate(make_rate_limit_error), status: 429)
658
+
598
659
  client = StripeClient.new
599
- begin
660
+
661
+ e = assert_raises Stripe::RateLimitError do
600
662
  client.execute_request(:post, "/v1/charges")
601
- rescue Stripe::RateLimitError => e
602
- assert_equal(429, e.http_status)
603
- assert_equal(true, e.json_body.is_a?(Hash))
604
663
  end
664
+ assert_equal(429, e.http_status)
665
+ assert_equal(true, e.json_body.is_a?(Hash))
605
666
  end
606
667
 
607
668
  should "raise OAuth::InvalidRequestError when error is a string with value 'invalid_request'" do
@@ -610,6 +671,7 @@ module Stripe
610
671
  error_description: "No grant type specified"), status: 400)
611
672
 
612
673
  client = StripeClient.new
674
+
613
675
  opts = { api_base: Stripe.connect_base }
614
676
  e = assert_raises Stripe::OAuth::InvalidRequestError do
615
677
  client.execute_request(:post, "/oauth/token", opts)
@@ -625,6 +687,7 @@ module Stripe
625
687
  error_description: "This authorization code has already been used. All tokens issued with this code have been revoked."), status: 400)
626
688
 
627
689
  client = StripeClient.new
690
+
628
691
  opts = { api_base: Stripe.connect_base }
629
692
  e = assert_raises Stripe::OAuth::InvalidGrantError do
630
693
  client.execute_request(:post, "/oauth/token", opts)
@@ -641,6 +704,7 @@ module Stripe
641
704
  error_description: "This application is not connected to stripe account acct_19tLK7DSlTMT26Mk, or that account does not exist."), status: 401)
642
705
 
643
706
  client = StripeClient.new
707
+
644
708
  opts = { api_base: Stripe.connect_base }
645
709
  e = assert_raises Stripe::OAuth::InvalidClientError do
646
710
  client.execute_request(:post, "/oauth/deauthorize", opts)
@@ -657,6 +721,7 @@ module Stripe
657
721
  error_description: "Something."), status: 401)
658
722
 
659
723
  client = StripeClient.new
724
+
660
725
  opts = { api_base: Stripe.connect_base }
661
726
  e = assert_raises Stripe::OAuth::OAuthError do
662
727
  client.execute_request(:post, "/oauth/deauthorize", opts)
@@ -817,6 +882,22 @@ module Stripe
817
882
  end
818
883
  end
819
884
 
885
+ context "#connection_manager" do
886
+ should "warn that #connection_manager is deprecated" do
887
+ old_stderr = $stderr
888
+ $stderr = StringIO.new
889
+ begin
890
+ client = StripeClient.new
891
+ client.connection_manager
892
+ message = "NOTE: Stripe::StripeClient#connection_manager is " \
893
+ "deprecated"
894
+ assert_match Regexp.new(message), $stderr.string
895
+ ensure
896
+ $stderr = old_stderr
897
+ end
898
+ end
899
+ end
900
+
820
901
  context "#request" do
821
902
  should "return a result and response object" do
822
903
  stub_request(:post, "#{Stripe.api_base}/v1/charges")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stripe
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.1
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stripe
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-04 00:00:00.000000000 Z
11
+ date: 2019-09-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Stripe is the easiest way to accept payments online. See https://stripe.com
14
14
  for details.