teuton 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/changelog/todo.md +4 -8
- data/docs/changelog/v2.7.md +11 -0
- data/docs/diagram.md +16 -15
- data/docs/learn/06-cmd_check.md +3 -2
- data/docs/learn/21-exit_codes.md +9 -16
- data/lib/teuton/case/case.rb +25 -44
- data/lib/teuton/case/close.rb +2 -0
- data/lib/teuton/case/config.rb +3 -3
- data/lib/teuton/case/{runner.rb → deprecated/runner.rb} +14 -10
- data/lib/teuton/case/deprecated/utils.rb +40 -0
- data/lib/teuton/case/dsl/all.rb +8 -0
- data/lib/teuton/case/dsl/expect.rb +25 -9
- data/lib/teuton/case/dsl/goto.rb +10 -9
- data/lib/teuton/case/dsl/log.rb +1 -2
- data/lib/teuton/case/dsl/macro.rb +2 -2
- data/lib/teuton/case/dsl/send.rb +3 -8
- data/lib/teuton/case/execute/execute_base.rb +55 -0
- data/lib/teuton/case/execute/execute_local.rb +29 -0
- data/lib/teuton/case/execute/execute_manager.rb +56 -0
- data/lib/teuton/case/execute/execute_ssh.rb +90 -0
- data/lib/teuton/case/execute/execute_telnet.rb +56 -0
- data/lib/teuton/case/play.rb +6 -6
- data/lib/teuton/case_manager/case_manager.rb +12 -8
- data/lib/teuton/case_manager/check_cases.rb +14 -12
- data/lib/teuton/case_manager/dsl.rb +6 -8
- data/lib/teuton/case_manager/export_manager.rb +2 -3
- data/lib/teuton/case_manager/hall_of_fame.rb +9 -10
- data/lib/teuton/case_manager/report.rb +11 -9
- data/lib/teuton/case_manager/show_report.rb +4 -6
- data/lib/teuton/case_manager/utils.rb +2 -48
- data/lib/teuton/check/dsl.rb +1 -2
- data/lib/teuton/check/laboratory.rb +7 -7
- data/lib/teuton/check/show.rb +5 -8
- data/lib/teuton/cli.rb +10 -0
- data/lib/teuton/readme/dsl.rb +5 -7
- data/lib/teuton/readme/lang.rb +3 -2
- data/lib/teuton/readme/readme.rb +15 -18
- data/lib/teuton/report/formatter/default/array.rb +6 -5
- data/lib/teuton/report/formatter/default/txt.rb +1 -0
- data/lib/teuton/report/formatter/resume/array.rb +3 -3
- data/lib/teuton/report/formatter/resume/html.rb +2 -2
- data/lib/teuton/report/report.rb +6 -5
- data/lib/teuton/skeleton.rb +8 -10
- data/lib/teuton/{application.rb → utils/application.rb} +13 -5
- data/lib/teuton/utils/name_file_finder.rb +40 -45
- data/lib/teuton/utils/project.rb +73 -0
- data/lib/teuton/{result → utils/result}/result.rb +9 -7
- data/lib/teuton/utils/settings.rb +12 -0
- data/lib/teuton/utils/verbose.rb +2 -2
- data/lib/teuton/version.rb +1 -1
- data/lib/teuton.rb +18 -17
- metadata +19 -9
- data/lib/teuton/case/dsl.rb +0 -10
- /data/lib/teuton/{result → utils/result}/ext_array.rb +0 -0
- /data/lib/teuton/{result → utils/result}/ext_compare.rb +0 -0
- /data/lib/teuton/{result → utils/result}/ext_filter.rb +0 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative "../../utils/verbose"
|
2
|
+
|
3
|
+
class ExecuteBase
|
4
|
+
include Verbose
|
5
|
+
|
6
|
+
def initialize(parent)
|
7
|
+
@parent = parent
|
8
|
+
# READ: @config, cmd = action[:command]
|
9
|
+
# WRITE: @action, @result, @session
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def config
|
15
|
+
@parent.config
|
16
|
+
end
|
17
|
+
|
18
|
+
def action
|
19
|
+
@parent.action
|
20
|
+
end
|
21
|
+
|
22
|
+
def result
|
23
|
+
@parent.result
|
24
|
+
end
|
25
|
+
|
26
|
+
def sessions
|
27
|
+
@parent.sessions
|
28
|
+
end
|
29
|
+
|
30
|
+
def log(...)
|
31
|
+
@parent.log(...)
|
32
|
+
end
|
33
|
+
|
34
|
+
def conn_status
|
35
|
+
@parent.conn_status
|
36
|
+
end
|
37
|
+
|
38
|
+
def encode_and_split(encoding, text)
|
39
|
+
# Convert text to UTF-8 deleting unknown chars
|
40
|
+
text ||= "" # Ensure text is not nil
|
41
|
+
flag = [:default, "UTF-8"].include? encoding
|
42
|
+
return text.encode("UTF-8", invalid: :replace).split("\n") if flag
|
43
|
+
|
44
|
+
# Convert text from input ENCODING to UTF-8
|
45
|
+
ec = Encoding::Converter.new(encoding.to_s, "UTF-8")
|
46
|
+
begin
|
47
|
+
text = ec.convert(text)
|
48
|
+
rescue => e
|
49
|
+
puts "[ERROR] #{e}: Declare text encoding..."
|
50
|
+
puts " run 'command', on: :host, :encoding => 'ISO-8859-1'"
|
51
|
+
end
|
52
|
+
|
53
|
+
text.split("\n")
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "open3"
|
2
|
+
require "rainbow"
|
3
|
+
require_relative "../../utils/project"
|
4
|
+
require_relative "../../utils/verbose"
|
5
|
+
require_relative "execute_base"
|
6
|
+
|
7
|
+
class ExecuteLocal < ExecuteBase
|
8
|
+
def call
|
9
|
+
action[:conn_type] = :local
|
10
|
+
response = my_execute(action[:command], action[:encoding])
|
11
|
+
result.exitcode = response[:exitcode]
|
12
|
+
result.content = response[:content]
|
13
|
+
end
|
14
|
+
|
15
|
+
def my_execute(cmd, encoding = "UTF-8")
|
16
|
+
return {exitcode: 0, content: ""} if Project.debug?
|
17
|
+
|
18
|
+
begin
|
19
|
+
text, status = Open3.capture2e(cmd)
|
20
|
+
exitcode = status.exitstatus
|
21
|
+
rescue => e
|
22
|
+
verbose Rainbow("!").green
|
23
|
+
text = e.to_s
|
24
|
+
exitcode = 1
|
25
|
+
end
|
26
|
+
content = encode_and_split(encoding, text)
|
27
|
+
{exitcode: exitcode, content: content}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative "execute_local"
|
2
|
+
require_relative "execute_ssh"
|
3
|
+
require_relative "execute_telnet"
|
4
|
+
|
5
|
+
class ExecuteManager
|
6
|
+
def initialize(parent)
|
7
|
+
@parent = parent
|
8
|
+
# READ: @config, cmd = action[:command]
|
9
|
+
# WRITE: @action, @result, @session
|
10
|
+
# my_execute, encode_and_split methods?
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(host)
|
14
|
+
start_time = Time.now
|
15
|
+
run_on(host)
|
16
|
+
action[:duration] = (Time.now - start_time).round(3)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def action
|
22
|
+
@parent.action
|
23
|
+
end
|
24
|
+
|
25
|
+
def config
|
26
|
+
@parent.config
|
27
|
+
end
|
28
|
+
|
29
|
+
def log
|
30
|
+
@parent.log
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_on(host)
|
34
|
+
protocol = config.get("#{host}_protocol".to_sym)
|
35
|
+
ip = config.get("#{host}_ip".to_sym)
|
36
|
+
|
37
|
+
if protocol.to_s.downcase == "local" || host.to_s == "localhost"
|
38
|
+
# Protocol force => local
|
39
|
+
ExecuteLocal.new(@parent).call
|
40
|
+
elsif protocol.to_s.downcase == "ssh"
|
41
|
+
# Protocol force => ssh
|
42
|
+
ExecuteSSH.new(@parent).call(host)
|
43
|
+
elsif protocol.to_s.downcase == "telnet"
|
44
|
+
# Protocol force => telnet
|
45
|
+
ExecuteTelnet.new(@parent).call(host)
|
46
|
+
elsif ip.to_s.downcase == "localhost" || ip.to_s.include?("127.0.0.")
|
47
|
+
# run_cmd_localhost
|
48
|
+
ExecuteLocal.new(@parent).call
|
49
|
+
elsif ip == "NODATA"
|
50
|
+
log("#{host} IP not found!", :error)
|
51
|
+
else
|
52
|
+
# run_cmd_remote_ssh host
|
53
|
+
ExecuteSSH.new(@parent).call(host)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require "net/ssh"
|
2
|
+
require "net/sftp"
|
3
|
+
require "rainbow"
|
4
|
+
require_relative "../../utils/project"
|
5
|
+
require_relative "../../utils/verbose"
|
6
|
+
require_relative "execute_base"
|
7
|
+
|
8
|
+
class ExecuteSSH < ExecuteBase
|
9
|
+
def call(input_hostname)
|
10
|
+
action[:conn_type] = :ssh
|
11
|
+
hostname = input_hostname.to_s
|
12
|
+
ip = config.get("#{hostname}_ip".to_sym).to_s
|
13
|
+
username = config.get("#{hostname}_username".to_sym).to_s
|
14
|
+
password = config.get("#{hostname}_password".to_sym).to_s
|
15
|
+
port = config.get("#{hostname}_port".to_sym).to_i
|
16
|
+
port = 22 if port.zero?
|
17
|
+
|
18
|
+
unless config.get("#{hostname}_route".to_sym) == "NODATA"
|
19
|
+
# Reconfigure command with gateway. Example host1_route: IP.
|
20
|
+
# hostname2 = hostname ¿not used?
|
21
|
+
ip2 = ip
|
22
|
+
username2 = username
|
23
|
+
password2 = password
|
24
|
+
command2 = action[:command]
|
25
|
+
hostname = config.get("#{hostname}_route".to_sym)
|
26
|
+
ip = config.get("#{hostname}_ip".to_sym).to_s
|
27
|
+
username = config.get("#{hostname}_username".to_sym).to_s
|
28
|
+
password = config.get("#{hostname}_password".to_sym).to_s
|
29
|
+
ostype = config.get("#{hostname}_ostype".to_sym).to_s
|
30
|
+
|
31
|
+
action[:command] = if ostype.downcase.start_with? "win"
|
32
|
+
"echo y | plink #{username2}@#{ip2} -ssh -pw #{password2} \"#{command2}\""
|
33
|
+
else
|
34
|
+
"sshpass -p #{password2} #{username2}@#{ip2} #{command2}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
text = ""
|
39
|
+
exitcode = 0
|
40
|
+
begin
|
41
|
+
if sessions[hostname].nil?
|
42
|
+
sessions[hostname] = Net::SSH.start(
|
43
|
+
ip,
|
44
|
+
username,
|
45
|
+
port: port,
|
46
|
+
password: password,
|
47
|
+
keepalive: true,
|
48
|
+
timeout: 30,
|
49
|
+
non_interactive: true
|
50
|
+
)
|
51
|
+
end
|
52
|
+
text = if sessions[hostname].instance_of? Net::SSH::Connection::Session
|
53
|
+
sessions[hostname].exec!(action[:command])
|
54
|
+
else
|
55
|
+
"SSH: NO CONNECTION!"
|
56
|
+
end
|
57
|
+
exitcode = text.exitstatus
|
58
|
+
rescue Errno::EHOSTUNREACH
|
59
|
+
sessions[hostname] = :nosession
|
60
|
+
conn_status[hostname] = :host_unreachable
|
61
|
+
exitcode = -1
|
62
|
+
log("Host #{ip} unreachable!", :error)
|
63
|
+
rescue Net::SSH::AuthenticationFailed
|
64
|
+
sessions[hostname] = :nosession
|
65
|
+
conn_status[hostname] = :error_authentication_failed
|
66
|
+
exitcode = -1
|
67
|
+
log("SSH::AuthenticationFailed!", :error)
|
68
|
+
rescue Net::SSH::HostKeyMismatch
|
69
|
+
sessions[hostname] = :nosession
|
70
|
+
conn_status[hostname] = :host_key_mismatch
|
71
|
+
exitcode = -1
|
72
|
+
log("SSH::HostKeyMismatch!", :error)
|
73
|
+
log("* The destination server's fingerprint is not matching " \
|
74
|
+
"what is in your local known_hosts file.", :error)
|
75
|
+
log("* Remove the existing entry in your local known_hosts file", :error)
|
76
|
+
log("* Try this => ssh-keygen -f '/home/USERNAME/.ssh/known_hosts' " \
|
77
|
+
"-R #{ip}", :error)
|
78
|
+
rescue => e
|
79
|
+
sessions[hostname] = :nosession
|
80
|
+
conn_status[hostname] = :error
|
81
|
+
exitcode = -1
|
82
|
+
log("[#{e.class}] SSH on <#{username}@#{ip}>" \
|
83
|
+
" exec: #{action[:command]}", :error)
|
84
|
+
end
|
85
|
+
output = encode_and_split(action[:encoding], text)
|
86
|
+
result.exitcode = exitcode
|
87
|
+
result.content = output
|
88
|
+
result.content.compact!
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "net/telnet"
|
2
|
+
require "rainbow"
|
3
|
+
require_relative "../../utils/project"
|
4
|
+
require_relative "../../utils/verbose"
|
5
|
+
require_relative "execute_base"
|
6
|
+
|
7
|
+
class ExecuteTelnet < ExecuteBase
|
8
|
+
def call(input_hostname)
|
9
|
+
action[:conn_type] = :telnet
|
10
|
+
hostname = input_hostname.to_s
|
11
|
+
ip = config.get((hostname + "_ip").to_sym)
|
12
|
+
username = config.get((hostname + "_username").to_sym).to_s
|
13
|
+
password = config.get((hostname + "_password").to_sym).to_s
|
14
|
+
text = ""
|
15
|
+
begin
|
16
|
+
if sessions[hostname].nil? || sessions[hostname] == :ok
|
17
|
+
h = Net::Telnet.new(
|
18
|
+
"Host" => ip,
|
19
|
+
"Timeout" => 30,
|
20
|
+
"Prompt" => /login|teuton|[$%#>]/
|
21
|
+
)
|
22
|
+
# "Prompt" => Regexp.new(username[1, 40]))
|
23
|
+
# "Prompt" => /[$%#>] \z/n)
|
24
|
+
h.login(username, password)
|
25
|
+
h.cmd(action[:command]) { |i| text << i }
|
26
|
+
h.close
|
27
|
+
sessions[hostname] = :ok
|
28
|
+
else
|
29
|
+
text = "TELNET: NO CONNECTION!"
|
30
|
+
end
|
31
|
+
rescue Net::OpenTimeout
|
32
|
+
sessions[hostname] = :nosession
|
33
|
+
conn_status[hostname] = :open_timeout
|
34
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
35
|
+
log(" ExceptionType=<Net::OpenTimeout> doing <telnet #{ip}>", :error)
|
36
|
+
log(" └── Revise host IP!", :warn)
|
37
|
+
rescue Net::ReadTimeout
|
38
|
+
sessions[hostname] = :nosession
|
39
|
+
conn_status[hostname] = :read_timeout
|
40
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
41
|
+
log(" ExceptionType=<Net::ReadTimeout> doing <telnet #{ip}>", :error)
|
42
|
+
rescue => e
|
43
|
+
sessions[hostname] = :nosession
|
44
|
+
conn_status[hostname] = :error
|
45
|
+
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
46
|
+
log(" ExceptionType=<#{e.class}> doing telnet on <#{username}@#{ip}>" \
|
47
|
+
" exec: #{action[:command]}", :error)
|
48
|
+
log(" └── username=<#{username}>, password=<#{password}>," \
|
49
|
+
" ip=<#{ip}>, HOSTID=<#{hostname}>", :warn)
|
50
|
+
end
|
51
|
+
output = encode_and_split(action[:encoding], text)
|
52
|
+
result.exitcode = -1
|
53
|
+
result.content = output
|
54
|
+
result.content.compact!
|
55
|
+
end
|
56
|
+
end
|
data/lib/teuton/case/play.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Case class:
|
4
|
-
# * play
|
5
|
-
# * play_in_parallel
|
6
|
-
# * play_in_sequence
|
7
|
-
# * fill_report
|
8
|
-
# * close_opened_sessions
|
9
3
|
class Case
|
4
|
+
# Case class: play
|
5
|
+
# TODO: Encapsulate code into PlayManager class
|
6
|
+
# * play_in_parallel, play_in_sequence, fill_report, close_opened_sessions
|
7
|
+
# READ: sessions, config, groups, action, report
|
8
|
+
# TODO: groups from Project or from Case???
|
10
9
|
def play
|
11
10
|
if skip?
|
12
11
|
verbose Rainbow("S").green
|
@@ -31,6 +30,7 @@ class Case
|
|
31
30
|
verboseln "\n=> Starting case [#{@config.get(:tt_members)}]" if get(:tt_sequence) == true
|
32
31
|
@groups.each do |t|
|
33
32
|
@action[:groupname] = t[:name]
|
33
|
+
# TODO: @parent(case).instance_eval(&t[:block])
|
34
34
|
instance_eval(&t[:block])
|
35
35
|
end
|
36
36
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
-
require_relative "../application"
|
2
1
|
require_relative "../case/case"
|
3
2
|
require_relative "../report/report"
|
3
|
+
require_relative "../utils/project"
|
4
|
+
require_relative "../utils/verbose"
|
4
5
|
require_relative "../utils/configfile_reader"
|
5
6
|
require_relative "export_manager"
|
6
7
|
require_relative "send_manager"
|
@@ -9,8 +10,6 @@ require_relative "check_cases"
|
|
9
10
|
require_relative "report"
|
10
11
|
require_relative "utils"
|
11
12
|
|
12
|
-
# This class does all the job
|
13
|
-
# Organize the hole job, sending orders to others classes
|
14
13
|
# * initialize
|
15
14
|
# * play
|
16
15
|
# Split into several files:
|
@@ -20,6 +19,7 @@ require_relative "utils"
|
|
20
19
|
# * case_manager/report
|
21
20
|
class CaseManager
|
22
21
|
include Utils
|
22
|
+
include Verbose
|
23
23
|
attr_reader :report, :cases
|
24
24
|
|
25
25
|
def initialize
|
@@ -28,21 +28,25 @@ class CaseManager
|
|
28
28
|
@report.filename = "resume"
|
29
29
|
end
|
30
30
|
|
31
|
-
##
|
32
|
-
# Execute "play" order: Start every single case test
|
33
31
|
def play(&block)
|
32
|
+
# Execute "play" order: Start every single case test
|
34
33
|
check_cases!
|
35
34
|
instance_eval(&block)
|
36
35
|
# Run export if user pass option command "--export=json"
|
37
|
-
i =
|
36
|
+
i = Project.value[:options]["export"]
|
38
37
|
export(format: i.to_sym) unless i.nil?
|
39
38
|
# Accept "configfile" param REVISE There exists?
|
40
|
-
i =
|
39
|
+
i = Project.value[:options]["configfile"]
|
41
40
|
export(format: i.to_sym) unless i.nil?
|
42
41
|
end
|
43
42
|
|
44
43
|
def export(args = {})
|
45
|
-
ExportManager.new.call(
|
44
|
+
ExportManager.new.call(
|
45
|
+
@report,
|
46
|
+
@cases,
|
47
|
+
args,
|
48
|
+
Project.value[:format]
|
49
|
+
)
|
46
50
|
end
|
47
51
|
|
48
52
|
def send(args = {})
|
@@ -1,32 +1,33 @@
|
|
1
1
|
require_relative "hall_of_fame"
|
2
|
+
require_relative "../utils/project"
|
2
3
|
|
3
4
|
class CaseManager
|
4
5
|
private
|
5
6
|
|
6
|
-
##
|
7
|
-
# Start checking every single case
|
8
7
|
def check_cases!
|
9
|
-
|
10
|
-
|
8
|
+
# Start checking every single case
|
9
|
+
app = Project.value
|
11
10
|
# Load configurations from config file
|
12
|
-
configdata = ConfigFileReader.read(
|
13
|
-
app
|
14
|
-
app
|
15
|
-
app
|
16
|
-
app
|
11
|
+
configdata = ConfigFileReader.read(Project.value[:config_path])
|
12
|
+
app[:ialias] = configdata[:alias]
|
13
|
+
app[:global] = configdata[:global]
|
14
|
+
app[:global][:tt_testname] = app[:global][:tt_testname] || app[:test_name]
|
15
|
+
app[:global][:tt_sequence] = false if app[:global][:tt_sequence].nil?
|
17
16
|
|
18
17
|
# Create out dir
|
19
|
-
outdir = app
|
18
|
+
outdir = app[:global][:tt_outdir] || File.join("var", app[:global][:tt_testname])
|
20
19
|
ensure_dir outdir
|
21
20
|
@report.output_dir = outdir
|
22
21
|
|
23
22
|
# Fill report head
|
24
|
-
open_main_report(app
|
23
|
+
open_main_report(app[:config_path])
|
25
24
|
|
26
25
|
# create cases and run
|
27
26
|
configdata[:cases].each { |config| @cases << Case.new(config) }
|
28
27
|
start_time = run_all_cases # run cases
|
29
28
|
|
29
|
+
# TODO: merge these 2 methdos
|
30
|
+
# TODO: CloseManager.call ???
|
30
31
|
uniques = collect_uniques_for_all_cases
|
31
32
|
close_reports_for_all_cases(uniques)
|
32
33
|
close_main_report(start_time)
|
@@ -36,7 +37,8 @@ class CaseManager
|
|
36
37
|
start_time = Time.now
|
37
38
|
verboseln Rainbow("-" * 36).green
|
38
39
|
verboseln Rainbow("Started at #{start_time}").green
|
39
|
-
if Application.instance.global[:tt_sequence] == true
|
40
|
+
# if Application.instance.global[:tt_sequence] == true
|
41
|
+
if Project.value[:global][:tt_sequence] == true
|
40
42
|
# Run every case in sequence
|
41
43
|
@cases.each(&:play)
|
42
44
|
else
|
@@ -1,16 +1,15 @@
|
|
1
|
-
require_relative "../
|
1
|
+
require_relative "../utils/project"
|
2
2
|
require_relative "case_manager"
|
3
3
|
|
4
4
|
def use(filename)
|
5
5
|
filename += ".rb"
|
6
|
-
|
7
|
-
rbfiles = File.join(app.project_path, "**", filename)
|
6
|
+
rbfiles = File.join(Project.value[:project_path], "**", filename)
|
8
7
|
files = Dir.glob(rbfiles)
|
9
8
|
findfiles = []
|
10
9
|
files.sort.each { |f| findfiles << f if f.include?(filename) }
|
11
10
|
begin
|
12
11
|
require_relative findfiles.first
|
13
|
-
|
12
|
+
Project.value[:uses] << File.basename(findfiles.first)
|
14
13
|
rescue
|
15
14
|
puts "[ERROR] Unknown file : #{filename}"
|
16
15
|
puts " Check line : use '#{filename}'"
|
@@ -19,7 +18,7 @@ def use(filename)
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def define_macro(name, *args, &block)
|
22
|
-
|
21
|
+
Project.value[:macros][name] = {args: args, block: block}
|
23
22
|
end
|
24
23
|
alias def_macro define_macro
|
25
24
|
alias defmacro define_macro
|
@@ -28,13 +27,12 @@ alias defmacro define_macro
|
|
28
27
|
# @param name (String) Group name
|
29
28
|
# @param block (Block) Tests code
|
30
29
|
def group(name, &block)
|
31
|
-
|
30
|
+
Project.value[:groups] << {name: name, block: block}
|
32
31
|
end
|
33
32
|
alias task group
|
34
33
|
|
35
|
-
# Start test
|
36
|
-
# @param block (Block) Extra code executed at the end.
|
37
34
|
def play(&block)
|
35
|
+
# Start test
|
38
36
|
CaseManager.new.play(&block)
|
39
37
|
end
|
40
38
|
alias start play
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rainbow"
|
4
|
-
require_relative "../application"
|
5
4
|
|
6
5
|
##
|
7
6
|
# Execute "export" order: Export every case report
|
@@ -12,7 +11,7 @@ class ExportManager
|
|
12
11
|
# @param main_report (Report)
|
13
12
|
# @param cases (Array)
|
14
13
|
# @param input (Hash) Selected export options
|
15
|
-
def call(main_report, cases, args)
|
14
|
+
def call(main_report, cases, args, default_format)
|
16
15
|
if args.class != Hash
|
17
16
|
puts Rainbow("[ERROR] Export argument error!").red
|
18
17
|
puts Rainbow(" Revise: export #{args}").red
|
@@ -23,7 +22,7 @@ class ExportManager
|
|
23
22
|
|
24
23
|
options = strings2symbols(args)
|
25
24
|
if options[:format].nil?
|
26
|
-
options[:format] =
|
25
|
+
options[:format] = default_format
|
27
26
|
end
|
28
27
|
|
29
28
|
# Step 1: Export case reports
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative "../
|
1
|
+
require_relative "../utils/project"
|
2
2
|
|
3
3
|
class CaseManager
|
4
4
|
class HallOfFame
|
@@ -9,22 +9,21 @@ class CaseManager
|
|
9
9
|
def call
|
10
10
|
celebrities = {}
|
11
11
|
|
12
|
-
@cases.each do |
|
13
|
-
|
12
|
+
@cases.each do |acase|
|
13
|
+
next if acase.skip
|
14
|
+
|
15
|
+
grade = acase.grade
|
14
16
|
label = if celebrities[grade]
|
15
17
|
celebrities[grade] + "*"
|
16
18
|
else
|
17
19
|
"*"
|
18
20
|
end
|
19
|
-
celebrities[grade] = label
|
21
|
+
celebrities[grade] = label
|
20
22
|
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
app = Application.instance
|
26
|
-
app.options[:case_number] = @cases.size
|
27
|
-
app.hall_of_fame = list
|
24
|
+
Project.value[:options][:case_number] = @cases.size
|
25
|
+
ordered_list = celebrities.sort_by { |key, _value| key }
|
26
|
+
Project.value[:hall_of_fame] = ordered_list.reverse
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require "rainbow"
|
2
|
+
require_relative "../utils/project"
|
3
|
+
require_relative "../utils/settings"
|
2
4
|
|
3
5
|
class CaseManager
|
4
6
|
private
|
@@ -7,15 +9,15 @@ class CaseManager
|
|
7
9
|
# Open main report (resume report)
|
8
10
|
# @param config_filepath (String)
|
9
11
|
def open_main_report(config_filepath)
|
10
|
-
app = Application.instance
|
12
|
+
# app = Application.instance
|
11
13
|
|
12
14
|
@report.head[:tt_title] = "Teuton (#{Teuton::VERSION})"
|
13
|
-
@report.head[:tt_scriptname] = trim(
|
15
|
+
@report.head[:tt_scriptname] = trim(Project.value[:script_path])
|
14
16
|
@report.head[:tt_configfile] = trim(config_filepath)
|
15
|
-
@report.head[:tt_pwd] =
|
17
|
+
@report.head[:tt_pwd] = Project.value[:running_basedir]
|
16
18
|
@report.head[:tt_debug] = true if @debug
|
17
|
-
|
18
|
-
@report.head.merge!(
|
19
|
+
@report.head[:tt_uses] = Project.value[:uses].join(", ") # TO-REVISE
|
20
|
+
@report.head.merge!(Project.value[:global])
|
19
21
|
end
|
20
22
|
|
21
23
|
def close_main_report(start_time)
|
@@ -29,7 +31,7 @@ class CaseManager
|
|
29
31
|
verboseln Rainbow("-" * 36).green
|
30
32
|
verboseln " "
|
31
33
|
|
32
|
-
app = Application.instance
|
34
|
+
# app = Application.instance
|
33
35
|
@cases.each do |c|
|
34
36
|
line = {}
|
35
37
|
if c.skip?
|
@@ -46,9 +48,9 @@ class CaseManager
|
|
46
48
|
else
|
47
49
|
line[:skip] = false
|
48
50
|
line[:id] = format("%<id>02d", {id: c.id.to_i})
|
49
|
-
line[:letter] =
|
50
|
-
line[:letter] =
|
51
|
-
line[:letter] =
|
51
|
+
line[:letter] = Settings.letter[:cross] if c.grade.zero?
|
52
|
+
line[:letter] = Settings.letter[:error] if c.grade < 50.0
|
53
|
+
line[:letter] = Settings.letter[:ok] if c.grade.to_i == 100
|
52
54
|
line[:grade] = c.grade.to_f
|
53
55
|
line[:members] = c.members
|
54
56
|
line[:conn_status] = c.conn_status
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "rainbow"
|
2
2
|
require "terminal-table"
|
3
|
-
require_relative "../
|
3
|
+
require_relative "../utils/project"
|
4
4
|
|
5
5
|
# | Verbosity level | Description |
|
6
6
|
# | :-------------: | ----------- |
|
@@ -15,7 +15,7 @@ class ShowReport
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def call(verbose)
|
18
|
-
return if
|
18
|
+
return if Project.quiet?
|
19
19
|
|
20
20
|
show_initial_configurations if verbose > 2
|
21
21
|
if filename.to_s.include? "resume"
|
@@ -121,8 +121,7 @@ class ShowReport
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def show_hall_of_fame
|
124
|
-
|
125
|
-
return if app.hall_of_fame.size < 3
|
124
|
+
return if Project.value[:hall_of_fame].size < 3
|
126
125
|
|
127
126
|
puts Rainbow("HALL OF FAME").bright
|
128
127
|
my_screen_table = Terminal::Table.new do |st|
|
@@ -133,9 +132,8 @@ class ShowReport
|
|
133
132
|
puts "#{my_screen_table}\n"
|
134
133
|
end
|
135
134
|
|
136
|
-
##
|
137
|
-
# Trim absolute path values
|
138
135
|
def trim(input)
|
136
|
+
# Trim absolute path values
|
139
137
|
return input unless input.to_s.start_with? Dir.pwd.to_s
|
140
138
|
return input if input == Dir.pwd.to_s
|
141
139
|
|
@@ -1,10 +1,9 @@
|
|
1
|
-
require_relative "../application"
|
2
1
|
require "fileutils"
|
3
|
-
|
4
|
-
require "rainbow"
|
2
|
+
require_relative "../utils/project"
|
5
3
|
|
6
4
|
module Utils
|
7
5
|
def ensure_dir(dirname)
|
6
|
+
# TODO: Mover a la carpeta Utils
|
8
7
|
# Create the directory if it dosn't exist.
|
9
8
|
unless Dir.exist?(dirname)
|
10
9
|
FileUtils.mkdir_p(dirname)
|
@@ -12,49 +11,4 @@ module Utils
|
|
12
11
|
end
|
13
12
|
true
|
14
13
|
end
|
15
|
-
|
16
|
-
def encode_and_split(encoding, text)
|
17
|
-
# Convert text to UTF-8 deleting unknown chars
|
18
|
-
text ||= "" # Ensure text is not nil
|
19
|
-
flag = [:default, "UTF-8"].include? encoding
|
20
|
-
return text.encode("UTF-8", invalid: :replace).split("\n") if flag
|
21
|
-
|
22
|
-
# Convert text from input ENCODING to UTF-8
|
23
|
-
ec = Encoding::Converter.new(encoding.to_s, "UTF-8")
|
24
|
-
begin
|
25
|
-
text = ec.convert(text)
|
26
|
-
rescue => e
|
27
|
-
puts "[ERROR] #{e}: Declare text encoding..."
|
28
|
-
puts " run 'command', on: :host, :encoding => 'ISO-8859-1'"
|
29
|
-
end
|
30
|
-
|
31
|
-
text.split("\n")
|
32
|
-
end
|
33
|
-
|
34
|
-
def my_execute(cmd, encoding = "UTF-8")
|
35
|
-
return {exitstatus: 0, content: ""} if Application.instance.debug
|
36
|
-
|
37
|
-
begin
|
38
|
-
# text = `#{cmd}`
|
39
|
-
# exitstatus = $CHILD_STATUS.exitstatus
|
40
|
-
text, status = Open3.capture2e(cmd)
|
41
|
-
exitstatus = status.exitstatus
|
42
|
-
rescue => e
|
43
|
-
verbose Rainbow("!").green
|
44
|
-
text = e.to_s
|
45
|
-
exitstatus = 1
|
46
|
-
end
|
47
|
-
content = encode_and_split(encoding, text)
|
48
|
-
{exitstatus: exitstatus, content: content}
|
49
|
-
end
|
50
|
-
|
51
|
-
def verboseln(text)
|
52
|
-
verbose(text + "\n")
|
53
|
-
end
|
54
|
-
|
55
|
-
def verbose(text)
|
56
|
-
return if Application.instance.quiet?
|
57
|
-
|
58
|
-
print text
|
59
|
-
end
|
60
14
|
end
|