pact-support 0.5.5 → 0.5.7

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: 8302de9af32aa569443e49a502132233ecc0fbc6
4
- data.tar.gz: d03296b6197757a59b1a8c197b375fb17e3be7d7
3
+ metadata.gz: 8eeb1140d12c89f3c03f855ecfbb9666259b502c
4
+ data.tar.gz: 8b7e7ef1dea78d0abe77c2fb0db5a17f46ee47e9
5
5
  SHA512:
6
- metadata.gz: db57a82df74f57807f6514abad63b30374ebbb81d6aadac107059e9dbef23978d2e94ef2b6a5c30095d5b870a464aea05269bea1ffa96aa030305a2d595c546a
7
- data.tar.gz: 9918d2bd33d4986bfcf67e41ed2a52d1d216bff694df1035f666cef2a933fbaaef37e8d5f82b9d34c3f80b5fab3a6c6434db6e06c15fc01a982bac5bf6f435da
6
+ metadata.gz: 9cbde3f5574d69c3be0b1e8f2fa7cd196e4c2e42133e966a7087d8a4f3796cb21906c93c7d6df5b97a445842031ed713ab1fa96de44f20110a25d3655e64fb49
7
+ data.tar.gz: 09d6fc96eeb2c6fcdce7269392a47a08ba3efa50e927b2fc80e9d41a21197dd4d1e37826ebe211b81ca9c79ad019761462431243385f7a34ff2514414314f71c
@@ -3,5 +3,5 @@ rvm:
3
3
  - 2.0.0
4
4
  - 2.1.8
5
5
  - 2.2.4
6
- - 2.3.0
6
+ - 2.3.1
7
7
  - jruby-9.0.5.0
@@ -2,20 +2,23 @@ Do this to generate your change history
2
2
 
3
3
  git log --pretty=format:' * %h - %s (%an, %ad)' vX.Y.Z..HEAD
4
4
 
5
-
6
- ### 0.5.5 (4 November 2015)
7
- * e9aaff0 - Merge pull request #21 from TakatoshiMaeda/reify_support_nested_something_like (Sergei Matheson, Fri Apr 29 09:54:00 2016 +1000)
5
+ ### 0.5.7 (3 May 2016)
6
+ * 289d4e5 - Handle loading local pact files as well as remote (Sergei Matheson, Tue May 3 12:56:51 2016 +1000)
7
+ * 6d4e559 - Update to ruby 2.3.1 in travis (Sergei Matheson, Tue May 3 10:46:46 2016 +1000)
8
+
9
+ ### 0.5.6 (29 April 2016)
10
+ * d8bc8fa - Remove pull request merge logs from changelog (Sergei Matheson, Fri Apr 29 10:06:51 2016 +1000)
11
+ * 24ba197 - Corrected v0.5.5 release date in CHANGELOG (Sergei Matheson, Fri Apr 29 10:05:11 2016 +1000)
12
+ * 9dcef8d - Retry reading pact file (Taiki Ono, Thu Apr 28 17:15:54 2016 +0900)
13
+ * 61ceda1 - Re-write test with WebMock (Taiki Ono, Thu Apr 28 15:50:29 2016 +0900)
14
+ * 62dcf66 - Use WebMock2 (Taiki Ono, Thu Apr 28 13:51:53 2016 +0900)
15
+
16
+ ### 0.5.5 (29 April 2016)
8
17
  * eb9aa26 - Supporting nested Pact::SomethingLike reification (Takatoshi Maeda, Thu Apr 28 02:04:58 2016 +0900)
9
- * 832790d - Merge pull request #20 from taiki45/dsl-without-block (Sergei Matheson, Thu Mar 24 09:36:22 2016 +1100)
10
18
  * 9e924c8 - Object supporting DSL can be built without block (Taiki Ono, Wed Mar 23 16:38:27 2016 +0900)
11
- * 57aa993 - Merge pull request #18 from taiki45/escape-query-string-component (Sergei Matheson, Tue Mar 15 09:24:36 2016 +1100)
12
19
  * 2b0e7b4 - Escape query string components (Taiki Ono, Mon Mar 14 15:22:29 2016 +0900)
13
20
  * a383368 - Fix indent (Taiki Ono, Mon Mar 14 15:18:26 2016 +0900)
14
- * fae9a14 - Merge pull request #17 from taiki45/upgrade-jruby (Ronald Holshausen, Mon Mar 14 09:56:16 2016 +1100)
15
21
  * dc54092 - Support latest jruby and drop supporting jruby 1.7 (Taiki Ono, Sun Mar 13 20:27:17 2016 +0900)
16
- * 22651e8 - Merge pull request #16 from taiki45/drop-supporting-ruby1.9 (Beth Skurrie, Sat Mar 12 14:04:41 2016 +1100)
17
- * 3dbaa38 - Merge pull request #15 from taiki45/suppress-rspec-warnings (Sergei Matheson, Fri Mar 11 09:29:26 2016 +1100)
18
- * 656c98a - Merge pull request #14 from taiki45/nested-query (Sergei Matheson, Fri Mar 11 09:19:58 2016 +1100)
19
22
  * 85fbb09 - Drop supporting ruby1.9 (Taiki Ono, Thu Mar 10 23:01:54 2016 +0900)
20
23
  * 966fa3a - `raise_error` should be with specific error (Taiki Ono, Thu Mar 10 22:50:13 2016 +0900)
21
24
  * 2861742 - Cosmetic change (Taiki Ono, Thu Mar 10 22:11:51 2016 +0900)
@@ -1,9 +1,22 @@
1
- module Pact
1
+ require 'net/http'
2
2
 
3
+ module Pact
3
4
  module PactFile
4
-
5
5
  extend self
6
6
 
7
+ OPEN_TIMEOUT = 5
8
+ READ_TIMEOUT = 5
9
+ RETRY_LIMIT = 3
10
+
11
+ class HttpError < StandardError
12
+ attr_reader :uri, :response
13
+
14
+ def initialize(uri, response)
15
+ @uri, @response = uri, response
16
+ super("HTTP request failed: status=#{response.code}")
17
+ end
18
+ end
19
+
7
20
  def read uri, options = {}
8
21
  uri_string = uri.to_s
9
22
  pact = render_pact(uri_string, options)
@@ -22,16 +35,74 @@ module Pact
22
35
  ::File.open(Pact.configuration.tmp_dir + "/#{name}", "w") { |file| file << pact}
23
36
  end
24
37
 
25
- def render_pact uri_string, options
38
+ def render_pact(uri_string, options)
26
39
  uri_obj = URI(uri_string)
27
- uri_user_info = uri_obj.userinfo
28
- if(uri_user_info)
40
+ if uri_obj.userinfo
29
41
  options[:username] = uri_obj.user unless options[:username]
30
42
  options[:password] = uri_obj.password unless options[:password]
31
- uri_string = uri_string.sub("#{uri_user_info}@", '')
32
43
  end
33
- open_options = options[:username] ? {http_basic_authentication:[options[:username],options[:password]]} : {}
34
- open(uri_string, open_options) { | file | file.read }
44
+ get(uri_obj, options)
45
+ end
46
+
47
+ private
48
+
49
+ def get(uri, options)
50
+ local?(uri) ? get_local(uri, options) : get_remote_with_retry(uri, options)
51
+ end
52
+
53
+ def local? uri
54
+ !uri.host
55
+ end
56
+
57
+ def get_local(uri, _)
58
+ File.read uri.to_s
59
+ end
60
+
61
+ def get_remote(uri, options)
62
+ request = Net::HTTP::Get.new(uri)
63
+ request.basic_auth(options[:username], options[:password]) if options[:username]
64
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
65
+ http.open_timeout = options[:open_timeout] || OPEN_TIMEOUT
66
+ http.read_timeout = options[:read_timeout] || READ_TIMEOUT
67
+ http.request(request)
68
+ end
69
+ end
70
+
71
+ def get_remote_with_retry(uri, options)
72
+ ((options[:retry_limit] || RETRY_LIMIT) + 1).times do |i|
73
+ begin
74
+ response = get_remote(uri, options)
75
+ case
76
+ when success?(response)
77
+ return response.body
78
+ when retryable?(response)
79
+ raise HttpError.new(uri, response) if abort_retry?(i, options)
80
+ delay_retry(i + 1)
81
+ next
82
+ else
83
+ raise HttpError.new(uri, response)
84
+ end
85
+ rescue Timeout::Error => e
86
+ raise e if abort_retry?(i, options)
87
+ delay_retry(i + 1)
88
+ end
89
+ end
90
+ end
91
+
92
+ def success?(response)
93
+ response.code.to_i == 200
94
+ end
95
+
96
+ def retryable?(response)
97
+ (500...600).cover?(response.code.to_i)
98
+ end
99
+
100
+ def abort_retry?(count, options)
101
+ count >= (options[:retry_limit] || RETRY_LIMIT)
102
+ end
103
+
104
+ def delay_retry(count)
105
+ Kernel.sleep(2 ** count * 0.3)
35
106
  end
36
107
  end
37
- end
108
+ end
@@ -1,5 +1,5 @@
1
1
  module Pact
2
2
  module Support
3
- VERSION = "0.5.5"
3
+ VERSION = "0.5.7"
4
4
  end
5
5
  end
@@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
27
27
  gem.add_runtime_dependency 'thor'
28
28
 
29
29
  gem.add_development_dependency 'rake', '~> 10.0.3'
30
- gem.add_development_dependency 'webmock', '~> 1.18.0'
30
+ gem.add_development_dependency 'webmock', '~> 2.0.0'
31
31
  gem.add_development_dependency 'pry'
32
32
  gem.add_development_dependency 'fakefs', '~> 0.4'
33
33
  gem.add_development_dependency 'hashie', '~> 2.0'
@@ -1,14 +1,36 @@
1
1
  require 'spec_helper'
2
+ require 'tempfile'
2
3
  require 'pact/consumer_contract/pact_file'
4
+ require 'base64' # XXX: https://github.com/bblimke/webmock/pull/611
3
5
 
4
6
  module Pact
5
7
  describe PactFile do
6
8
  describe 'render_pact' do
7
9
  let(:uri_without_userinfo) { 'http://pactbroker.com'}
8
10
  let(:pact_content) { 'api contract'}
11
+
12
+ describe 'from a local file URI' do
13
+ let(:temp_file) { Tempfile.new('local-pact-file') }
14
+ let(:file_uri) { temp_file.path }
15
+ let(:local_pact_content) { 'local pact content' }
16
+ before do
17
+ File.write file_uri, local_pact_content
18
+ end
19
+ after do
20
+ temp_file.unlink
21
+ end
22
+
23
+ it 'reads from the local file system' do
24
+ expect(PactFile.render_pact(file_uri, {})).to eq(local_pact_content)
25
+ end
26
+ end
27
+
9
28
  context 'without basic authentication' do
29
+ before do
30
+ stub_request(:get, uri_without_userinfo).to_return(body: pact_content)
31
+ end
32
+
10
33
  it 'should open uri to get pact file content' do
11
- expect(PactFile).to receive(:open).with(uri_without_userinfo, {}).and_return(pact_content)
12
34
  expect(PactFile.render_pact(uri_without_userinfo, {})).to eq(pact_content)
13
35
  end
14
36
  end
@@ -19,29 +41,140 @@ module Pact
19
41
  let(:options) do
20
42
  { username: username, password: password }
21
43
  end
44
+ before do
45
+ stub_request(:get, uri_without_userinfo).with(basic_auth: [username, password]).to_return(body: pact_content)
46
+ end
47
+
22
48
  context 'when userinfo is specified in the option' do
23
49
  it 'should open uri to get pact file content with userinfo in the options' do
24
- expect(PactFile).to receive(:open).with(uri_without_userinfo, {http_basic_authentication:[username, password]})
25
- .and_return(pact_content)
26
50
  expect(PactFile.render_pact(uri_without_userinfo, options)).to eq(pact_content)
27
51
  end
52
+
28
53
  let(:uri_with_userinfo) { 'http://dummyuser:dummyps@pactbroker.com'}
54
+
29
55
  it 'should use userinfo in options which overwrites userinfo in url' do
30
- expect(PactFile).to receive(:open).with(uri_without_userinfo, {http_basic_authentication:[username, password]})
31
- .and_return(pact_content)
32
56
  expect(PactFile.render_pact(uri_with_userinfo, options)).to eq(pact_content)
33
57
  end
34
58
  end
35
59
 
36
60
  context 'when user info is specified in url' do
37
61
  let(:uri_with_userinfo) { "http://#{username}:#{password}@pactbroker.com"}
62
+
38
63
  it 'should open uri to get pact file content with userinfo in the uri' do
39
- expect(PactFile).to receive(:open).with(uri_without_userinfo, {http_basic_authentication:[username, password]})
40
- .and_return(pact_content)
41
64
  expect(PactFile.render_pact(uri_with_userinfo, {})).to eq(pact_content)
42
65
  end
43
66
  end
44
67
  end
68
+
69
+ describe 'retry feature' do
70
+ before { allow(PactFile).to receive(:delay_retry).with(kind_of(Integer)) }
71
+
72
+ def render_pact(options = {})
73
+ PactFile.render_pact(uri_without_userinfo, options)
74
+ end
75
+
76
+ context 'with client error' do
77
+ before { stub_request(:get, uri_without_userinfo).to_return(status: 400) }
78
+
79
+ it 'raises client error without retrying' do
80
+ expect(PactFile).not_to receive(:delay_retry)
81
+ expect { render_pact }.to raise_error(PactFile::HttpError, /status=400/)
82
+ end
83
+ end
84
+
85
+ context 'with single server error' do
86
+ before do
87
+ stub_request(:get, uri_without_userinfo).to_return(status: 500).
88
+ then.to_return(status: 200, body: pact_content)
89
+ end
90
+
91
+ it 'retries and succeeds' do
92
+ expect(render_pact).to eq(pact_content)
93
+ end
94
+ end
95
+
96
+ context 'with continuous server errors' do
97
+ before { stub_request(:get, uri_without_userinfo).to_return(status: 500) }
98
+
99
+ it 'retries but failed by retry limit' do
100
+ expect { render_pact }.to raise_error(PactFile::HttpError, /status=500/)
101
+ end
102
+ end
103
+
104
+ context 'with single open timeout' do
105
+ before do
106
+ stub_request(:get, uri_without_userinfo).to_raise(Net::OpenTimeout).
107
+ then.to_return(status: 200, body: pact_content)
108
+ end
109
+
110
+ it 'retries and succeeds' do
111
+ expect(render_pact).to eq(pact_content)
112
+ end
113
+ end
114
+
115
+ context 'with continuous open timeouts' do
116
+ before { stub_request(:get, uri_without_userinfo).to_raise(Net::OpenTimeout) }
117
+
118
+ it 'retries but failed by retry limit' do
119
+ expect { render_pact }.to raise_error(Net::OpenTimeout)
120
+ end
121
+ end
122
+
123
+ context 'with single read timeout' do
124
+ before do
125
+ stub_request(:get, uri_without_userinfo).to_raise(Net::ReadTimeout).
126
+ then.to_return(status: 200, body: pact_content)
127
+ end
128
+
129
+ it 'retries and succeeds' do
130
+ expect(render_pact).to eq(pact_content)
131
+ end
132
+ end
133
+
134
+ context 'with continuous read timeout' do
135
+ before { stub_request(:get, uri_without_userinfo).to_raise(Net::ReadTimeout) }
136
+
137
+ it 'retries but failed by retry limit' do
138
+ expect { render_pact }.to raise_error(Net::ReadTimeout)
139
+ end
140
+ end
141
+
142
+ context 'with retry_limit option and server error' do
143
+ before do
144
+ stub_request(:get, uri_without_userinfo).to_return(status: 500).
145
+ then.to_return(status: 200, body: pact_content)
146
+ end
147
+
148
+ it 'retries and succeeds' do
149
+ expect { render_pact(retry_limit: 0) }.to raise_error(PactFile::HttpError, /status=500/)
150
+ end
151
+ end
152
+
153
+ context 'with retry_limit option and open timeout error' do
154
+ before do
155
+ stub_request(:get, uri_without_userinfo).to_raise(Net::OpenTimeout).
156
+ then.to_return(status: 200, body: pact_content)
157
+ end
158
+
159
+ it 'retries and succeeds' do
160
+ expect { render_pact(retry_limit: 0) }.to raise_error(Net::OpenTimeout)
161
+ end
162
+ end
163
+
164
+ context 'with retry_limit option which is greater than default retry limit' do
165
+ before do
166
+ stub_request(:get, uri_without_userinfo).to_return(status: 500).
167
+ then.to_return(status: 500).
168
+ then.to_return(status: 500).
169
+ then.to_return(status: 500).
170
+ then.to_return(status: 200, body: pact_content)
171
+ end
172
+
173
+ it 'retries and succeeds' do
174
+ expect(render_pact(retry_limit: 4)).to eq(pact_content)
175
+ end
176
+ end
177
+ end
45
178
  end
46
179
  end
47
- end
180
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact-support
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Fraser
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-04-29 00:00:00.000000000 Z
15
+ date: 2016-05-03 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: randexp
@@ -146,14 +146,14 @@ dependencies:
146
146
  requirements:
147
147
  - - "~>"
148
148
  - !ruby/object:Gem::Version
149
- version: 1.18.0
149
+ version: 2.0.0
150
150
  type: :development
151
151
  prerelease: false
152
152
  version_requirements: !ruby/object:Gem::Requirement
153
153
  requirements:
154
154
  - - "~>"
155
155
  - !ruby/object:Gem::Version
156
- version: 1.18.0
156
+ version: 2.0.0
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: pry
159
159
  requirement: !ruby/object:Gem::Requirement