teuton 2.5.0 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
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