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 +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +12 -9
- data/lib/pact/consumer_contract/pact_file.rb +80 -9
- data/lib/pact/support/version.rb +1 -1
- data/pact-support.gemspec +1 -1
- data/spec/lib/pact/consumer_contract/pact_file_spec.rb +141 -8
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eeb1140d12c89f3c03f855ecfbb9666259b502c
|
4
|
+
data.tar.gz: 8b7e7ef1dea78d0abe77c2fb0db5a17f46ee47e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cbde3f5574d69c3be0b1e8f2fa7cd196e4c2e42133e966a7087d8a4f3796cb21906c93c7d6df5b97a445842031ed713ab1fa96de44f20110a25d3655e64fb49
|
7
|
+
data.tar.gz: 09d6fc96eeb2c6fcdce7269392a47a08ba3efa50e927b2fc80e9d41a21197dd4d1e37826ebe211b81ca9c79ad019761462431243385f7a34ff2514414314f71c
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
7
|
-
*
|
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
|
-
|
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
|
38
|
+
def render_pact(uri_string, options)
|
26
39
|
uri_obj = URI(uri_string)
|
27
|
-
|
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
|
-
|
34
|
-
|
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
|
data/lib/pact/support/version.rb
CHANGED
data/pact-support.gemspec
CHANGED
@@ -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', '~>
|
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.
|
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-
|
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:
|
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:
|
156
|
+
version: 2.0.0
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: pry
|
159
159
|
requirement: !ruby/object:Gem::Requirement
|