Top Level Namespace
Defined Under Namespace
Modules: HashRecursiveBlank, HashRecursiveMerge, Tdi Classes: Hash, TDI
Instance Method Summary collapse
-
#a_p(obj) ⇒ Object
Awesome Print config.
-
#getaddress(host, raise_exception: true) ⇒ Object
Return IP address.
-
#local_networks ⇒ Object
Return a list of local networks and it’s details.
-
#origin_network(remote) ⇒ Object
Return the origin network to be used when trying to connect to a remote service.
-
#plan_compiler(opts, plan) ⇒ Object
Test plan compile.
-
#plan_filter(opts, plan) ⇒ Object
Test plan filter.
-
#plan_inheriter(opts, plan) ⇒ Object
Poor’s man test plan inheritance.
-
#planner(opts, plan) ⇒ Object
Test plan builder.
-
#report(opts, tdiplan) ⇒ Object
Generate report file.
-
#role_plan_split(name) ⇒ Object
Split role_name and plan_name.
-
#runner(opts, filename, plan) ⇒ Object
Run tests.
-
#shred(opts, filename, tdiplan) ⇒ Object
Remove tdi plan file.
-
#summary(opts, tdiplan) ⇒ Object
Display test summary.
Instance Method Details
#a_p(obj) ⇒ Object
Awesome Print config.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/util.rb', line 25 def a_p(obj) ap obj, { indent: 2, index: false, color: { args: :pale, array: :white, bigdecimal: :blue, class: :yellow, date: :greenish, falseclass: :red, fixnum: :blue, float: :blue, hash: :blue, keyword: :cyan, method: :purpleish, nilclass: :red, rational: :blue, string: :green, struct: :pale, symbol: :cyanish, time: :greenish, trueclass: :green, variable: :cyanish, } } end |
#getaddress(host, raise_exception: true) ⇒ Object
Return IP address.
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/util.rb', line 107 def getaddress(host, raise_exception: true) if IPAddress.valid?(host) return host # use address (already an IP) else if raise_exception return Socket::getaddrinfo(host, nil, :AF_INET, :STREAM).first[2] else return Socket::getaddrinfo(host, nil, :AF_INET, :STREAM).first[2] rescue nil end end end |
#local_networks ⇒ Object
Return a list of local networks and it’s details.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/util.rb', line 54 def local_networks Socket.getifaddrs.each.select { |ifaddr| ifaddr.addr.ipv4? && !ifaddr.name.start_with?('lo') }. map do |ifaddr| ip = IPAddress::IPv4.new("#{ifaddr.addr.ip_address}/#{ifaddr.netmask.ip_address}") { interface: ifaddr.name, network: ip.network.address, netmask: ip.netmask, prefix: ip.prefix, broadcast: ip.broadcast.address, ipv4: ip.address, } end end |
#origin_network(remote) ⇒ Object
Return the origin network to be used when trying to connect to a remote service.
Stolen from:
coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/
The above code does NOT make a connection or send any packets. Since UDP is a stateless protocol connect() merely makes a system call which figures out how to route the packets based on the address and what interface (and therefore IP address) it should bind to. addr() returns an array containing the family (AF_INET), local port, and local address (which is what we want) of the socket. This is a good alternative to ‘ifconfig`/`ipconfig` solutions because it doesn’t spawn a shell and it works the same on all systems.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/util.rb', line 83 def origin_network(remote) orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true host = remote # host (name or IP) addr = getaddress(remote, raise_exception: false) UDPSocket.open do |s| begin s.connect(remote, 1) res = {from: local_networks.each.select { |locnet| locnet[:ipv4].eql?(s.addr.last) }.first} rescue res = {from: nil} end res[:to] = {host: host, addr: addr} return res end ensure Socket.do_not_reverse_lookup = orig end |
#plan_compiler(opts, plan) ⇒ Object
Test plan compile.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 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 |
# File 'lib/planner.rb', line 85 def plan_compiler(opts, plan) # Gera um plano de teste baseado em todos os valores dos hashes, desde o mais # global (role) até o mais específico (test case). # Ordem de precedência: test case > test plan. puts 'Compiling test plan...'.cyan if opts[:verbose] > 1 compiled_plan = {} # Role. # Ex: {"app": {"desc": "...", "acl": {"domain1": {"port": 80}...}...}...} plan.select { |key, val| val.is_a?(Hash) }.each_with_index do |(role_name, role_content), index| if opts[:verbose] > 2 puts '=' * 60 puts "Role: #{role_name}" puts 'Role content:' puts "* #{role_content}".yellow end # Role (if not already). compiled_plan[role_name] ||= role_content # Test plan. # Ex: {"acl": {"domain1": {"port": 80}...}...} role_content.select { |key, val| val.is_a?(Hash) }.each_pair do |plan_name, plan_content| if opts[:verbose] > 2 puts "Plan: #{plan_name}" puts 'Plan content:' puts "* #{plan_content}".yellow end # Test plan (if not already). compiled_plan[role_name][plan_name] ||= plan_content # Test case. # Ex: {"domain1": {"port": 80}...} plan_content.select { |key, val| val.is_a?(Hash) }.each_pair do |case_name, case_content| if opts[:verbose] > 2 puts "Case: #{case_name}" puts 'Case content:' puts "* #{case_content}".yellow end # Test case compile. new_case_content = role_content.reject { |key, val| UNMERGEABLE_KEY_LIST.include?(key) || val.is_a?(Hash) } new_case_content.merge!(plan_content.reject { |key, val| UNMERGEABLE_KEY_LIST.include?(key) || val.is_a?(Hash) }) new_case_content.merge!(case_content.reject { |key, val| UNMERGEABLE_KEY_LIST.include?(key) || val.is_a?(Hash) }) # Test case (new, merged). compiled_plan[role_name][plan_name][case_name] = new_case_content if opts[:verbose] > 2 puts 'Compiled case content:' puts "* #{new_case_content}".yellow end end end if opts[:verbose] > 2 puts '=' * 60 puts unless index == plan.size - 1 end end if opts[:verbose] > 1 puts 'Compiling test plan... done.'.green puts end compiled_plan end |
#plan_filter(opts, plan) ⇒ Object
Test plan filter.
238 239 240 241 242 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 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/planner.rb', line 238 def plan_filter(opts, plan) # Filtra roles e test plans desejados a partir do plano fornecido. puts 'Filtering test plan...'.cyan if opts[:verbose] > 1 filtered_plan = {} flag_err = false # Ex: -p admin # Ex: -p admin::acl # Ex: --plan app # Ex: --plan app::acl # Ex: --plan fe # Ex: --plan admin::acl,app,fe if opts.plan? # Do filter. puts 'Filtering following test plan from input file:'.cyan if opts[:verbose] > 0 opts[:plan].each do |plan_name| puts " - #{plan_name}".cyan if opts[:verbose] > 0 # Pattern from command line is already validate by validate_args(). # Does not need to check for nil. f_role_name, f_plan_name = role_plan_split(plan_name) if plan.has_key?(f_role_name) unless f_plan_name.nil? # Test plan only. if plan[f_role_name].has_key?(f_plan_name) # Initialize hash key if not present. filtered_plan[f_role_name] ||= {} filtered_plan[f_role_name][f_plan_name] = plan[f_role_name][f_plan_name] puts " Test plan \"#{plan_name}\" included.".green if opts[:verbose] > 0 else puts "ERR: Test plan \"#{plan_name}\" not found in input file. This test plan can not be included.".light_magenta flag_err = true end else # Role test plan (entire). filtered_plan[f_role_name] = plan[f_role_name] puts " Role \"#{plan_name}\" included.".green if opts[:verbose] > 0 end else puts "ERR: Role \"#{f_role_name}\" not found in input file. Test plan \"#{plan_name}\" can not be included.".light_magenta flag_err = true end end puts if opts[:verbose] > 0 else # No filter. filtered_plan = plan end if opts[:verbose] > 2 puts 'Filtered test plan:'.cyan puts "* #{filtered_plan}".yellow end exit 1 if flag_err if opts[:verbose] > 1 puts 'Filtering test plan... done.'.green puts end filtered_plan end |
#plan_inheriter(opts, plan) ⇒ Object
Poor’s man test plan inheritance.
164 165 166 167 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 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/planner.rb', line 164 def plan_inheriter(opts, plan) # Processa a herança entre roles e test plans. puts 'Inheriting test plan...'.cyan if opts[:verbose] > 1 inherited_plan = {} # Role may inherit from role. # Ex: {"app": {"desc": "...", "inherits": "other_role", "acl": {"domain1": {"port": 80}...}...}...} plan.select { |key, val| val.is_a?(Hash) }.each_with_index do |(role_name, role_content), index| if opts[:verbose] > 2 puts '=' * 60 puts "Role: #{role_name}" puts 'Role content:' puts "* #{role_content}".yellow end # Role (if not already). inherited_plan[role_name] ||= role_content # Inheritance present? i_role_name = role_content['inherits'] unless i_role_name.nil? puts "Role #{role_name} inherits #{i_role_name}" if opts[:verbose] > 2 inherited_plan[role_name] = plan[i_role_name].rmerge(role_content) end # Plan may inherit from plan. # Ex: {"acl": {"inherits": "other_role::other_plan", "domain1": {"port": 80}...}...} role_content.select { |key, val| val.is_a?(Hash) }.each_pair do |plan_name, plan_content| if opts[:verbose] > 2 puts "Plan: #{plan_name}" puts 'Plan content:' puts "* #{plan_content}".yellow end # Test plan (if not already). inherited_plan[role_name][plan_name] ||= plan_content # Inheritance present? i_plan = plan_content['inherits'] unless i_plan.nil? i_role_name, i_plan_name = role_plan_split(i_plan) if i_role_name.nil? || i_plan_name.nil? puts "ERR: Invalid inheritance \"#{i_plan}\". Must match pattern \"role::plan\".".light_magenta exit 1 end # TODO: Tratar quando chave não existe. puts "Plan #{plan_name} inherits #{i_plan}" if opts[:verbose] > 2 inherited_plan[role_name][plan_name] = plan[i_role_name][i_plan_name].rmerge(plan_content) end end if opts[:verbose] > 2 puts '=' * 60 puts unless index == plan.size - 1 end end if opts[:verbose] > 1 puts 'Inheriting test plan... done.'.green puts end inherited_plan end |
#planner(opts, plan) ⇒ Object
Test plan builder.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/planner.rb', line 24 def planner(opts, plan) # Compila um plano completo. # Processa a herança. # Compila novamente para gerar um plano intermediário. # # Pass 1. if opts[:verbose] > 1 puts '* Pass 1...'.cyan puts end compiled_plan1 = plan_compiler(opts, plan) inherited_plan1 = plan_inheriter(opts, compiled_plan1) recompiled_plan1 = plan_compiler(opts, inherited_plan1) if opts[:verbose] > 1 puts '* Pass 1... done.'.green puts end # Zera o plano, mantendo apenas a estrutura de hashes. Desta forma é possível # gerar um esqueleto de plano com todas as entradas de test cases com valores # vazios (originais e herdados). # Logo em seguida ocorre um merge recursivo com os valores originais para # depois ser processado por completo novamente. # O objetivo é dar precedência aos valores globais locais sobre os valores # herdados. # # Blank and repopulate with original values. blanked_plan = recompiled_plan1.rblank if opts[:verbose] > 2 puts 'Blanked plan:' puts "* #{blanked_plan}".yellow end repopulated_plan = blanked_plan.rmerge(compiled_plan1) if opts[:verbose] > 2 puts 'Repopulated plan:' puts "* #{repopulated_plan}".yellow end # Compila um plano completo. # Processa a herança. # Compila novamente para gerar um plano final. # # Pass 2. if opts[:verbose] > 1 puts '* Pass 2...'.cyan puts end compiled_plan2 = plan_compiler(opts, repopulated_plan) inherited_plan2 = plan_inheriter(opts, compiled_plan2) recompiled_plan2 = plan_compiler(opts, inherited_plan2) if opts[:verbose] > 1 puts '* Pass 2... done.'.green puts end # Final plan. plan_filter(opts, recompiled_plan2) end |
#report(opts, tdiplan) ⇒ Object
Generate report file.
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/runner.rb', line 123 def report(opts, tdiplan) if opts[:verbose] > 2 puts 'Report:'.cyan a_p tdiplan.report end if opts.reportfile? puts "Generating report file: \"#{opts[:reportfile]}\"".cyan if opts[:verbose] > 1 File.open(opts[:reportfile], 'w') { |file| file.write(JSON.pretty_generate(tdiplan.report)) } end end |
#role_plan_split(name) ⇒ Object
Split role_name and plan_name.
307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/planner.rb', line 307 def role_plan_split(name) if name.include?('::') # Test plan only. f_role_name = name.split('::').first f_plan_name = name.split('::').last else # Role test plan (entire). f_role_name = name f_plan_name = nil end return f_role_name, f_plan_name end |
#runner(opts, filename, plan) ⇒ Object
Run tests.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 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 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/runner.rb', line 25 def runner(opts, filename, plan) puts 'Running tests...'.cyan if opts[:verbose] > 1 # Skip reserved roles. # Ex: {"global": {"desc": "...", "acl": {"domain1": {"port": 80}...}...}...} # Ex: {"common": {"desc": "...", "acl": {"domain1": {"port": 80}...}...}...} plan.select { |role_name, role_content| if role_content.is_a?(Hash) UNTESTABLE_ROLE_LIST.include?(role_name) || role_content['notest'].eql?('true') end }.each_pair do |role_name, role_content| puts "Skipping reserved or disabled role: #{role_name}".yellow if opts[:verbose] > 0 end # Remove untestable roles. plan.reject! { |role_name, role_content| if role_content.is_a?(Hash) UNTESTABLE_ROLE_LIST.include?(role_name) || role_content['notest'].eql?('true') end } total_roles = plan.select { |key, val| val.is_a?(Hash) }.size puts "Total roles to run: #{total_roles}".cyan if opts[:verbose] > 1 # Run the rest. tdiplan = TDIPlan.new # Role. # Ex: {"admin": {"desc": "...", "acl": {"domain1": {"port": 80}...}...}...} plan.select { |key, val| val.is_a?(Hash) }.each_with_index do |(role_name, role_content), index| total_plans = role_content.select { |key, val| val.is_a?(Hash) }.size if role_content['desc'].nil? puts "* #{role_name.capitalize}".cyan else puts "* #{role_name.capitalize} - #{role_content['desc']}".cyan end puts "Total test plans to run for this role: #{total_plans}".cyan if opts[:verbose] > 1 # Test plan. # Ex: {"acl": {"domain1": {"port": 80}...}...} role_content.select { |key, val| val.is_a?(Hash) }.each_pair do |plan_name, plan_content| total_cases = plan_content.select { |key, val| val.is_a?(Hash) }.size puts "* #{plan_name.upcase}".cyan puts "Total test cases to run for this plan: #{total_cases}".cyan if opts[:verbose] > 1 if opts[:verbose] > 3 puts "Plan: #{plan_name}" puts 'Plan content:' puts "* #{plan_content}".yellow end # Test plan content (test cases). # Ex: {"domain1": {"port": 80}, "domain2": {"port": 80}...} if tdiplan.respond_to?(plan_name) tdiplan.send(plan_name, role_name, plan_name, plan_content) else puts "Skipping not supported test plan type \"#{plan_name}\" for \"#{role_name}::#{plan_name}\".".yellow tdiplan.skip = tdiplan.skip + total_cases end end puts unless index == plan.size - 1 end # Summary. summary(opts, tdiplan) # Report file. report(opts, tdiplan) # Shred. shred(opts, filename, tdiplan) puts 'Running tests... done.'.green if opts[:verbose] > 1 ret = 0 ret += 1 if tdiplan.fail > 0 ret += 2 if opts.warnfail? && tdiplan.warn > 0 ret = 0 if opts.nofail? # 1 if failures # 2 if warnings (only if -w/--warnfail is active) # 3 if both (only if -w/--warnfail is active) # 0 if none or if -n/--nofail is active ret end |
#shred(opts, filename, tdiplan) ⇒ Object
Remove tdi plan file.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/runner.rb', line 136 def shred(opts, filename, tdiplan) if opts.shred? puts "Shreding and removing test plan file: \"#{filename}\"...".cyan if opts[:verbose] > 2 if OS.linux? shred_cmd = "shred -f -n 38 -u -z #{filename}" elsif OS.mac? shred_cmd = "srm -f -z #{filename}" else shred_cmd = "rm -f #{filename}" end puts "Shreding with command \"#{shred_cmd}\"...".cyan if opts[:verbose] > 2 if system(shred_cmd) puts "Shreding and removing test plan file: \"#{filename}\"... done.".green if opts[:verbose] > 2 else puts "ERR: Shreding and removing test plan file: \"#{filename}\".".light_magenta end end end |
#summary(opts, tdiplan) ⇒ Object
Display test summary.
117 118 119 120 |
# File 'lib/runner.rb', line 117 def summary(opts, tdiplan) puts '=' * 79 puts "Total: #{tdiplan.total} | Skip: #{tdiplan.skip} | Pass: #{tdiplan.pass} | Warn: #{tdiplan.warn} | Fail: #{tdiplan.fail}" end |