teuton 2.3.6 → 2.3.7
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/README.md +3 -4
- data/bin/teuton +1 -1
- data/docs/CHANGELOG.md +8 -0
- data/docs/changelog/v2.4.md +16 -0
- data/docs/dsl/definition/expect.md +11 -7
- data/docs/dsl/definition/result.md +7 -6
- data/docs/dsl/definition/run_local.md +0 -1
- data/docs/dsl/definition/target.md +1 -1
- data/docs/dsl/execution/export.md +14 -16
- data/docs/dsl/execution/send.md +1 -1
- data/docs/dsl/setting/get.md +5 -5
- data/docs/es/exit_code.md +59 -0
- data/docs/es/guess_os.md +28 -0
- data/docs/{Challenge-Server-Project.md → ideas/Challenge-Server-Project.md} +0 -0
- data/docs/{changelog → ideas}/contributions.md +0 -0
- data/docs/{changelog → ideas}/ideas.md +0 -0
- data/docs/{changelog → ideas}/servidor-de-retos.md +0 -0
- data/docs/learn/{example-01-target.md → 01-target.md} +1 -3
- data/docs/learn/{example-02-config.md → 02-config.md} +1 -3
- data/docs/learn/{example-03-remote-hosts.md → 03-remote_hosts.md} +10 -10
- data/docs/learn/{example-04-new-test.md → 04-new_test.md} +8 -16
- data/docs/learn/{example-05-use.md → 05-use.md} +1 -3
- data/docs/learn/{example-06-debug.md → 06-debug.md} +1 -3
- data/docs/learn/{example-07-log.md → 07-log.md} +1 -3
- data/docs/learn/{example-08-readme.md → 08-readme.md} +1 -3
- data/docs/learn/{example-09-preserve.md → 09-preserve.md} +7 -4
- data/docs/learn/10-result.md +36 -0
- data/docs/learn/11-moodle_id.md +19 -0
- data/docs/learn/12-get_vars.md +37 -0
- data/docs/learn/13-include.md +59 -0
- data/docs/learn/16-exit_codes.md +24 -0
- data/docs/learn/README.md +19 -17
- data/lib/teuton/application.rb +24 -17
- data/lib/teuton/case_manager/case/builtin/main.rb +2 -3
- data/lib/teuton/case_manager/case/builtin/package.rb +2 -3
- data/lib/teuton/case_manager/case/builtin/service.rb +4 -5
- data/lib/teuton/case_manager/case/builtin/teuton_file.rb +3 -4
- data/lib/teuton/case_manager/case/builtin/teuton_host.rb +5 -6
- data/lib/teuton/case_manager/case/builtin/user.rb +1 -2
- data/lib/teuton/case_manager/case/case.rb +27 -27
- data/lib/teuton/case_manager/case/close.rb +2 -2
- data/lib/teuton/case_manager/case/config.rb +14 -14
- data/lib/teuton/case_manager/case/dsl/expect.rb +46 -39
- data/lib/teuton/case_manager/case/dsl/goto.rb +2 -2
- data/lib/teuton/case_manager/case/dsl/log.rb +5 -6
- data/lib/teuton/case_manager/case/dsl/macro.rb +11 -7
- data/lib/teuton/case_manager/case/dsl/main.rb +8 -8
- data/lib/teuton/case_manager/case/dsl/send.rb +11 -14
- data/lib/teuton/case_manager/case/dsl/unique.rb +1 -3
- data/lib/teuton/case_manager/case/main.rb +5 -5
- data/lib/teuton/case_manager/case/play.rb +1 -1
- data/lib/teuton/case_manager/case/result/ext_array.rb +9 -9
- data/lib/teuton/case_manager/case/result/ext_compare.rb +44 -58
- data/lib/teuton/case_manager/case/result/ext_filter.rb +20 -8
- data/lib/teuton/case_manager/case/result/result.rb +19 -18
- data/lib/teuton/case_manager/case/runner.rb +53 -60
- data/lib/teuton/case_manager/case_manager.rb +15 -15
- data/lib/teuton/case_manager/check_cases.rb +1 -4
- data/lib/teuton/case_manager/dsl.rb +5 -5
- data/lib/teuton/case_manager/export_manager.rb +8 -19
- data/lib/teuton/case_manager/hall_of_fame.rb +4 -6
- data/lib/teuton/case_manager/main.rb +4 -5
- data/lib/teuton/case_manager/report.rb +21 -16
- data/lib/teuton/case_manager/show.rb +2 -2
- data/lib/teuton/case_manager/utils.rb +13 -14
- data/lib/teuton/check/builtin.rb +5 -1
- data/lib/teuton/check/dsl.rb +10 -11
- data/lib/teuton/check/laboratory.rb +13 -15
- data/lib/teuton/check/show.rb +33 -35
- data/lib/teuton/cli.rb +31 -35
- data/lib/teuton/files/start.rb +3 -6
- data/lib/teuton/readme/dsl.rb +12 -6
- data/lib/teuton/readme/lang.rb +20 -21
- data/lib/teuton/readme/readme.rb +40 -42
- data/lib/teuton/report/close.rb +1 -3
- data/lib/teuton/report/formatter/array_formatter.rb +28 -39
- data/lib/teuton/report/formatter/base_formatter.rb +2 -13
- data/lib/teuton/report/formatter/csv_formatter.rb +12 -18
- data/lib/teuton/report/formatter/formatter_factory.rb +31 -29
- data/lib/teuton/report/formatter/html_formatter.rb +37 -21
- data/lib/teuton/report/formatter/json_formatter.rb +2 -8
- data/lib/teuton/report/formatter/list_formatter.rb +6 -12
- data/lib/teuton/report/formatter/moodle_csv_formatter.rb +3 -6
- data/lib/teuton/report/formatter/resume_array_formatter.rb +1 -1
- data/lib/teuton/report/formatter/resume_html_formatter.rb +29 -19
- data/lib/teuton/report/formatter/resume_json_formatter.rb +2 -3
- data/lib/teuton/report/formatter/resume_list_formatter.rb +4 -4
- data/lib/teuton/report/formatter/resume_txt_formatter.rb +14 -18
- data/lib/teuton/report/formatter/resume_yaml_formatter.rb +1 -9
- data/lib/teuton/report/formatter/txt_formatter.rb +19 -20
- data/lib/teuton/report/formatter/xml_formatter.rb +29 -37
- data/lib/teuton/report/formatter/yaml_formatter.rb +2 -12
- data/lib/teuton/report/report.rb +10 -10
- data/lib/teuton/report/show.rb +14 -33
- data/lib/teuton/skeleton.rb +6 -14
- data/lib/teuton/utils/configfile_reader.rb +22 -21
- data/lib/teuton/utils/name_file_finder.rb +21 -26
- data/lib/teuton/utils/verbose.rb +1 -2
- data/lib/teuton/version.rb +3 -4
- data/lib/teuton.rb +5 -6
- metadata +60 -86
- data/bin/check_teuton +0 -41
|
@@ -1,43 +1,33 @@
|
|
|
1
|
+
require "net/ssh"
|
|
2
|
+
require "net/sftp"
|
|
3
|
+
require "net/telnet"
|
|
4
|
+
require_relative "dsl/log"
|
|
1
5
|
|
|
2
|
-
require 'net/ssh'
|
|
3
|
-
require 'net/sftp'
|
|
4
|
-
require 'net/telnet'
|
|
5
|
-
require_relative 'dsl/log'
|
|
6
|
-
|
|
7
|
-
# Class Case
|
|
8
|
-
# * run_local_cmd
|
|
9
|
-
# * run_remote_cmd
|
|
10
|
-
# * run_remote_cmd_ssh
|
|
11
|
-
# * reconfigure_command_with_gateway
|
|
12
|
-
# * run_remote_cmd_telnet
|
|
13
6
|
class Case
|
|
14
|
-
|
|
15
7
|
private
|
|
16
8
|
|
|
17
9
|
def run_cmd_on(host)
|
|
18
10
|
protocol = @config.get("#{host}_protocol".to_sym)
|
|
19
11
|
ip = @config.get("#{host}_ip".to_sym)
|
|
20
12
|
|
|
21
|
-
if
|
|
22
|
-
run_cmd_localhost
|
|
23
|
-
elsif protocol.to_s.downcase ==
|
|
13
|
+
if protocol.to_s.downcase == "local" || host.to_s == "localhost"
|
|
14
|
+
run_cmd_localhost # Protocol force => local
|
|
15
|
+
elsif protocol.to_s.downcase == "ssh"
|
|
24
16
|
run_cmd_remote_ssh(host) # Protocol force => ssh
|
|
25
|
-
elsif protocol.to_s.downcase ==
|
|
26
|
-
|
|
27
|
-
elsif
|
|
28
|
-
run_cmd_localhost
|
|
29
|
-
elsif ip ==
|
|
17
|
+
elsif protocol.to_s.downcase == "telnet"
|
|
18
|
+
run_cmd_remote_telnet(host) # Protocol force => telnet
|
|
19
|
+
elsif ip.to_s.downcase == "localhost" || ip.to_s.include?("127.0.0.")
|
|
20
|
+
run_cmd_localhost
|
|
21
|
+
elsif ip == "NODATA"
|
|
30
22
|
log("#{host} IP not found!", :error)
|
|
31
23
|
else
|
|
32
24
|
run_cmd_remote_ssh host
|
|
33
25
|
end
|
|
34
26
|
end
|
|
35
27
|
|
|
36
|
-
|
|
37
|
-
# Run command on local machine
|
|
38
|
-
def run_cmd_localhost()
|
|
28
|
+
def run_cmd_localhost
|
|
39
29
|
@action[:conn_type] = :local
|
|
40
|
-
i = my_execute(
|
|
30
|
+
i = my_execute(@action[:command], @action[:encoding])
|
|
41
31
|
@result.exitstatus = i[:exitstatus]
|
|
42
32
|
@result.content = i[:content]
|
|
43
33
|
end
|
|
@@ -47,9 +37,9 @@ class Case
|
|
|
47
37
|
# @param input_hostname (Symbol or String)
|
|
48
38
|
def run_cmd_remote(input_hostname)
|
|
49
39
|
hostname = input_hostname.to_s
|
|
50
|
-
i = (hostname +
|
|
40
|
+
i = (hostname + "_protocol").to_sym
|
|
51
41
|
protocol = @config.get(i) if @config.get(i)
|
|
52
|
-
protocol = :ssh if protocol.nil? || protocol ==
|
|
42
|
+
protocol = :ssh if protocol.nil? || protocol == "NODATA"
|
|
53
43
|
protocol = protocol.to_sym
|
|
54
44
|
case protocol
|
|
55
45
|
when :ssh
|
|
@@ -57,7 +47,7 @@ class Case
|
|
|
57
47
|
when :telnet
|
|
58
48
|
run_cmd_remote_telnet(input_hostname)
|
|
59
49
|
when :local
|
|
60
|
-
run_cmd_localhost
|
|
50
|
+
run_cmd_localhost
|
|
61
51
|
else
|
|
62
52
|
log("Protocol #{protocol} unknown! Use ssh or telnet.", :error)
|
|
63
53
|
end
|
|
@@ -72,9 +62,9 @@ class Case
|
|
|
72
62
|
port = @config.get("#{hostname}_port".to_sym).to_i
|
|
73
63
|
port = 22 if port.zero?
|
|
74
64
|
|
|
75
|
-
unless @config.get("#{hostname}_route".to_sym) ==
|
|
65
|
+
unless @config.get("#{hostname}_route".to_sym) == "NODATA"
|
|
76
66
|
# Reconfigure command with gateway. Example host1_route: IP.
|
|
77
|
-
hostname2 = hostname
|
|
67
|
+
# hostname2 = hostname ¿not used?
|
|
78
68
|
ip2 = ip
|
|
79
69
|
username2 = username
|
|
80
70
|
password2 = password
|
|
@@ -85,26 +75,27 @@ class Case
|
|
|
85
75
|
password = @config.get("#{hostname}_password".to_sym).to_s
|
|
86
76
|
ostype = @config.get("#{hostname}_ostype".to_sym).to_s
|
|
87
77
|
|
|
88
|
-
if ostype.downcase.start_with?
|
|
89
|
-
|
|
90
|
-
@action[:command] = "echo y | plink #{username2}@#{ip2} -ssh -pw #{password2} \"#{command2}\""
|
|
78
|
+
@action[:command] = if ostype.downcase.start_with? "win"
|
|
79
|
+
"echo y | plink #{username2}@#{ip2} -ssh -pw #{password2} \"#{command2}\""
|
|
91
80
|
else
|
|
92
|
-
|
|
81
|
+
"sshpass -p #{password2} #{username2}@#{ip2} #{command2}"
|
|
93
82
|
end
|
|
94
83
|
end
|
|
95
84
|
|
|
96
|
-
text =
|
|
85
|
+
text = ""
|
|
97
86
|
begin
|
|
98
87
|
if @sessions[hostname].nil?
|
|
99
|
-
@sessions[hostname] = Net::SSH.start(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
88
|
+
@sessions[hostname] = Net::SSH.start(
|
|
89
|
+
ip,
|
|
90
|
+
username,
|
|
91
|
+
port: port,
|
|
92
|
+
password: password,
|
|
93
|
+
keepalive: true,
|
|
94
|
+
timeout: 30,
|
|
95
|
+
non_interactive: true
|
|
96
|
+
)
|
|
106
97
|
end
|
|
107
|
-
if @sessions[hostname].
|
|
98
|
+
if @sessions[hostname].instance_of? Net::SSH::Connection::Session
|
|
108
99
|
text = @sessions[hostname].exec!(@action[:command])
|
|
109
100
|
end
|
|
110
101
|
rescue Errno::EHOSTUNREACH
|
|
@@ -116,18 +107,18 @@ class Case
|
|
|
116
107
|
@sessions[hostname] = :nosession
|
|
117
108
|
@conn_status[hostname] = :error_authentication_failed
|
|
118
109
|
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
119
|
-
log(
|
|
110
|
+
log("SSH::AuthenticationFailed!", :error)
|
|
120
111
|
rescue Net::SSH::HostKeyMismatch
|
|
121
112
|
@sessions[hostname] = :nosession
|
|
122
113
|
@conn_status[hostname] = :host_key_mismatch
|
|
123
114
|
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
124
|
-
log(
|
|
115
|
+
log("SSH::HostKeyMismatch!", :error)
|
|
125
116
|
log("* The destination server's fingerprint is not matching " \
|
|
126
|
-
|
|
127
|
-
log(
|
|
117
|
+
"what is in your local known_hosts file.", :error)
|
|
118
|
+
log("* Remove the existing entry in your local known_hosts file", :error)
|
|
128
119
|
log("* Try this => ssh-keygen -f '/home/USERNAME/.ssh/known_hosts' " \
|
|
129
120
|
"-R #{ip}", :error)
|
|
130
|
-
rescue
|
|
121
|
+
rescue => e
|
|
131
122
|
@sessions[hostname] = :nosession
|
|
132
123
|
@conn_status[hostname] = :error
|
|
133
124
|
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
@@ -142,21 +133,23 @@ class Case
|
|
|
142
133
|
|
|
143
134
|
def run_cmd_remote_telnet(input_hostname)
|
|
144
135
|
@action[:conn_type] = :telnet
|
|
145
|
-
app = Application.instance
|
|
136
|
+
# app = Application.instance ¿not used?
|
|
146
137
|
hostname = input_hostname.to_s
|
|
147
|
-
ip = @config.get((hostname +
|
|
148
|
-
username = @config.get((hostname +
|
|
149
|
-
password = @config.get((hostname +
|
|
150
|
-
text =
|
|
138
|
+
ip = @config.get((hostname + "_ip").to_sym)
|
|
139
|
+
username = @config.get((hostname + "_username").to_sym).to_s
|
|
140
|
+
password = @config.get((hostname + "_password").to_sym).to_s
|
|
141
|
+
text = ""
|
|
151
142
|
begin
|
|
152
143
|
if @sessions[hostname].nil? || @sessions[hostname] == :ok
|
|
153
|
-
h = Net::Telnet.new(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
144
|
+
h = Net::Telnet.new(
|
|
145
|
+
"Host" => ip,
|
|
146
|
+
"Timeout" => 30,
|
|
147
|
+
"Prompt" => /login|teuton|[$%#>]/
|
|
148
|
+
)
|
|
149
|
+
# "Prompt" => Regexp.new(username[1, 40]))
|
|
150
|
+
# "Prompt" => /[$%#>] \z/n)
|
|
158
151
|
h.login(username, password)
|
|
159
|
-
text =
|
|
152
|
+
text = ""
|
|
160
153
|
h.cmd(@action[:command]) { |i| text << i }
|
|
161
154
|
h.close
|
|
162
155
|
@sessions[hostname] = :ok
|
|
@@ -166,13 +159,13 @@ class Case
|
|
|
166
159
|
@conn_status[hostname] = :open_timeout
|
|
167
160
|
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
168
161
|
log(" ExceptionType=<Net::OpenTimeout> doing <telnet #{ip}>", :error)
|
|
169
|
-
log(
|
|
162
|
+
log(" └── Revise host IP!", :warn)
|
|
170
163
|
rescue Net::ReadTimeout
|
|
171
164
|
@sessions[hostname] = :nosession
|
|
172
165
|
@conn_status[hostname] = :read_timeout
|
|
173
166
|
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
174
167
|
log(" ExceptionType=<Net::ReadTimeout> doing <telnet #{ip}>", :error)
|
|
175
|
-
rescue
|
|
168
|
+
rescue => e
|
|
176
169
|
@sessions[hostname] = :nosession
|
|
177
170
|
@conn_status[hostname] = :error
|
|
178
171
|
verbose Rainbow(Application.instance.letter[:error]).red.bright
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative
|
|
6
|
-
require_relative
|
|
7
|
-
require_relative
|
|
8
|
-
require_relative
|
|
9
|
-
require_relative
|
|
10
|
-
require_relative
|
|
3
|
+
require "singleton"
|
|
4
|
+
require_relative "../application"
|
|
5
|
+
require_relative "../report/report"
|
|
6
|
+
require_relative "../utils/configfile_reader"
|
|
7
|
+
require_relative "case/case"
|
|
8
|
+
require_relative "export_manager"
|
|
9
|
+
require_relative "main"
|
|
10
|
+
require_relative "utils"
|
|
11
11
|
|
|
12
12
|
# This class does all the job
|
|
13
13
|
# Organize the hole job, sending orders to others classes
|
|
@@ -28,7 +28,7 @@ class CaseManager
|
|
|
28
28
|
def initialize
|
|
29
29
|
@cases = []
|
|
30
30
|
@report = Report.new(0)
|
|
31
|
-
@report.filename =
|
|
31
|
+
@report.filename = "resume"
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
##
|
|
@@ -38,10 +38,10 @@ class CaseManager
|
|
|
38
38
|
check_cases!
|
|
39
39
|
instance_eval(&block)
|
|
40
40
|
# Run export if user pass option command "--export=json"
|
|
41
|
-
i = Application.instance.options[
|
|
41
|
+
i = Application.instance.options["export"]
|
|
42
42
|
export(format: i.to_sym) unless i.nil?
|
|
43
43
|
# Accept "configfile" param REVISE There exists?
|
|
44
|
-
i = Application.instance.options[
|
|
44
|
+
i = Application.instance.options["configfile"]
|
|
45
45
|
export(format: i.to_sym) unless i.nil?
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -52,8 +52,8 @@ class CaseManager
|
|
|
52
52
|
if args.class != Hash
|
|
53
53
|
puts "[ERROR] CaseManager#export: Argument = <#{args}>, " \
|
|
54
54
|
"class = #{args.class}"
|
|
55
|
-
puts
|
|
56
|
-
raise
|
|
55
|
+
puts " Usage: export :format => :colored_text"
|
|
56
|
+
raise "[ERROR] CaseManager#export: Argument error!"
|
|
57
57
|
end
|
|
58
58
|
# Export report files
|
|
59
59
|
ExportManager.run(@report, @cases, args)
|
|
@@ -64,8 +64,8 @@ class CaseManager
|
|
|
64
64
|
# @param args (Hash) Send options
|
|
65
65
|
def send(args = {})
|
|
66
66
|
threads = []
|
|
67
|
-
puts
|
|
68
|
-
puts "[INFO] Sending files...#{args
|
|
67
|
+
puts ""
|
|
68
|
+
puts "[INFO] Sending files...#{args}"
|
|
69
69
|
@cases.each { |c| threads << Thread.new { c.send(args) } }
|
|
70
70
|
threads.each(&:join)
|
|
71
71
|
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
# CaseManager: check_cases!
|
|
5
3
|
class CaseManager
|
|
6
4
|
private
|
|
7
5
|
|
|
@@ -18,8 +16,7 @@ class CaseManager
|
|
|
18
16
|
app.global[:tt_sequence] = false if app.global[:tt_sequence].nil?
|
|
19
17
|
|
|
20
18
|
# Create out dir
|
|
21
|
-
outdir = app.global[:tt_outdir] ||
|
|
22
|
-
File.join('var', app.global[:tt_testname])
|
|
19
|
+
outdir = app.global[:tt_outdir] || File.join("var", app.global[:tt_testname])
|
|
23
20
|
ensure_dir outdir
|
|
24
21
|
@report.output_dir = outdir
|
|
25
22
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
require_relative
|
|
2
|
-
require_relative
|
|
1
|
+
require_relative "../application"
|
|
2
|
+
require_relative "case_manager"
|
|
3
3
|
|
|
4
4
|
# Define filename to be used into our test
|
|
5
5
|
# @param filename (String) Filename to be required
|
|
6
6
|
def use(filename)
|
|
7
|
-
filename +=
|
|
7
|
+
filename += ".rb"
|
|
8
8
|
app = Application.instance
|
|
9
9
|
rbfiles = File.join(app.project_path, "**", filename)
|
|
10
10
|
files = Dir.glob(rbfiles)
|
|
@@ -18,7 +18,7 @@ end
|
|
|
18
18
|
# @param name (String) macro name
|
|
19
19
|
# @param block (Block) macro code
|
|
20
20
|
def define_macro(name, *args, &block)
|
|
21
|
-
Application.instance.macros[name] = {
|
|
21
|
+
Application.instance.macros[name] = {args: args, block: block}
|
|
22
22
|
end
|
|
23
23
|
alias def_macro define_macro
|
|
24
24
|
alias defmacro define_macro
|
|
@@ -27,7 +27,7 @@ alias defmacro define_macro
|
|
|
27
27
|
# @param name (String) Group name
|
|
28
28
|
# @param block (Block) Tests code
|
|
29
29
|
def group(name, &block)
|
|
30
|
-
Application.instance.groups << {
|
|
30
|
+
Application.instance.groups << {name: name, block: block}
|
|
31
31
|
end
|
|
32
32
|
alias task group
|
|
33
33
|
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "../application"
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
# ExportManager is used by CaseManager to export output reports
|
|
7
5
|
module ExportManager
|
|
8
6
|
##
|
|
9
7
|
# Run export function
|
|
10
8
|
# @param main_report (Report)
|
|
11
9
|
# @param cases (Array)
|
|
12
10
|
# @param input (Hash) Selected export options
|
|
13
|
-
# rubocop:disable Metrics/AbcSize
|
|
14
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
15
11
|
def self.run(main_report, cases, input)
|
|
16
12
|
args = strings2symbols(input)
|
|
17
13
|
|
|
@@ -29,42 +25,35 @@ module ExportManager
|
|
|
29
25
|
# Step 3: Preserve files if required
|
|
30
26
|
preserve_files if args[:preserve] == true
|
|
31
27
|
end
|
|
32
|
-
# rubocop:enable Metrics/AbcSize
|
|
33
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
34
28
|
|
|
35
29
|
##
|
|
36
30
|
# Convert Hash String values into Symbol values
|
|
37
31
|
# @param input (Hash)
|
|
38
|
-
# rubocop:disable Style/ConditionalAssignment
|
|
39
32
|
private_class_method def self.strings2symbols(input)
|
|
40
33
|
args = {}
|
|
41
34
|
input.each_pair do |key, value|
|
|
42
|
-
if value.
|
|
43
|
-
|
|
35
|
+
args[key] = if value.instance_of? String
|
|
36
|
+
value.to_sym
|
|
44
37
|
else
|
|
45
|
-
|
|
38
|
+
value
|
|
46
39
|
end
|
|
47
40
|
end
|
|
48
41
|
args
|
|
49
42
|
end
|
|
50
|
-
# rubocop:enable Style/ConditionalAssignment
|
|
51
43
|
|
|
52
44
|
##
|
|
53
45
|
# Preserve output files for current project
|
|
54
|
-
# rubocop:disable Metrics/AbcSize
|
|
55
|
-
# rubocop:disable Metrics/MethodLength
|
|
56
46
|
private_class_method def self.preserve_files
|
|
57
47
|
app = Application.instance
|
|
58
48
|
t = Time.now
|
|
59
|
-
data = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'%<hour>02d%<min>02d%<sec>02d', data)
|
|
49
|
+
data = {year: t.year, month: t.month, day: t.day, hour: t.hour, min: t.min, sec: t.sec}
|
|
50
|
+
subdir = format("%<year>s%<month>02d%<day>02d-" \
|
|
51
|
+
"%<hour>02d%<min>02d%<sec>02d", data)
|
|
63
52
|
logdir = File.join(app.output_basedir, app.global[:tt_testname], subdir)
|
|
64
53
|
srcdir = File.join(app.output_basedir, app.global[:tt_testname])
|
|
65
54
|
puts "[INFO] Preserving files => #{logdir}"
|
|
66
55
|
FileUtils.mkdir(logdir)
|
|
67
|
-
Dir.glob(File.join(srcdir,
|
|
56
|
+
Dir.glob(File.join(srcdir, "**.*")).each { |file| FileUtils.cp(file, logdir) }
|
|
68
57
|
end
|
|
69
58
|
# rubocop:enable Metrics/AbcSize
|
|
70
59
|
# rubocop:enable Metrics/MethodLength
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
require_relative '../application'
|
|
1
|
+
require_relative "../application"
|
|
3
2
|
|
|
4
3
|
class CaseManager
|
|
5
|
-
|
|
6
4
|
private
|
|
7
5
|
|
|
8
6
|
def build_hall_of_fame
|
|
@@ -10,10 +8,10 @@ class CaseManager
|
|
|
10
8
|
|
|
11
9
|
@cases.each do |c|
|
|
12
10
|
grade = c.grade # report.tail[:grade]
|
|
13
|
-
if celebrities[grade]
|
|
14
|
-
|
|
11
|
+
label = if celebrities[grade]
|
|
12
|
+
celebrities[grade] + "*"
|
|
15
13
|
else
|
|
16
|
-
|
|
14
|
+
"*"
|
|
17
15
|
end
|
|
18
16
|
celebrities[grade] = label unless c.skip
|
|
19
17
|
end
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
require_relative
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
5
|
-
require_relative 'show'
|
|
1
|
+
require_relative "check_cases"
|
|
2
|
+
require_relative "hall_of_fame"
|
|
3
|
+
require_relative "report"
|
|
4
|
+
require_relative "show"
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
require
|
|
2
|
-
##
|
|
3
|
-
# Class CaseManager
|
|
4
|
-
# Methods related with report
|
|
5
|
-
class CaseManager
|
|
1
|
+
require "rainbow"
|
|
6
2
|
|
|
3
|
+
class CaseManager
|
|
7
4
|
private
|
|
8
5
|
|
|
9
6
|
##
|
|
@@ -27,22 +24,32 @@ class CaseManager
|
|
|
27
24
|
@report.tail[:finish_time] = finish_time
|
|
28
25
|
@report.tail[:duration] = finish_time - start_time
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
duration = format("%3.3f", (finish_time - start_time))
|
|
28
|
+
verbose Rainbow("\n==> Teuton: Duration=#{duration}").yellow.bright
|
|
31
29
|
verboseln Rainbow(" (#{finish_time})").yellow.bright
|
|
32
|
-
verboseln
|
|
30
|
+
verboseln " "
|
|
33
31
|
|
|
34
32
|
app = Application.instance
|
|
35
33
|
@cases.each do |c|
|
|
36
34
|
line = {}
|
|
37
35
|
if c.skip?
|
|
38
|
-
line = {
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
line = {
|
|
37
|
+
skip: true,
|
|
38
|
+
id: "-",
|
|
39
|
+
grade: 0.0,
|
|
40
|
+
letter: "",
|
|
41
|
+
members: "-",
|
|
42
|
+
conn_status: {},
|
|
43
|
+
moodle_id: "",
|
|
44
|
+
moodle_feedback: ""
|
|
45
|
+
}
|
|
41
46
|
else
|
|
42
47
|
line[:skip] = false
|
|
43
|
-
line[:id] = format(
|
|
48
|
+
line[:id] = format("%<id>02d", {id: c.id.to_i})
|
|
49
|
+
line[:letter] = app.letter[:cross] if c.grade.zero?
|
|
44
50
|
line[:letter] = app.letter[:error] if c.grade < 50.0
|
|
45
|
-
line[:
|
|
51
|
+
line[:letter] = app.letter[:ok] if c.grade.to_i == 100
|
|
52
|
+
line[:grade] = c.grade.to_f
|
|
46
53
|
line[:members] = c.members
|
|
47
54
|
line[:conn_status] = c.conn_status
|
|
48
55
|
line[:moodle_id] = c.get(:tt_moodle_id)
|
|
@@ -60,9 +67,7 @@ class CaseManager
|
|
|
60
67
|
return input unless input.to_s.start_with? Dir.pwd.to_s
|
|
61
68
|
return input if input == Dir.pwd.to_s
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
offset
|
|
65
|
-
output = "#{input[offset, input.size]}"
|
|
66
|
-
output.to_s
|
|
70
|
+
offset = Dir.pwd.length + 1
|
|
71
|
+
input[offset, input.size].to_s
|
|
67
72
|
end
|
|
68
73
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "../application"
|
|
4
4
|
|
|
5
5
|
# CaseManager show method
|
|
6
6
|
class CaseManager
|
|
@@ -17,7 +17,7 @@ class CaseManager
|
|
|
17
17
|
return if mode == :resume
|
|
18
18
|
|
|
19
19
|
@cases.each do |c|
|
|
20
|
-
puts
|
|
20
|
+
puts "=" * 40
|
|
21
21
|
c.show
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require 'fileutils'
|
|
1
|
+
require_relative "../application"
|
|
2
|
+
require "fileutils"
|
|
4
3
|
|
|
5
4
|
module Utils
|
|
6
|
-
# Create the directory if it dosn't exist.
|
|
7
5
|
def ensure_dir(dirname)
|
|
6
|
+
# Create the directory if it dosn't exist.
|
|
8
7
|
unless Dir.exist?(dirname)
|
|
9
8
|
FileUtils.mkdir_p(dirname)
|
|
10
9
|
return false
|
|
@@ -14,15 +13,15 @@ module Utils
|
|
|
14
13
|
|
|
15
14
|
def encode_and_split(encoding, text)
|
|
16
15
|
# Convert text to UTF-8 deleting unknown chars
|
|
17
|
-
text ||=
|
|
18
|
-
flag = [:default,
|
|
19
|
-
return text.encode(
|
|
16
|
+
text ||= "" # Ensure text is not nil
|
|
17
|
+
flag = [:default, "UTF-8"].include? encoding
|
|
18
|
+
return text.encode("UTF-8", invalid: :replace).split("\n") if flag
|
|
20
19
|
|
|
21
20
|
# Convert text from input ENCODING to UTF-8
|
|
22
|
-
ec = Encoding::Converter.new(encoding.to_s,
|
|
21
|
+
ec = Encoding::Converter.new(encoding.to_s, "UTF-8")
|
|
23
22
|
begin
|
|
24
23
|
text = ec.convert(text)
|
|
25
|
-
rescue
|
|
24
|
+
rescue => e
|
|
26
25
|
puts "[ERROR] #{e}: Declare text encoding..."
|
|
27
26
|
puts " run 'command', on: :host, :encoding => 'ISO-8859-1'"
|
|
28
27
|
end
|
|
@@ -30,18 +29,18 @@ module Utils
|
|
|
30
29
|
text.split("\n")
|
|
31
30
|
end
|
|
32
31
|
|
|
33
|
-
def my_execute(cmd, encoding =
|
|
34
|
-
return {
|
|
32
|
+
def my_execute(cmd, encoding = "UTF-8")
|
|
33
|
+
return {exitstatus: 0, content: ""} if Application.instance.debug
|
|
35
34
|
|
|
36
35
|
begin
|
|
37
36
|
text = `#{cmd}`
|
|
38
37
|
exitstatus = $CHILD_STATUS.exitstatus
|
|
39
|
-
rescue
|
|
40
|
-
verbose
|
|
38
|
+
rescue => e
|
|
39
|
+
verbose "!"
|
|
41
40
|
puts("[ERROR] #{e}: Local exec: #{cmd}")
|
|
42
41
|
end
|
|
43
42
|
content = encode_and_split(encoding, text)
|
|
44
|
-
{
|
|
43
|
+
{exitstatus: exitstatus, content: content}
|
|
45
44
|
end
|
|
46
45
|
|
|
47
46
|
def verboseln(text)
|
data/lib/teuton/check/builtin.rb
CHANGED
|
@@ -10,6 +10,10 @@ class Builtin
|
|
|
10
10
|
def method_missing(method)
|
|
11
11
|
@parent.log "BUILTIN #{method}"
|
|
12
12
|
end
|
|
13
|
+
|
|
14
|
+
def respond_to_missing?(_method, *)
|
|
15
|
+
true
|
|
16
|
+
end
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
# Laboratory
|
|
@@ -17,7 +21,7 @@ end
|
|
|
17
21
|
class Laboratory
|
|
18
22
|
def service(param)
|
|
19
23
|
log "BUILTIN service(#{param})"
|
|
20
|
-
@builtin
|
|
24
|
+
@builtin ||= Builtin.new(self)
|
|
21
25
|
@builtin.param = param
|
|
22
26
|
@builtin
|
|
23
27
|
end
|
data/lib/teuton/check/dsl.rb
CHANGED
|
@@ -15,7 +15,7 @@ class Laboratory
|
|
|
15
15
|
@stats[:targets] += 1
|
|
16
16
|
@targetid += 1
|
|
17
17
|
weight = args[:weight] || 1.0
|
|
18
|
-
verboseln format(
|
|
18
|
+
verboseln format("(%03<targetid>d) target %<desc>s", targetid: @targetid, desc: desc)
|
|
19
19
|
verboseln " weight #{weight}"
|
|
20
20
|
end
|
|
21
21
|
alias goal target
|
|
@@ -48,7 +48,7 @@ class Laboratory
|
|
|
48
48
|
def expect(cond)
|
|
49
49
|
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
|
50
50
|
verboseln " expect #{cond} (#{cond.class})"
|
|
51
|
-
verboseln
|
|
51
|
+
verboseln ""
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
##
|
|
@@ -56,7 +56,7 @@ class Laboratory
|
|
|
56
56
|
def expect_one(cond)
|
|
57
57
|
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
|
58
58
|
verboseln " expect_one #{cond} (#{cond.class})"
|
|
59
|
-
verboseln
|
|
59
|
+
verboseln ""
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
##
|
|
@@ -64,7 +64,7 @@ class Laboratory
|
|
|
64
64
|
def expect_none(cond)
|
|
65
65
|
verboseln " alter #{result.alterations}" unless result.alterations.empty?
|
|
66
66
|
verboseln " expect_none #{cond} (#{cond.class})"
|
|
67
|
-
verboseln
|
|
67
|
+
verboseln ""
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
##
|
|
@@ -85,7 +85,7 @@ class Laboratory
|
|
|
85
85
|
# rubocop:disable Style/MissingRespondToMissing
|
|
86
86
|
def method_missing(method)
|
|
87
87
|
a = method.to_s
|
|
88
|
-
instance_eval("get(:#{a[0, a.size - 1]})", __FILE__, __LINE__) if a[a.size - 1] ==
|
|
88
|
+
instance_eval("get(:#{a[0, a.size - 1]})", __FILE__, __LINE__) if a[a.size - 1] == "?"
|
|
89
89
|
end
|
|
90
90
|
# rubocop:enable Style/MissingRespondToMissing
|
|
91
91
|
|
|
@@ -93,8 +93,7 @@ class Laboratory
|
|
|
93
93
|
# Execute Teuton DSL gett keyword
|
|
94
94
|
# Same as get keyword, but show pretty output when used by readme command.
|
|
95
95
|
def gett(option)
|
|
96
|
-
|
|
97
|
-
value
|
|
96
|
+
get(option)
|
|
98
97
|
end
|
|
99
98
|
|
|
100
99
|
##
|
|
@@ -103,12 +102,12 @@ class Laboratory
|
|
|
103
102
|
@stats[:uniques] += 1
|
|
104
103
|
|
|
105
104
|
verboseln " ! Unique value for <#{key}>"
|
|
106
|
-
verboseln
|
|
105
|
+
verboseln ""
|
|
107
106
|
end
|
|
108
107
|
|
|
109
108
|
##
|
|
110
109
|
# Execute Teuton DSL log keyword
|
|
111
|
-
def log(text =
|
|
110
|
+
def log(text = "", type = :info)
|
|
112
111
|
@stats[:logs] += 1
|
|
113
112
|
verboseln " log [#{type}]: " + text.to_s
|
|
114
113
|
end
|
|
@@ -118,8 +117,8 @@ class Laboratory
|
|
|
118
117
|
def set(key, value)
|
|
119
118
|
@stats[:sets] += 1
|
|
120
119
|
|
|
121
|
-
key =
|
|
122
|
-
value =
|
|
120
|
+
key = ":" + key.to_s if key.instance_of? Symbol
|
|
121
|
+
value = ":" + value.to_s if value.instance_of? Symbol
|
|
123
122
|
|
|
124
123
|
@sets[key] = value
|
|
125
124
|
"set(#{key},#{value})"
|