right_develop 3.1.9 → 3.1.10
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/VERSION +1 -1
- data/lib/right_develop/testing/clients/rest/requests/playback.rb +13 -5
- data/lib/right_develop/testing/clients/rest/requests/record.rb +17 -0
- data/lib/right_develop/testing/recording/metadata.rb +26 -7
- data/lib/right_develop/testing/servers/might_api/app/base.rb +49 -1
- data/right_develop.gemspec +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca1ee47286ed9116bc3e025b1596019d85b1b59c
|
4
|
+
data.tar.gz: 524daf75dc03226c0fa94d0c265dc494f24e7ac2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2264a0ad0de1f8cef1de281cca8d9ab688c3d2d14006d5a4225decb2cf7fd346cb67226832abee3933f43b65b9a5f157b5a121159d90591223a40b2ed05463a3
|
7
|
+
data.tar.gz: c00c17b93fb059d26181ebc335f25fcbecee4e8c7f0d0e7e6542a179b05a47ced720c0973e7ec9d8dc56ad1bf6a0e1801128b74b2afdfadcdcc07a70069251cc
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.1.
|
1
|
+
3.1.10
|
@@ -89,7 +89,7 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
89
89
|
end
|
90
90
|
|
91
91
|
RETRY_DELAY = 0.5
|
92
|
-
MAX_RETRIES =
|
92
|
+
MAX_RETRIES = 240 # = 120 seconds; a socket usually times out in 60-120 seconds
|
93
93
|
|
94
94
|
# Overrides transmit to catch halt thrown by log_request.
|
95
95
|
#
|
@@ -176,7 +176,6 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
176
176
|
# allowed due to multithreaded requests causing the epoch to advance
|
177
177
|
# (in a non-throttled playback) before all requests for a past epoch have
|
178
178
|
# been made. the current epoch is always preferred over past.
|
179
|
-
logger.debug("BEGIN playback state = #{state.inspect}") if logger.debug?
|
180
179
|
file_path = nil
|
181
180
|
past_epochs = state[:past_epochs] ||= []
|
182
181
|
try_epochs = [state[:epoch]] + past_epochs
|
@@ -203,11 +202,20 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
203
202
|
response_hash[:body])
|
204
203
|
result = FakeNetHttpResponse.new(response_hash, response_metadata)
|
205
204
|
else
|
206
|
-
msg =
|
207
|
-
|
208
|
-
|
205
|
+
msg = <<EOF
|
206
|
+
Unable to locate response file(s) in epoch range [#{first_tried_epoch} - #{last_tried_epoch}]:
|
207
|
+
#{first_tried_path.inspect}
|
208
|
+
request checksum_data = #{request_metadata.checksum_data.inspect}
|
209
|
+
state = #{state.inspect}
|
210
|
+
EOF
|
209
211
|
raise PLAYBACK_ERROR, msg
|
210
212
|
end
|
213
|
+
|
214
|
+
# defer any verbose debug logging (i.e. the current state) until after
|
215
|
+
# metadata has been successfully loaded because a retryable missing
|
216
|
+
# variable may occur a couple hundred times before the condition is
|
217
|
+
# satisfied, if ever.
|
218
|
+
logger.debug("BEGIN playback state = #{state.inspect}") if logger.debug?
|
211
219
|
logger.debug("Played back response from #{file_path.inspect}.")
|
212
220
|
|
213
221
|
# determine if epoch is done, which it is if every known request has been
|
@@ -63,6 +63,23 @@ module RightDevelop::Testing::Client::Rest::Request
|
|
63
63
|
def to_hash; @headers; end
|
64
64
|
end
|
65
65
|
|
66
|
+
# Overrides transmit to catch halt thrown by log_request.
|
67
|
+
#
|
68
|
+
# @param [URI[ uri of some kind
|
69
|
+
# @param [Net::HTTP] req of some kind
|
70
|
+
# @param [RestClient::Payload] of some kind
|
71
|
+
#
|
72
|
+
# @return
|
73
|
+
def transmit(uri, req, payload, &block)
|
74
|
+
super
|
75
|
+
rescue ::Interrupt
|
76
|
+
if @request_timestamp
|
77
|
+
logger.warn('Interrupted with at least one request outstanding; will record a timeout response.')
|
78
|
+
handle_timeout
|
79
|
+
end
|
80
|
+
raise
|
81
|
+
end
|
82
|
+
|
66
83
|
# Overrides log_request for basic logging.
|
67
84
|
#
|
68
85
|
# @param [RestClient::Response] to capture
|
@@ -88,7 +88,7 @@ module RightDevelop::Testing::Recording
|
|
88
88
|
class RecordingError < StandardError; end
|
89
89
|
class PlaybackError < StandardError; end
|
90
90
|
|
91
|
-
attr_reader :uri, :verb, :http_status, :headers, :body
|
91
|
+
attr_reader :uri, :verb, :http_status, :headers, :body, :checksum_data
|
92
92
|
attr_reader :mode, :logger, :effective_route_config, :variables
|
93
93
|
attr_reader :typenames_to_values
|
94
94
|
|
@@ -636,8 +636,15 @@ module RightDevelop::Testing::Recording
|
|
636
636
|
result = variable # use macro as substituted value
|
637
637
|
elsif values = @variables[variable]
|
638
638
|
# quick out for same as initial value; don't show array index.
|
639
|
+
# special case for 'any_variable_name[*]' which always uses the last
|
640
|
+
# given value instead of keeping an array of values.
|
639
641
|
if values.first == real_value
|
640
642
|
result = variable
|
643
|
+
elsif variable.end_with?('[*]')
|
644
|
+
# special case for wildcard index; update 1-sized array 0th entry with
|
645
|
+
# latest value instead of appending a new unique value.
|
646
|
+
@variables[variable][0] = real_value
|
647
|
+
result = variable
|
641
648
|
else
|
642
649
|
# show zero-based array index beyond the zero index.
|
643
650
|
unless value_index = values.index(real_value)
|
@@ -667,8 +674,17 @@ module RightDevelop::Testing::Recording
|
|
667
674
|
end
|
668
675
|
result = variable # use macro as substituted value
|
669
676
|
else
|
670
|
-
|
671
|
-
|
677
|
+
value_index = nil
|
678
|
+
if values = @variables[variable]
|
679
|
+
# special wildcard index notation means 'always latest value'; the
|
680
|
+
# recorded variable name will be the wildcard index name.
|
681
|
+
if variable.end_with?('[*]')
|
682
|
+
value_index = 0
|
683
|
+
else
|
684
|
+
value_index = values.index(real_value)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
case value_index
|
672
688
|
when nil
|
673
689
|
message = 'A variable referenced by a response has not yet been ' +
|
674
690
|
'defined by a request while replacing variable = ' +
|
@@ -702,7 +718,10 @@ module RightDevelop::Testing::Recording
|
|
702
718
|
raise PlaybackError, message
|
703
719
|
end
|
704
720
|
elsif variable_array = @variables[variable]
|
705
|
-
if
|
721
|
+
if variable.end_with?('[*]')
|
722
|
+
# special case for wildcard
|
723
|
+
variable_array_index = 0
|
724
|
+
elsif matched = VARIABLE_INDEX_REGEX.match(target_value)
|
706
725
|
variable_array_index = Integer(matched[1])
|
707
726
|
else
|
708
727
|
variable_array_index = 0
|
@@ -791,12 +810,12 @@ module RightDevelop::Testing::Recording
|
|
791
810
|
end
|
792
811
|
|
793
812
|
# use deep-sorted JSON to prevent random ordering changing the checksum.
|
794
|
-
checksum_data = self.class.deep_sorted_json(significant_data)
|
813
|
+
@checksum_data = self.class.deep_sorted_json(significant_data)
|
795
814
|
if logger.debug?
|
796
815
|
logger.debug("#{@kind} significant = #{significant.inspect}")
|
797
|
-
logger.debug("#{@kind} checksum_data = #{checksum_data.inspect}")
|
816
|
+
logger.debug("#{@kind} checksum_data = #{@checksum_data.inspect}")
|
798
817
|
end
|
799
|
-
::Digest::MD5.hexdigest(checksum_data)
|
818
|
+
::Digest::MD5.hexdigest(@checksum_data)
|
800
819
|
end
|
801
820
|
|
802
821
|
# Performs a selective copy of any significant fields (recursively) or else
|
@@ -23,6 +23,7 @@
|
|
23
23
|
require ::File.expand_path('../../config/init', __FILE__)
|
24
24
|
|
25
25
|
require 'rack/chunked'
|
26
|
+
require 'set'
|
26
27
|
require 'stringio'
|
27
28
|
require 'uri'
|
28
29
|
|
@@ -30,6 +31,8 @@ module RightDevelop::Testing::Server::MightApi
|
|
30
31
|
module App
|
31
32
|
class Base
|
32
33
|
|
34
|
+
MUTEX = ::Mutex.new # semaphore for critical sections
|
35
|
+
|
33
36
|
MAX_REDIRECTS = 10 # 500 after so many redirects
|
34
37
|
|
35
38
|
# Rack (and Skeletor) apps and some known AWS apps only accept dash and
|
@@ -63,6 +66,18 @@ module RightDevelop::Testing::Server::MightApi
|
|
63
66
|
nil
|
64
67
|
end
|
65
68
|
|
69
|
+
def self.interrupted?
|
70
|
+
!!@interrupted
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.interrupted=(value)
|
74
|
+
@interrupted = value
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.app_threads
|
78
|
+
@app_threads ||= ::Set.new
|
79
|
+
end
|
80
|
+
|
66
81
|
def call(env)
|
67
82
|
# HACK: chain trap interrupt on first call to app because the trap chain
|
68
83
|
# does not exist, in rack terms, until just before app is run.
|
@@ -75,7 +90,11 @@ module RightDevelop::Testing::Server::MightApi
|
|
75
90
|
# cleaned-up on shutdown, etc. admin mode has a workaround whereby it is
|
76
91
|
# able to clean-up any temporary files immediately after reading its
|
77
92
|
# config and whenever the administered configuration changes.
|
78
|
-
|
93
|
+
raise ::Interrupt if self.class.interrupted?
|
94
|
+
MUTEX.synchronize do
|
95
|
+
entrapment unless Base.trapped?
|
96
|
+
self.class.app_threads << ::Thread.current
|
97
|
+
end
|
79
98
|
|
80
99
|
env['rack.logger'] ||= logger
|
81
100
|
|
@@ -145,6 +164,13 @@ module RightDevelop::Testing::Server::MightApi
|
|
145
164
|
logger.error(message)
|
146
165
|
logger.debug(trace.join("\n"))
|
147
166
|
internal_server_error(message)
|
167
|
+
rescue ::Interrupt
|
168
|
+
# setting interrupted=true may or may not be redundant, depending on
|
169
|
+
# visibility of interrupted flag to all outstanding app threads.
|
170
|
+
# the problem is that we are not allowed to synchronize a mutex inside
|
171
|
+
# of a trap context.
|
172
|
+
self.class.interrupted = true
|
173
|
+
internal_server_error('interrupt')
|
148
174
|
rescue ::Exception => e
|
149
175
|
message = "Unhandled exception: #{e.class} #{e.message}"
|
150
176
|
trace = e.backtrace || []
|
@@ -156,6 +182,12 @@ module RightDevelop::Testing::Server::MightApi
|
|
156
182
|
env['rack.errors'].puts(trace.join("\n"))
|
157
183
|
end
|
158
184
|
internal_server_error(message)
|
185
|
+
ensure
|
186
|
+
unless self.class.interrupted?
|
187
|
+
MUTEX.synchronize do
|
188
|
+
self.class.app_threads.delete(::Thread.current)
|
189
|
+
end
|
190
|
+
end
|
159
191
|
end
|
160
192
|
|
161
193
|
# Handler.
|
@@ -434,6 +466,22 @@ EOF
|
|
434
466
|
app.logger.warn('cannot log traps') # no exception raised
|
435
467
|
end
|
436
468
|
|
469
|
+
# interrupt any running app threads to resolve outstanding requests.
|
470
|
+
#
|
471
|
+
# note that Mutex#synchronize is not allowed inside a trap context.
|
472
|
+
#
|
473
|
+
# FIX: duplicating the set is slightly unsafe but not sure how else
|
474
|
+
# to deal with data protected by critical section in a trap. we also
|
475
|
+
# have logic in ensure block to avoid modifying set on interrupt.
|
476
|
+
app.class.interrupted = true
|
477
|
+
app_threads = app.class.app_threads.dup
|
478
|
+
app_threads.each do |app_thread|
|
479
|
+
if app_thread.alive?
|
480
|
+
app_thread.raise(::Interrupt)
|
481
|
+
app_thread.join
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
437
485
|
# cleanup fixtures, if requested.
|
438
486
|
app.cleanup
|
439
487
|
if previous_trap && previous_trap.respond_to?(:call)
|
data/right_develop.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: right_develop 3.1.
|
5
|
+
# stub: right_develop 3.1.10 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "right_develop"
|
9
|
-
s.version = "3.1.
|
9
|
+
s.version = "3.1.10"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Tony Spataro"]
|
14
|
-
s.date = "2014-12-
|
14
|
+
s.date = "2014-12-10"
|
15
15
|
s.description = "A toolkit of development tools created by RightScale."
|
16
16
|
s.email = "support@rightscale.com"
|
17
17
|
s.executables = ["right_develop"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_develop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Spataro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: right_support
|