teuton 2.6.0 → 2.7.0
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/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
|