teuton 2.10.8 → 2.11.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/README.md +65 -18
- data/docs/commands/README.md +18 -81
- data/docs/commands/check.md +66 -0
- data/docs/commands/config.md +120 -0
- data/docs/commands/help.md +37 -0
- data/docs/commands/new.md +34 -0
- data/docs/commands/readme.md +52 -0
- data/docs/commands/{run-tests.md → run.md} +1 -1
- data/docs/config_file.md +125 -0
- data/docs/devel/README.md +12 -0
- data/docs/dsl/expect.md +2 -2
- data/docs/dsl/run.md +30 -67
- data/docs/install/s-node.md +9 -7
- data/docs/install/t-node.md +18 -19
- data/docs/learn/11-export.md +1 -1
- data/docs/learn/13-feedback.md +1 -1
- data/docs/learn/14-moodle_id.md +4 -4
- data/docs/learn/15-readme.md +14 -8
- data/docs/learn/16-include.md +21 -16
- data/docs/learn/17-alias.md +2 -2
- data/docs/learn/18-log.md +5 -3
- data/docs/learn/19-read_vars.md +7 -3
- data/docs/learn/20-macros.md +6 -4
- data/docs/learn/21-exit_codes.md +3 -3
- data/docs/learn/22-result.md +7 -3
- data/docs/learn/23-test-code.md +17 -7
- data/docs/learn/24-test-sql.md +19 -18
- data/docs/learn/25-expect-result.md +1 -0
- data/docs/learn/26-expect_sequence.md +12 -7
- data/docs/learn/27-run_script.md +11 -5
- data/docs/tutorial/es/nginx/README.md +546 -0
- data/lib/teuton/case/case.rb +0 -2
- data/lib/teuton/case/dsl/expect.rb +2 -2
- data/lib/teuton/case/dsl/log.rb +1 -1
- data/lib/teuton/case/dsl/run.rb +2 -3
- data/lib/teuton/case/dsl/upload.rb +1 -1
- data/lib/teuton/case/execute/execute_base.rb +3 -6
- data/lib/teuton/case/execute/execute_local.rb +5 -2
- data/lib/teuton/case/execute/execute_ssh.rb +0 -1
- data/lib/teuton/case/execute/execute_telnet.rb +0 -2
- data/lib/teuton/case/play.rb +2 -2
- data/lib/teuton/case/result/result.rb +1 -3
- data/lib/teuton/case_manager/case_manager.rb +14 -17
- data/lib/teuton/case_manager/dsl.rb +4 -4
- data/lib/teuton/case_manager/export_manager.rb +22 -17
- data/lib/teuton/case_manager/{check_cases.rb → ext/check_cases.rb} +7 -6
- data/lib/teuton/case_manager/ext/hall_of_fame.rb +28 -0
- data/lib/teuton/case_manager/{report.rb → ext/report.rb} +6 -8
- data/lib/teuton/case_manager/send_manager.rb +1 -0
- data/lib/teuton/case_manager/{show_report.rb → show_resume_report.rb} +12 -26
- data/lib/teuton/case_manager/stats_manager.rb +26 -0
- data/lib/teuton/check/checker.rb +16 -8
- data/lib/teuton/check/main.rb +2 -2
- data/lib/teuton/check/show.rb +3 -3
- data/lib/teuton/cli.rb +3 -2
- data/lib/teuton/readme/dsl/getset.rb +1 -0
- data/lib/teuton/readme/main.rb +2 -2
- data/lib/teuton/readme/readme.rb +2 -2
- data/lib/teuton/report/formatter/default/array.rb +1 -3
- data/lib/teuton/report/formatter/default/markdown.rb +1 -1
- data/lib/teuton/report/formatter/default/txt.rb +1 -1
- data/lib/teuton/report/formatter/default/xml.rb +93 -29
- data/lib/teuton/report/formatter/formatter.rb +2 -1
- data/lib/teuton/report/formatter/resume/array.rb +1 -3
- data/lib/teuton/report/formatter/resume/txt.rb +6 -2
- data/lib/teuton/report/formatter/resume/xml.rb +92 -0
- data/lib/teuton/report/report.rb +1 -1
- data/lib/teuton/utils/config_file_reader.rb +141 -0
- data/lib/teuton/utils/name_file_finder.rb +12 -15
- data/lib/teuton/utils/project.rb +19 -21
- data/lib/teuton/utils/settings.rb +3 -1
- data/lib/teuton/version.rb +1 -1
- data/lib/teuton.rb +11 -10
- metadata +35 -30
- data/docs/commands/check-example.md +0 -53
- data/docs/es/aprender/01-cmd_new.md +0 -27
- data/docs/es/aprender/02-target.md +0 -131
- data/docs/es/aprender/README.md +0 -36
- data/docs/ideas/todo.md +0 -44
- data/docs/install/README.md +0 -38
- data/lib/teuton/case_manager/hall_of_fame.rb +0 -29
- data/lib/teuton/files/README.md +0 -9
- data/lib/teuton/utils/configfile_reader.rb +0 -135
- /data/docs/{ideas → devel}/contributions.md +0 -0
- /data/docs/{ideas → es}/Challenge-Server-Project.md +0 -0
- /data/docs/{ideas → es}/servidor-de-retos.md +0 -0
- /data/docs/{install/modes_of_use.md → modes_of_use.md} +0 -0
- /data/lib/teuton/{case_manager → deprecated}/utils.rb +0 -0
|
@@ -1,40 +1,104 @@
|
|
|
1
|
-
require_relative "
|
|
2
|
-
require_relative "../../../version"
|
|
1
|
+
require_relative "array"
|
|
3
2
|
|
|
4
|
-
class XMLFormatter <
|
|
3
|
+
class XMLFormatter < ArrayFormatter
|
|
5
4
|
def initialize(report)
|
|
6
5
|
super
|
|
7
6
|
@ext = "xml"
|
|
7
|
+
@data = {}
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def process(options = {})
|
|
11
|
-
|
|
12
|
-
w "<teuton
|
|
13
|
-
w "
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
w "#{tab * 2}<line type='log'>#{i}</line>\n"
|
|
20
|
-
next
|
|
21
|
-
end
|
|
22
|
-
w "#{tab * 2}<line>\n"
|
|
23
|
-
w "#{tab * 3}<id>#{i[:id]}</id>\n"
|
|
24
|
-
w "#{tab * 3}<description>#{i[:description]}</description>\n"
|
|
25
|
-
w "#{tab * 3}<command"
|
|
26
|
-
w " tempfile='#{i[:tempfile]}'" if i[:tempfile]
|
|
27
|
-
w ">#{i[:command]}</command>\n"
|
|
28
|
-
w "#{tab * 3}<check>#{i[:check]}</check>\n"
|
|
29
|
-
w "#{tab * 3}<weigth>#{i[:weight]}</weigth>\n"
|
|
30
|
-
w "#{tab * 2}</line>\n"
|
|
31
|
-
end
|
|
32
|
-
w "#{tab}</lines>\n"
|
|
33
|
-
w "#{tab}<tail>\n"
|
|
34
|
-
@tail.each { |key, value| w "#{tab * 2}<#{key}>#{value}</#{key}>\n" }
|
|
35
|
-
w "#{tab}</tail>\n"
|
|
11
|
+
build_data(options)
|
|
12
|
+
w "<teuton>\n"
|
|
13
|
+
w "\n"
|
|
14
|
+
process_config
|
|
15
|
+
process_logs
|
|
16
|
+
process_groups
|
|
17
|
+
process_results
|
|
18
|
+
process_hof
|
|
36
19
|
w "</teuton>\n"
|
|
37
|
-
|
|
38
20
|
deinit
|
|
39
21
|
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def process_config
|
|
26
|
+
w " <configuration>\n"
|
|
27
|
+
@data[:config].sort.each do |key, value|
|
|
28
|
+
w " <#{key}>#{value}</#{key}>\n"
|
|
29
|
+
end
|
|
30
|
+
w " </configuration>\n"
|
|
31
|
+
w "\n"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def process_logs
|
|
35
|
+
return if @data[:logs].empty?
|
|
36
|
+
|
|
37
|
+
w " <logs>\n"
|
|
38
|
+
@data[:logs].each { |line| w " <log>#{line}</log>\n" }
|
|
39
|
+
w " </logs>\n"
|
|
40
|
+
w "\n"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def process_groups
|
|
44
|
+
return if @data[:groups].empty?
|
|
45
|
+
|
|
46
|
+
w " <group>\n"
|
|
47
|
+
@data[:groups].each { |g| process_group g }
|
|
48
|
+
w " </group>\n"
|
|
49
|
+
w "\n"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def process_results
|
|
53
|
+
w " <results>\n"
|
|
54
|
+
@data[:results].sort.each do |key, value|
|
|
55
|
+
w " <#{key}>#{value}</#{key}>\n"
|
|
56
|
+
end
|
|
57
|
+
w " </results>\n"
|
|
58
|
+
w "\n"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def process_hof
|
|
62
|
+
return if @data[:hall_of_fame].empty?
|
|
63
|
+
|
|
64
|
+
w " <hall_of_fame>\n"
|
|
65
|
+
w "| Grade | Amount |\n"
|
|
66
|
+
w "| ----- | ------ |\n"
|
|
67
|
+
@data[:hall_of_fame].each do |grade, amount|
|
|
68
|
+
current = ""
|
|
69
|
+
current = "current='true'" if grade == @data[:results][:grade]
|
|
70
|
+
w " <line #{current}>\n"
|
|
71
|
+
w " <grade>#{grade}</grade>\n"
|
|
72
|
+
w " <amount>#{amount}</amount>\n"
|
|
73
|
+
w " <line>\n"
|
|
74
|
+
end
|
|
75
|
+
w " <hall_of_fame>\n"
|
|
76
|
+
w "\n"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def process_group(group)
|
|
82
|
+
w " <group title='#{group[:title]}'>\n"
|
|
83
|
+
group[:targets].each do |i|
|
|
84
|
+
w " <target id='#{format("%02d", i[:target_id].to_i)}'>\n"
|
|
85
|
+
w " <score>#{i[:score]}</score>\n"
|
|
86
|
+
w " <weight>#{i[:weight]}</weight>\n"
|
|
87
|
+
w " <description>#{i[:description]}</description>\n"
|
|
88
|
+
w " <command>#{i[:command]}</command>\n"
|
|
89
|
+
w " <output>#{i[:output]}</output>\n"
|
|
90
|
+
w " <duration>#{i[:duration]}</duration>\n"
|
|
91
|
+
w " <conn_type>#{i[:conn_type]}</conn_type>\n"
|
|
92
|
+
w " <alterations>#{sanitize(i[:alterations])}</alterations>\n"
|
|
93
|
+
w " <expected>#{i[:expected]}</expected>\n"
|
|
94
|
+
w " <result>#{i[:result]}</result>\n"
|
|
95
|
+
w " </target>\n"
|
|
96
|
+
end
|
|
97
|
+
w " </group>\n"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def sanitize(text)
|
|
101
|
+
# Replace & by &
|
|
102
|
+
text.gsub("&", "&")
|
|
103
|
+
end
|
|
40
104
|
end
|
|
@@ -11,6 +11,7 @@ require_relative "resume/html"
|
|
|
11
11
|
require_relative "resume/json"
|
|
12
12
|
require_relative "resume/markdown"
|
|
13
13
|
require_relative "resume/txt"
|
|
14
|
+
require_relative "resume/xml"
|
|
14
15
|
require_relative "resume/yaml"
|
|
15
16
|
require_relative "moodle_csv_formatter"
|
|
16
17
|
|
|
@@ -29,7 +30,7 @@ module Formatter
|
|
|
29
30
|
resume_json: ResumeJSONFormatter,
|
|
30
31
|
resume_markdown: ResumeMarkdownFormatter,
|
|
31
32
|
resume_txt: ResumeTXTFormatter,
|
|
32
|
-
resume_xml:
|
|
33
|
+
resume_xml: ResumeXMLFormatter,
|
|
33
34
|
resume_yaml: ResumeYAMLFormatter
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -38,9 +38,7 @@ class ResumeArrayFormatter < BaseFormatter
|
|
|
38
38
|
|
|
39
39
|
def build_hof_data
|
|
40
40
|
fame = {}
|
|
41
|
-
|
|
42
|
-
Project.value[:hall_of_fame].each { |line| fame[line[0]] = line[1] }
|
|
43
|
-
end
|
|
41
|
+
Project.value[:hall_of_fame].each { |line| fame[line[0]] = line[1] }
|
|
44
42
|
@data[:hall_of_fame] = fame
|
|
45
43
|
end
|
|
46
44
|
end
|
|
@@ -55,13 +55,13 @@ class ResumeTXTFormatter < ResumeArrayFormatter
|
|
|
55
55
|
st.add_row %w[CASE MEMBERS HOST ERROR]
|
|
56
56
|
@data[:cases].each do |line|
|
|
57
57
|
line[:conn_status].each_pair do |h, e|
|
|
58
|
-
st.add_row [line[:id], line[:members], h, e]
|
|
58
|
+
st.add_row [line[:id], line[:members], h, colorize(e, :red_bright)]
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
return unless my_screen_table.rows.size > 1
|
|
63
63
|
|
|
64
|
-
w "#{colorize("CONN ERRORS", :
|
|
64
|
+
w "#{colorize("CONN ERRORS", :bg_blue)}\n#{my_screen_table}\n\n"
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def process_results
|
|
@@ -100,6 +100,8 @@ class ResumeTXTFormatter < ResumeArrayFormatter
|
|
|
100
100
|
case option
|
|
101
101
|
when :bg_blue
|
|
102
102
|
Rainbow(text).bg(:blue)
|
|
103
|
+
when :bg_red
|
|
104
|
+
Rainbow(text).bg(:red)
|
|
103
105
|
when :blue_bright
|
|
104
106
|
Rainbow(text).blue.bright
|
|
105
107
|
when :bright
|
|
@@ -108,6 +110,8 @@ class ResumeTXTFormatter < ResumeArrayFormatter
|
|
|
108
110
|
Rainbow(text).color(:green)
|
|
109
111
|
when :red
|
|
110
112
|
Rainbow(text).color(:red)
|
|
113
|
+
when :red_bright
|
|
114
|
+
Rainbow(text).red.bright
|
|
111
115
|
else
|
|
112
116
|
puts "[ERROR] ResumeTXTFormatter#colorize option=#{option}"
|
|
113
117
|
exit 1
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require_relative "array"
|
|
2
|
+
|
|
3
|
+
class ResumeXMLFormatter < ResumeArrayFormatter
|
|
4
|
+
MIN_HALL_OF_FAME = 3
|
|
5
|
+
|
|
6
|
+
def initialize(report)
|
|
7
|
+
super
|
|
8
|
+
@ext = "xml"
|
|
9
|
+
@data = {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def process(options = {})
|
|
13
|
+
build_data(options)
|
|
14
|
+
w "<teuton>\n"
|
|
15
|
+
w "\n"
|
|
16
|
+
process_config
|
|
17
|
+
process_cases
|
|
18
|
+
process_conn_errors
|
|
19
|
+
process_results
|
|
20
|
+
process_hof
|
|
21
|
+
w "</teuton>\n"
|
|
22
|
+
deinit
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def process_config
|
|
28
|
+
w " <configuration>\n"
|
|
29
|
+
@data[:config].each do |key, value|
|
|
30
|
+
w(" <#{key}>#{trim(value)}</#{key}>\n")
|
|
31
|
+
end
|
|
32
|
+
w " </configuration>\n"
|
|
33
|
+
w "\n"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def process_cases
|
|
37
|
+
w " <cases>\n"
|
|
38
|
+
@data[:cases].each do |line|
|
|
39
|
+
w " <case id='#{line[:id]}'>\n"
|
|
40
|
+
w " <members>#{line[:members]}</members>\n"
|
|
41
|
+
w " <grade>#{line[:grade]}</grade>\n"
|
|
42
|
+
w " <state>#{line[:letter]}</state>\n"
|
|
43
|
+
w " </case>\n"
|
|
44
|
+
end
|
|
45
|
+
w " </cases>\n"
|
|
46
|
+
w "\n"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def process_conn_errors
|
|
50
|
+
lines = []
|
|
51
|
+
lines << " <conn_errors>"
|
|
52
|
+
@data[:cases].each do |line|
|
|
53
|
+
line[:conn_status].each_pair do |host, error|
|
|
54
|
+
lines << " <conn_error>"
|
|
55
|
+
lines << " <case>#{line[:id]}</case>"
|
|
56
|
+
lines << " <members>#{line[:members]}</members>"
|
|
57
|
+
lines << " <host>#{host}</host>"
|
|
58
|
+
lines << " <error>#{error}</error>"
|
|
59
|
+
lines << " </conn_error>"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
lines << " </conn_errors>"
|
|
63
|
+
|
|
64
|
+
if lines.size > 2
|
|
65
|
+
w lines.join("\n")
|
|
66
|
+
w "\n"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def process_results
|
|
71
|
+
w " <results>\n"
|
|
72
|
+
@data[:results].each do |key, value|
|
|
73
|
+
w(" <#{key}>#{value}</#{key}>\n")
|
|
74
|
+
end
|
|
75
|
+
w " </results>\n"
|
|
76
|
+
w "\n"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def process_hof
|
|
80
|
+
return if @data[:hall_of_fame].size < MIN_HALL_OF_FAME
|
|
81
|
+
|
|
82
|
+
w " <hall_of_fame>\n"
|
|
83
|
+
@data[:hall_of_fame].each do |grade, amount|
|
|
84
|
+
w " <line>\n"
|
|
85
|
+
w " <grade>#{grade}</grade>\n"
|
|
86
|
+
w " <amount>#{amount}</amount>\n"
|
|
87
|
+
w " </line>\n"
|
|
88
|
+
end
|
|
89
|
+
w " </hall_of_fame>\n"
|
|
90
|
+
w "\n"
|
|
91
|
+
end
|
|
92
|
+
end
|
data/lib/teuton/report/report.rb
CHANGED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "yaml"
|
|
3
|
+
|
|
4
|
+
##
|
|
5
|
+
# Read config file content. Available file formats: YAML or JSON
|
|
6
|
+
module ConfigFileReader
|
|
7
|
+
def self.call(filepath)
|
|
8
|
+
return minimum_configuration_with_one_case unless File.exist?(filepath)
|
|
9
|
+
|
|
10
|
+
return read_yaml(filepath) if [".yaml", ".yml"].include? File.extname(filepath)
|
|
11
|
+
|
|
12
|
+
return read_json(filepath) if File.extname(filepath) == ".json"
|
|
13
|
+
|
|
14
|
+
raise "[ERROR] ConfigFileReader.call: <#{filepath}>. Unkown extension!"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.convert_string_keys_to_symbol(input)
|
|
18
|
+
return input if input.class != Hash
|
|
19
|
+
|
|
20
|
+
output = {}
|
|
21
|
+
input.each_pair do |key, value|
|
|
22
|
+
key2 = key
|
|
23
|
+
key2 = key.to_sym if key.class
|
|
24
|
+
value2 = value
|
|
25
|
+
if value.instance_of? Hash
|
|
26
|
+
value2 = convert_string_keys_to_symbol(value)
|
|
27
|
+
elsif value.instance_of? Array
|
|
28
|
+
value2 = []
|
|
29
|
+
value.each { |i| value2 << convert_string_keys_to_symbol(i) }
|
|
30
|
+
end
|
|
31
|
+
output[key2] = value2
|
|
32
|
+
end
|
|
33
|
+
output
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.minimum_configuration_with_one_case
|
|
37
|
+
data = {}
|
|
38
|
+
data[:global] = {}
|
|
39
|
+
data[:alias] = {}
|
|
40
|
+
data[:cases] = [{tt_members: "anonymous"}]
|
|
41
|
+
data
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.is_yaml_file?(filepath)
|
|
45
|
+
extensions = [".yaml", ".YAML", ".yml", ".YML"]
|
|
46
|
+
ext = File.extname(filepath)
|
|
47
|
+
return true if File.file?(filepath) && extensions.include?(ext)
|
|
48
|
+
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.is_json_file?(filepath)
|
|
53
|
+
extensions = [".json", ".JSON"]
|
|
54
|
+
ext = File.extname(filepath)
|
|
55
|
+
return true if File.file?(filepath) && extensions.include?(ext)
|
|
56
|
+
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.read_yaml(filepath)
|
|
61
|
+
begin
|
|
62
|
+
data = YAML.load(File.open(filepath))
|
|
63
|
+
rescue => e
|
|
64
|
+
warn "[ERROR] ConfigFileReader.read_yaml: #{e}"
|
|
65
|
+
warn "[ERROR] Revise file content! <#{filepath}>"
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
data = convert_string_keys_to_symbol(data)
|
|
69
|
+
data[:global] = data[:global] || {}
|
|
70
|
+
data[:alias] = data[:alias] || {}
|
|
71
|
+
data[:cases] = data[:cases] || []
|
|
72
|
+
read_included_files!(filepath, data)
|
|
73
|
+
data
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.read_json(filepath)
|
|
77
|
+
data = JSON.parse(File.read(filepath), symbolize_names: true)
|
|
78
|
+
data = convert_string_keys_to_symbol(data)
|
|
79
|
+
data[:global] = data[:global] || {}
|
|
80
|
+
data[:alias] = data[:alias] || {}
|
|
81
|
+
data[:cases] = data[:cases] || []
|
|
82
|
+
read_included_files!(filepath, data)
|
|
83
|
+
data
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self.read_included_files!(filepath, data)
|
|
87
|
+
return if data[:global][:tt_include].nil?
|
|
88
|
+
|
|
89
|
+
include_dir = data[:global][:tt_include]
|
|
90
|
+
basedir = if include_dir == File.absolute_path(include_dir)
|
|
91
|
+
include_dir
|
|
92
|
+
else
|
|
93
|
+
File.join(File.dirname(filepath), data[:global][:tt_include])
|
|
94
|
+
end
|
|
95
|
+
filepaths = Dir.glob(File.join(basedir, "**/*"))
|
|
96
|
+
filepaths.each { |filepath|
|
|
97
|
+
if File.directory?(filepath)
|
|
98
|
+
next
|
|
99
|
+
elsif is_yaml_file? filepath
|
|
100
|
+
data[:cases] << read_included_yaml_file(filepath)
|
|
101
|
+
elsif is_json_file? filepath
|
|
102
|
+
data[:cases] << read_included_json_file(filepath)
|
|
103
|
+
elsif File.file? filepath
|
|
104
|
+
warn "[WARN] Ignore config file <#{filepath}>. No yaml or json extension!"
|
|
105
|
+
next
|
|
106
|
+
end
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.read_included_yaml_file(filepath)
|
|
111
|
+
begin
|
|
112
|
+
data = YAML.load(File.open(filepath))
|
|
113
|
+
rescue => e
|
|
114
|
+
warn "[ERROR] ConfigFileReader.read_included_yaml: #{e}"
|
|
115
|
+
warn "[ERROR] Loading configuration file! <#{filename}>"
|
|
116
|
+
exit 1
|
|
117
|
+
end
|
|
118
|
+
data[:tt_source_file] = relative_path(filepath)
|
|
119
|
+
convert_string_keys_to_symbol(data)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def self.read_included_json_file(filepath)
|
|
123
|
+
begin
|
|
124
|
+
data = JSON.parse(File.read(filepath), symbolize_names: true)
|
|
125
|
+
rescue => e
|
|
126
|
+
warn "[ERROR] ConfigFileReader.read_included_json: #{e}"
|
|
127
|
+
warn "[ERROR] Loading configuration file! <#{filename}>"
|
|
128
|
+
exit 1
|
|
129
|
+
end
|
|
130
|
+
data[:tt_source_file] = relative_path(filepath)
|
|
131
|
+
convert_string_keys_to_symbol(data)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def self.relative_path(filepath)
|
|
135
|
+
if filepath.start_with?(Dir.pwd)
|
|
136
|
+
filepath[Dir.pwd.length + 1, filepath.length]
|
|
137
|
+
else
|
|
138
|
+
filepath
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -10,8 +10,8 @@ class NameFileFinder
|
|
|
10
10
|
def initialize(options = {})
|
|
11
11
|
@options = options
|
|
12
12
|
@project_path = nil
|
|
13
|
-
@script_path = nil
|
|
14
|
-
@config_path = nil
|
|
13
|
+
@script_path = nil # Path to DSL script file
|
|
14
|
+
@config_path = nil # Path to YAML config file
|
|
15
15
|
@test_name = nil
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -21,14 +21,11 @@ class NameFileFinder
|
|
|
21
21
|
def find_filenames_for(relprojectpath)
|
|
22
22
|
projectpath = File.absolute_path(relprojectpath)
|
|
23
23
|
|
|
24
|
-
# Define:
|
|
25
|
-
# script_path, must contain fullpath to DSL script file
|
|
26
|
-
# config_path, must contain fullpath to YAML config file
|
|
27
24
|
if File.directory?(projectpath)
|
|
28
|
-
# COMPLEX MODE:
|
|
25
|
+
# COMPLEX MODE: main RB file is <start.rb>
|
|
29
26
|
find_filenames_from_directory(projectpath)
|
|
30
27
|
else
|
|
31
|
-
# SIMPLE MODE:
|
|
28
|
+
# SIMPLE MODE: main RB file is We <pathtofile>
|
|
32
29
|
find_filenames_from_rb(projectpath)
|
|
33
30
|
end
|
|
34
31
|
true
|
|
@@ -37,11 +34,11 @@ class NameFileFinder
|
|
|
37
34
|
private
|
|
38
35
|
|
|
39
36
|
def find_filenames_from_directory(folder_path)
|
|
40
|
-
# Find project filenames
|
|
41
|
-
# COMPLEX MODE:
|
|
37
|
+
# Find project filenames into directory <folder path>
|
|
38
|
+
# COMPLEX MODE: main RB file is <start.rb>
|
|
42
39
|
script_path = File.join(folder_path, "start.rb")
|
|
43
40
|
unless File.exist? script_path
|
|
44
|
-
warn Rainbow("[ERROR]
|
|
41
|
+
warn Rainbow("[ERROR] Main script file not found! <#{script_path}>").bright.red
|
|
45
42
|
exit 1
|
|
46
43
|
end
|
|
47
44
|
|
|
@@ -53,8 +50,8 @@ class NameFileFinder
|
|
|
53
50
|
end
|
|
54
51
|
|
|
55
52
|
def find_configfilename_from_directory(folder_path)
|
|
56
|
-
# Find project config filename
|
|
57
|
-
# COMPLEX MODE:
|
|
53
|
+
# Find project config filename into directory <folder path>
|
|
54
|
+
# COMPLEX MODE: By default <config.yaml> is the confing file
|
|
58
55
|
config_path = ""
|
|
59
56
|
|
|
60
57
|
if options["cpath"].nil?
|
|
@@ -76,9 +73,9 @@ class NameFileFinder
|
|
|
76
73
|
# SIMPLE MODE: We use script_path as main RB file
|
|
77
74
|
# This must be fullpath to DSL script file
|
|
78
75
|
if File.extname(script_path) != ".rb"
|
|
79
|
-
warn Rainbow("[ERROR]
|
|
80
|
-
warn Rainbow("
|
|
81
|
-
warn Rainbow("
|
|
76
|
+
warn Rainbow("[ERROR] Main script file not found!").bright.red
|
|
77
|
+
warn Rainbow("[ERROR] Not found <#{script_path}/start.rb>").white
|
|
78
|
+
warn Rainbow("[ERROR] Not found <#{script_path}.rb>").white
|
|
82
79
|
exit 1
|
|
83
80
|
end
|
|
84
81
|
|
data/lib/teuton/utils/project.rb
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
require_relative "name_file_finder"
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# Class is used to store global parameters of the running project
|
|
3
5
|
class Project
|
|
4
6
|
def self.init
|
|
5
7
|
@project = {}
|
|
6
8
|
@project[:running_basedir] = Dir.getwd
|
|
7
9
|
@project[:output_basedir] = "var"
|
|
8
10
|
@project[:name] = "teuton"
|
|
9
|
-
@project[:format] = :txt
|
|
10
|
-
@project[:debug] = false
|
|
11
|
-
@project[:options] = {
|
|
11
|
+
@project[:format] = :txt # Default export format
|
|
12
|
+
@project[:debug] = false # Disable/enable local executions
|
|
13
|
+
@project[:options] = { # Default input options
|
|
12
14
|
"color" => true,
|
|
13
15
|
"lang" => "en",
|
|
14
16
|
"panel" => false,
|
|
15
17
|
"quiet" => false
|
|
16
18
|
}
|
|
17
|
-
@project[:verbose] = true
|
|
18
|
-
@project[:global] = {}
|
|
19
|
+
@project[:verbose] = true # Enable/disable screen outputs
|
|
20
|
+
@project[:global] = {}
|
|
19
21
|
@project[:ialias] = {} # Hash of Internal alias
|
|
20
|
-
@project[:macros] = {}
|
|
21
|
-
@project[:groups] = []
|
|
22
|
-
@project[:uses] = []
|
|
23
|
-
@project[:hall_of_fame] = []
|
|
22
|
+
@project[:macros] = {}
|
|
23
|
+
@project[:groups] = []
|
|
24
|
+
@project[:uses] = []
|
|
25
|
+
@project[:hall_of_fame] = [] # Hall of fame content
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def self.value
|
|
@@ -29,14 +31,6 @@ class Project
|
|
|
29
31
|
|
|
30
32
|
init
|
|
31
33
|
|
|
32
|
-
def self.debug?
|
|
33
|
-
value[:debug]
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def self.name
|
|
37
|
-
value[:name]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
34
|
def self.quiet?
|
|
41
35
|
return true if value[:options]["quiet"]
|
|
42
36
|
return true unless value[:verbose]
|
|
@@ -44,10 +38,6 @@ class Project
|
|
|
44
38
|
false
|
|
45
39
|
end
|
|
46
40
|
|
|
47
|
-
def self.verbose
|
|
48
|
-
value[:verbose]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
41
|
##
|
|
52
42
|
# Preprocess input options:
|
|
53
43
|
# * Convert input case options String to an Array of integers
|
|
@@ -68,4 +58,12 @@ class Project
|
|
|
68
58
|
numbers = value[:options]["case"].split(",")
|
|
69
59
|
value[:options]["case"] = numbers.collect!(&:to_i)
|
|
70
60
|
end
|
|
61
|
+
|
|
62
|
+
def self.relative_path(filepath)
|
|
63
|
+
if filepath.start_with?(Dir.pwd)
|
|
64
|
+
filepath[Dir.pwd.length + 1, filepath.length]
|
|
65
|
+
else
|
|
66
|
+
filepath
|
|
67
|
+
end
|
|
68
|
+
end
|
|
71
69
|
end
|
data/lib/teuton/version.rb
CHANGED
data/lib/teuton.rb
CHANGED
|
@@ -14,21 +14,17 @@ module Teuton
|
|
|
14
14
|
Project.value[:script_path],
|
|
15
15
|
Project.value[:config_path]
|
|
16
16
|
)
|
|
17
|
-
|
|
18
|
-
checker.show_onlyconfig
|
|
19
|
-
else
|
|
20
|
-
checker.show
|
|
21
|
-
end
|
|
17
|
+
checker.show(options["onlyconfig"] || false)
|
|
22
18
|
end
|
|
23
19
|
|
|
24
20
|
def self.run(projectpath, options = {})
|
|
25
21
|
Project.add_input_params(projectpath, options)
|
|
26
|
-
require_dsl_and_script("teuton/case_manager/dsl")
|
|
22
|
+
require_dsl_and_script("teuton/case_manager/dsl")
|
|
27
23
|
end
|
|
28
24
|
|
|
29
25
|
def self.readme(projectpath, options = {})
|
|
30
26
|
Project.add_input_params(projectpath, options)
|
|
31
|
-
require_dsl_and_script("teuton/readme/main")
|
|
27
|
+
require_dsl_and_script("teuton/readme/main")
|
|
32
28
|
readme = Readme.new(
|
|
33
29
|
Project.value[:script_path],
|
|
34
30
|
Project.value[:config_path]
|
|
@@ -36,14 +32,19 @@ module Teuton
|
|
|
36
32
|
readme.show
|
|
37
33
|
end
|
|
38
34
|
|
|
35
|
+
def self.server(projectpath)
|
|
36
|
+
require_relative "teuton/config/server"
|
|
37
|
+
ConfigServer.configure_project(projectpath)
|
|
38
|
+
end
|
|
39
|
+
|
|
39
40
|
private_class_method def self.require_dsl_and_script(dslpath)
|
|
41
|
+
# Load DSL file and then load script file
|
|
40
42
|
require_relative dslpath
|
|
41
43
|
begin
|
|
42
44
|
require_relative Project.value[:script_path]
|
|
43
45
|
rescue => e
|
|
44
|
-
warn e
|
|
45
|
-
warn Rainbow.new("[
|
|
46
|
-
warn Rainbow.new("[ERROR] Syntax Error!").red
|
|
46
|
+
warn Rainbow.new("[ERROR] require_dsl_and_script: <#{e}>").bright.red
|
|
47
|
+
warn Rainbow.new("[ERROR] Reading file #{Project.value[:script_path]}").bright.red
|
|
47
48
|
exit 1
|
|
48
49
|
end
|
|
49
50
|
end
|