Class: RightDevelop::Testing::Recording::Config
- Inherits:
-
Object
- Object
- RightDevelop::Testing::Recording::Config
- Defined in:
- lib/right_develop/testing/recording/config.rb
Overview
Config file format.
Defined Under Namespace
Classes: ConfigError
Constant Summary collapse
- FIXTURES_DIR_NAME =
default relative directories.
'fixtures'.freeze
- LOG_DIR_NAME =
'log'.freeze
- PID_DIR_NAME =
'pid'.freeze
- STOP_TRAVERSAL_KEY =
the empty key is used as a stop traversal signal because any literal value would be ambiguous.
''.freeze
- VALID_MODES =
RightSupport::Data::Mash.new( :admin => 'Administrative for changing mode, fixtures, etc. while running.', :echo => 'Echoes request back as response and validates route.', :playback => 'Playback a session for one or more stubbed web services.', :record => 'Record a session for one or more proxied web services.' ).freeze
- ALLOWED_KINDS =
keys allowed under the deep route configuration.
%w(request response)
- ALLOWED_CONFIG_ACTIONS =
%w(delay_seconds significant timeouts transform variables)
- ALLOWED_TIMEOUTS =
%w(open_timeout read_timeout)
- ALLOWED_VARIABLE_TYPES =
%w(body header query)
- METADATA_CLASS =
metadata.
::RightDevelop::Testing::Recording::Metadata
- FIXTURE_FILE_NAME_REGEX =
patterns for fixture files.
/^([0-9A-Fa-f]{32}).yml$/
- TYPE_NAME_VALUE_REGEX =
typename to value expression for significant/requests/responses configurations.
/^(body|header|query|verb)(?:[:#]([^=]+))?=(.*)$/
Class Method Summary collapse
-
.deep_mash(any) ⇒ Object
Deeply mashes and duplicates (clones) a hash containing other hashes or arrays of hashes but not other types.
-
.from_file(path, options = nil) ⇒ Config
Loads the config from given path or a relative location.
Instance Method Summary collapse
-
#admin(value = nil) ⇒ Hash
Admin route configuration.
-
#cleanup_dirs(value = nil) ⇒ TrueClass|FalseClass
True if cleaning-up fixtures directory on interrupt or configuration change.
-
#fixtures_dir(value = nil) ⇒ String
Location of fixtures used for record/playback.
-
#initialize(config_hash, options = nil) ⇒ Config
constructor
A new instance of Config.
- #log_dir(value = nil) ⇒ Object
- #log_level(value = nil) ⇒ Object
- #mode(value = nil) ⇒ Object
- #pid_dir(value = nil) ⇒ Object
- #routes(value = nil) ⇒ Object
- #throttle(value = nil) ⇒ Object
-
#to_hash ⇒ String
Raw hash representing complete configuration.
Constructor Details
#initialize(config_hash, options = nil) ⇒ Config
Returns a new instance of Config.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/right_develop/testing/recording/config.rb', line 71 def initialize(config_hash, = nil) # defaults. current_dir = ::Dir.pwd defaults = RightSupport::Data::Mash.new( 'fixtures_dir' => ::File.(FIXTURES_DIR_NAME, current_dir), 'log_level' => :info, 'log_dir' => ::File.(LOG_DIR_NAME, current_dir), 'pid_dir' => ::File.(PID_DIR_NAME, current_dir), 'throttle' => 1, ) unless config_hash.kind_of?(::Hash) raise ConfigError, 'config_hash must be a hash' end # shallow merge of hash because the defaults are a shallow hash. deep mash # of caller's config to deep clone and normalize keys. config_hash = defaults.merge(deep_mash(config_hash)) if # another deep merge of any additional options. ::RightSupport::Data::HashTools.deep_merge!(config_hash, ) end @config_hash = RightSupport::Data::Mash.new mode(config_hash['mode']) admin(config_hash['admin']) routes(config_hash['routes']) log_dir(config_hash['log_dir']) pid_dir(config_hash['pid_dir']) log_level(config_hash['log_level']) fixtures_dir(config_hash['fixtures_dir']) cleanup_dirs(config_hash['cleanup_dirs']) throttle(config_hash['throttle']) end |
Class Method Details
.deep_mash(any) ⇒ Object
Deeply mashes and duplicates (clones) a hash containing other hashes or arrays of hashes but not other types.
Note that Mash.new(my_mash) will convert child hashes to mashes but not with the guarantee of cloning and detaching the deep mash. In other words. if any part of the hash is already a mash then it is not cloned by invoking Mash.new()
now delegates to RightSupport::Data::HashTools
294 295 296 |
# File 'lib/right_develop/testing/recording/config.rb', line 294 def self.deep_mash(any) ::RightSupport::Data::HashTools.deep_mash(any) end |
.from_file(path, options = nil) ⇒ Config
Loads the config from given path or a relative location.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/right_develop/testing/recording/config.rb', line 243 def self.from_file(path, = nil) # load unless ::File.file?(path) raise ConfigError, "Missing expected configuration file: #{path.inspect}" end config_hash = deep_mash(::YAML.load_file(path)) # enumerate routes looking for any route-specific config data to load # into the config hash from .yml files in subdirectories. this allows # the user to spread configuration of specific requests/responses out in # the file system instead of having a single monster config .yml extension = '.yml' (config_hash[:routes] || {}).each do |route_path, route_data| if subdir = route_data[:subdir] route_subdir = ::File.(::File.join(path, '..', subdir)) ::Dir[::File.join(route_subdir, "**/*#{extension}")].each do |route_config_path| route_config_data = RightSupport::Data::Mash.new(::YAML.load_file(route_config_path)) filename = ::File.basename(route_config_path)[0..-(extension.length + 1)] hash_path = ::File.dirname(route_config_path)[(route_subdir.length + 1)..-1].split('/') unless current_route_data = ::RightSupport::Data::HashTools.deep_get(route_data, hash_path) current_route_data = RightSupport::Data::Mash.new ::RightSupport::Data::HashTools.deep_set!(route_data, hash_path, current_route_data) end # inject a 'stop' at the point where the sub-config file data was # inserted into the big hash. the 'stop' basically distingishes the # 'directory' from the 'file' information because the hash doesn't # use classes to distinguish the data it contains; it only uses # simple types. use of simple types makes it easy to YAMLize or # JSONize or otherwise serialize in round-trip fashion. merge_data = { filename => { STOP_TRAVERSAL_KEY => route_config_data } } ::RightSupport::Data::HashTools.deep_merge!(current_route_data, merge_data) end end end # config self.new(config_hash, ) end |
Instance Method Details
#admin(value = nil) ⇒ Hash
Returns admin route configuration.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/right_develop/testing/recording/config.rb', line 137 def admin(value = nil) if value if mode == :admin case value when ::Hash admin_routes = (value['routes'] || {}).inject({}) do |r, (k, v)| case v when ::String, ::Symbol r[normalize_route_prefix(k)] = v.to_s.to_sym else raise ConfigError, "Invalid admin route target: #{v.inspect}" end r end if admin_routes.empty? raise ConfigError, "Invalid admin routes: #{value['routes'].inspect}" else @config_hash['admin'] = deep_mash(routes: admin_routes) end else raise ConfigError, "Unexpected type for admin configuration: #{value.class}" end else raise ConfigError, "Unexpected admin settings configured for non-admin mode: #{mode}" end end @config_hash['admin'] || {} end |
#cleanup_dirs(value = nil) ⇒ TrueClass|FalseClass
Returns true if cleaning-up fixtures directory on interrupt or configuration change.
118 119 120 121 |
# File 'lib/right_develop/testing/recording/config.rb', line 118 def cleanup_dirs(value = nil) @config_hash['cleanup_dirs'] = Array(value) if value @config_hash['cleanup_dirs'] end |
#fixtures_dir(value = nil) ⇒ String
Returns location of fixtures used for record/playback.
111 112 113 114 |
# File 'lib/right_develop/testing/recording/config.rb', line 111 def fixtures_dir(value = nil) @config_hash['fixtures_dir'] = value if value @config_hash['fixtures_dir'] end |
#log_dir(value = nil) ⇒ Object
214 215 216 217 |
# File 'lib/right_develop/testing/recording/config.rb', line 214 def log_dir(value = nil) @config_hash['log_dir'] = value if value @config_hash['log_dir'] end |
#log_level(value = nil) ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/right_develop/testing/recording/config.rb', line 197 def log_level(value = nil) if value case value when Integer if value < ::Logger::DEBUG || value >= ::Logger::UNKNOWN raise ConfigError, "log_level is out of range: #{value}" end @config_hash['log_level'] = value when String, Symbol @config_hash['log_level'] = ::Logger.const_get(value.to_s.upcase) else raise ConfigError, "log_level is unexpected type: #{log_level}" end end @config_hash['log_level'] end |
#mode(value = nil) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/right_develop/testing/recording/config.rb', line 123 def mode(value = nil) if value value = value.to_s if VALID_MODES.has_key?(value) @config_hash['mode'] = value.to_sym else raise ConfigError, "mode must be one of #{VALID_MODES.keys.sort.inspect}: #{value.inspect}" end end @config_hash['mode'] end |
#pid_dir(value = nil) ⇒ Object
219 220 221 222 |
# File 'lib/right_develop/testing/recording/config.rb', line 219 def pid_dir(value = nil) @config_hash['pid_dir'] = value if value @config_hash['pid_dir'] end |
#routes(value = nil) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/right_develop/testing/recording/config.rb', line 168 def routes(value = nil) if value case value when Hash # admin mode requires any playback/record config to be sent as a # PUT/POST request to the configured admin route. if mode == :admin raise ConfigError, 'Preconfigured routes are not allowed in admin mode.' end # normalize routes for efficient usage but keep them separate from # user's config so that .to_hash returns something understandable and # JSONizable/YAMLable. mutable_routes = value.inject(RightSupport::Data::Mash.new) do |r, (k, v)| r[normalize_route_prefix(k)] = normalize_route_data(k, v) r end # deep freeze routes to detect any case where code is unintentionally # modifying the route hash. @normalized_routes = ::RightSupport::Data::HashTools.deep_freeze!(mutable_routes) @config_hash['routes'] = ::RightSupport::Data::HashTools.deep_clone2(value) else raise ConfigError, 'routes must be a hash' end end @normalized_routes || {} end |
#throttle(value = nil) ⇒ Object
224 225 226 227 228 229 230 231 232 233 |
# File 'lib/right_develop/testing/recording/config.rb', line 224 def throttle(value = nil) if value value = Integer(value) if value < 0 || value > 100 raise ConfigError, "throttle is out of range: #{value}" end @config_hash['throttle'] = value end @config_hash['throttle'] end |
#to_hash ⇒ String
Returns raw hash representing complete configuration.
105 106 107 108 |
# File 'lib/right_develop/testing/recording/config.rb', line 105 def to_hash # unmash to hash ::JSON.load(@config_hash.to_json) end |