teuton 2.5.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/docs/CHANGELOG.md +2 -0
  3. data/docs/changelog/todo.md +4 -6
  4. data/docs/changelog/v2.6.md +4 -0
  5. data/docs/changelog/v2.7.md +11 -0
  6. data/docs/diagram.md +55 -0
  7. data/docs/learn/02-target.md +37 -12
  8. data/docs/learn/03-remote_hosts.md +1 -1
  9. data/docs/learn/04-config.md +1 -1
  10. data/docs/learn/06-cmd_check.md +4 -6
  11. data/docs/learn/07-target_weight.md +1 -3
  12. data/docs/learn/21-exit_codes.md +9 -16
  13. data/docs/learn/README.md +1 -1
  14. data/lib/teuton/case/case.rb +95 -0
  15. data/lib/teuton/{case_manager/case → case}/close.rb +2 -0
  16. data/lib/teuton/{case_manager/case → case}/config.rb +3 -3
  17. data/lib/teuton/{case_manager/case → case/deprecated}/runner.rb +14 -10
  18. data/lib/teuton/case/deprecated/utils.rb +40 -0
  19. data/lib/teuton/{case_manager/case/dsl/main.rb → case/dsl/all.rb} +0 -2
  20. data/lib/teuton/{case_manager/case → case}/dsl/expect.rb +25 -9
  21. data/lib/teuton/{case_manager/case → case}/dsl/goto.rb +10 -9
  22. data/lib/teuton/{case_manager/case → case}/dsl/log.rb +1 -2
  23. data/lib/teuton/{case_manager/case → case}/dsl/macro.rb +2 -2
  24. data/lib/teuton/{case_manager/case → case}/dsl/send.rb +3 -8
  25. data/lib/teuton/case/execute/execute_base.rb +55 -0
  26. data/lib/teuton/case/execute/execute_local.rb +29 -0
  27. data/lib/teuton/case/execute/execute_manager.rb +56 -0
  28. data/lib/teuton/case/execute/execute_ssh.rb +90 -0
  29. data/lib/teuton/case/execute/execute_telnet.rb +56 -0
  30. data/lib/teuton/{case_manager/case → case}/play.rb +11 -14
  31. data/lib/teuton/case_manager/case_manager.rb +20 -39
  32. data/lib/teuton/case_manager/check_cases.rb +14 -12
  33. data/lib/teuton/case_manager/dsl.rb +7 -9
  34. data/lib/teuton/case_manager/export_manager.rb +19 -6
  35. data/lib/teuton/case_manager/hall_of_fame.rb +9 -10
  36. data/lib/teuton/case_manager/report.rb +11 -9
  37. data/lib/teuton/case_manager/send_manager.rb +17 -0
  38. data/lib/teuton/{report/show.rb → case_manager/show_report.rb} +4 -6
  39. data/lib/teuton/case_manager/utils.rb +2 -43
  40. data/lib/teuton/check/dsl.rb +1 -2
  41. data/lib/teuton/check/laboratory.rb +7 -7
  42. data/lib/teuton/check/show.rb +5 -8
  43. data/lib/teuton/cli.rb +10 -0
  44. data/lib/teuton/readme/dsl.rb +5 -7
  45. data/lib/teuton/readme/lang.rb +3 -2
  46. data/lib/teuton/readme/readme.rb +15 -18
  47. data/lib/teuton/report/formatter/default/array.rb +6 -5
  48. data/lib/teuton/report/formatter/default/txt.rb +1 -0
  49. data/lib/teuton/report/formatter/resume/array.rb +3 -3
  50. data/lib/teuton/report/formatter/resume/html.rb +2 -2
  51. data/lib/teuton/report/report.rb +6 -5
  52. data/lib/teuton/skeleton.rb +8 -10
  53. data/lib/teuton/{application.rb → utils/application.rb} +13 -5
  54. data/lib/teuton/utils/name_file_finder.rb +40 -45
  55. data/lib/teuton/utils/project.rb +73 -0
  56. data/lib/teuton/{case_manager/case → utils}/result/ext_array.rb +5 -5
  57. data/lib/teuton/{case_manager/case → utils}/result/result.rb +10 -8
  58. data/lib/teuton/utils/settings.rb +12 -0
  59. data/lib/teuton/utils/verbose.rb +2 -2
  60. data/lib/teuton/version.rb +1 -1
  61. data/lib/teuton.rb +28 -27
  62. metadata +43 -30
  63. data/lib/teuton/case_manager/case/case.rb +0 -117
  64. data/lib/teuton/case_manager/case/main.rb +0 -7
  65. data/lib/teuton/case_manager/main.rb +0 -3
  66. /data/lib/teuton/{case_manager/case → case}/builtin/main.rb +0 -0
  67. /data/lib/teuton/{case_manager/case → case}/builtin/package.rb +0 -0
  68. /data/lib/teuton/{case_manager/case → case}/builtin/service.rb +0 -0
  69. /data/lib/teuton/{case_manager/case → case}/builtin/teuton_file.rb +0 -0
  70. /data/lib/teuton/{case_manager/case → case}/builtin/teuton_host.rb +0 -0
  71. /data/lib/teuton/{case_manager/case → case}/builtin/user.rb +0 -0
  72. /data/lib/teuton/{case_manager/case → case}/dsl/getset.rb +0 -0
  73. /data/lib/teuton/{case_manager/case → case}/dsl/target.rb +0 -0
  74. /data/lib/teuton/{case_manager/case → case}/dsl/unique.rb +0 -0
  75. /data/lib/teuton/{case_manager/case → utils}/result/ext_compare.rb +0 -0
  76. /data/lib/teuton/{case_manager/case → utils}/result/ext_filter.rb +0 -0
@@ -1,13 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../runner"
3
+ require_relative "../execute/execute_manager"
4
4
 
5
- # Case class -> DSL module:
6
- # * goto
7
- # * run
8
5
  module DSL
9
6
  ##
10
- # DLS run: It's the same as goto :localhost
7
+ # DSL run and goto
8
+ # run: It's the same as goto :localhost
11
9
  # @param command (String)
12
10
  # @param args (Hash)
13
11
  def run(command, args = {})
@@ -17,7 +15,7 @@ module DSL
17
15
  goto(host, args)
18
16
  end
19
17
 
20
- # Run command from the host identify as pHostname
18
+ # Run command from the host identify as "host"
21
19
  # goto :host1, :execute => "command"
22
20
  def goto(host = :localhost, args = {})
23
21
  @result.reset
@@ -27,9 +25,12 @@ module DSL
27
25
  tempfile(args[:tempfile]) if args[:tempfile]
28
26
  @action[:encoding] = args[:encoding] || "UTF-8"
29
27
 
30
- start_time = Time.now
31
- run_cmd_on(host)
32
- @action[:duration] = (Time.now - start_time).round(3)
28
+ ExecuteManager.new(self).call(host)
29
+ @action[:output] = if @result.content.size < 2
30
+ @result.value.clone
31
+ else
32
+ "(#{@result.content.size} lines)"
33
+ end
33
34
  end
34
35
  alias_method :on, :goto
35
36
  end
@@ -1,6 +1,5 @@
1
1
  require "rainbow"
2
- ##
3
- # Define DSL#log function
2
+
4
3
  module DSL
5
4
  ##
6
5
  # Record log message
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../../application"
3
+ require_relative "../../utils/project"
4
4
 
5
5
  # DSL module methods: assert, missing_method
6
6
  module DSL
@@ -9,7 +9,7 @@ module DSL
9
9
  # @param name (String) Macro name
10
10
  # @param input (Hash) Macro params
11
11
  def macro(name, input = {})
12
- macros = Application.instance.macros
12
+ macros = Project.value[:macros]
13
13
  unless macros[name]
14
14
  log("Macro #{name} not found!", :error)
15
15
  return
@@ -1,12 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Case->DSL#
4
- # * send
5
- # * tempfile
6
- # * tempdir
7
- # * remote_tempdir
8
- # * remote_tempfile
9
3
  module DSL
4
+ # * send, tempfile, tempdir, remote_tempdir, remote_tempfile
10
5
  def send(args = {})
11
6
  return if skip?
12
7
 
@@ -52,7 +47,7 @@ module DSL
52
47
  name = "teuton.tmp" if input == :default
53
48
 
54
49
  @action[:tempfile] = File.join(@tmpdir, name)
55
- @action[:remote_tempfile] = File.join(@remote_tmpdir, name)
50
+ @action[:remote_tempfile] = File.join(remote_tempdir, name)
56
51
 
57
52
  @action[:tempfile]
58
53
  end
@@ -66,6 +61,6 @@ module DSL
66
61
  end
67
62
 
68
63
  def remote_tempdir
69
- @remote_tmpdir
64
+ File.join("/", "tmp") # TODO: Remove this?
70
65
  end
71
66
  end
@@ -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
@@ -1,27 +1,22 @@
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
13
12
  return false
14
13
  end
15
14
  start_time = Time.now
16
- if get(:tt_sequence) == true
17
- play_in_sequence
18
- else
19
- play_in_parallel
20
- end
15
+ play_groups_in_sequence
21
16
  fill_report(start_time, Time.now)
22
17
  close_opened_sessions
23
18
  end
24
- alias start play
19
+ alias_method :start, :play
25
20
 
26
21
  def close_opened_sessions
27
22
  @sessions.each_value do |s|
@@ -31,14 +26,16 @@ class Case
31
26
 
32
27
  private
33
28
 
34
- def play_in_parallel
29
+ def play_groups_in_sequence
30
+ verboseln "\n=> Starting case [#{@config.get(:tt_members)}]" if get(:tt_sequence) == true
35
31
  @groups.each do |t|
36
32
  @action[:groupname] = t[:name]
33
+ # TODO: @parent(case).instance_eval(&t[:block])
37
34
  instance_eval(&t[:block])
38
35
  end
39
36
  end
40
37
 
41
- def play_in_sequence
38
+ def play_groups_in_parallel
42
39
  verboseln "Starting case [#{@config.get(:tt_members)}]"
43
40
  @groups.each do |t|
44
41
  verbose "* Processing [#{t[:name]}] "
@@ -1,15 +1,15 @@
1
- require "rainbow"
2
- require "singleton"
3
- require_relative "../application"
1
+ require_relative "../case/case"
4
2
  require_relative "../report/report"
5
- require_relative "../report/show"
3
+ require_relative "../utils/project"
4
+ require_relative "../utils/verbose"
6
5
  require_relative "../utils/configfile_reader"
7
- require_relative "case/case"
8
6
  require_relative "export_manager"
9
- require_relative "main"
7
+ require_relative "send_manager"
8
+ require_relative "show_report"
9
+ require_relative "check_cases"
10
+ require_relative "report"
11
+ require_relative "utils"
10
12
 
11
- # This class does all the job
12
- # Organize the hole job, sending orders to others classes
13
13
  # * initialize
14
14
  # * play
15
15
  # Split into several files:
@@ -18,8 +18,8 @@ require_relative "main"
18
18
  # * case_manager/hall_of_fame
19
19
  # * case_manager/report
20
20
  class CaseManager
21
- include Singleton
22
21
  include Utils
22
+ include Verbose
23
23
  attr_reader :report, :cases
24
24
 
25
25
  def initialize
@@ -28,51 +28,32 @@ class CaseManager
28
28
  @report.filename = "resume"
29
29
  end
30
30
 
31
- ##
32
- # Execute "play" order: Start every single case test
33
- # @param block (Block)
34
31
  def play(&block)
32
+ # Execute "play" order: Start every single case test
35
33
  check_cases!
36
34
  instance_eval(&block)
37
35
  # Run export if user pass option command "--export=json"
38
- i = Application.instance.options["export"]
36
+ i = Project.value[:options]["export"]
39
37
  export(format: i.to_sym) unless i.nil?
40
38
  # Accept "configfile" param REVISE There exists?
41
- i = Application.instance.options["configfile"]
39
+ i = Project.value[:options]["configfile"]
42
40
  export(format: i.to_sym) unless i.nil?
43
41
  end
44
42
 
45
- ##
46
- # Execute "export" order: Export every case report
47
- # @param args (Hash) Export options
48
43
  def export(args = {})
49
- if args.class != Hash
50
- puts Rainbow("[ERROR] Argument error with 'export'!").red
51
- puts Rainbow(" Code : CaseManager#export").red
52
- puts Rainbow(" Line : export #{args}").red
53
- puts Rainbow(" Use : export format: 'txt'").red
54
- puts ""
55
- exit 1
56
- end
57
- ExportManager.run(@report, @cases, args)
44
+ ExportManager.new.call(
45
+ @report,
46
+ @cases,
47
+ args,
48
+ Project.value[:format]
49
+ )
58
50
  end
59
51
 
60
- ##
61
- # Execute "send" order: Send every case report
62
- # @param args (Hash) Send options
63
52
  def send(args = {})
64
- threads = []
65
- puts ""
66
- puts Rainbow("-" * 50).green
67
- puts Rainbow("Sending files...#{args}").color(:green)
68
- @cases.each { |c| threads << Thread.new { c.send(args) } }
69
- threads.each(&:join)
70
- puts Rainbow("Sending finished!").color(:green)
71
- puts Rainbow("-" * 50).green
53
+ SendManager.new.call(@cases, args)
72
54
  end
73
55
 
74
56
  def show(options = {verbose: 1})
75
- verbose = options[:verbose]
76
- ShowReport.new(@report).call(verbose)
57
+ ShowReport.new(@report).call(options[:verbose])
77
58
  end
78
59
  end
@@ -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
- app = Application.instance
10
-
8
+ # Start checking every single case
9
+ app = Project.value
11
10
  # Load configurations from config file
12
- configdata = ConfigFileReader.read(app.config_path)
13
- app.ialias = configdata[:alias]
14
- app.global = configdata[:global]
15
- app.global[:tt_testname] = app.global[:tt_testname] || app.test_name
16
- app.global[:tt_sequence] = false if app.global[:tt_sequence].nil?
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.global[:tt_outdir] || File.join("var", app.global[:tt_testname])
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.config_path)
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 "../application"
1
+ require_relative "../utils/project"
2
2
  require_relative "case_manager"
3
3
 
4
4
  def use(filename)
5
5
  filename += ".rb"
6
- app = Application.instance
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
- app.uses << File.basename(findfiles.first)
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
- Application.instance.macros[name] = {args: args, block: block}
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
- Application.instance.groups << {name: name, block: block}
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)
38
- CaseManager.instance.play(&block)
35
+ # Start test
36
+ CaseManager.new.play(&block)
39
37
  end
40
38
  alias start play